diff --git a/.dockerignore b/.dockerignore index 5b123fd0195..58354ff4211 100644 --- a/.dockerignore +++ b/.dockerignore @@ -5,3 +5,8 @@ java/*/target java/*/bin php/vendor releases +/dist/ +/py-vtdb/ +/vthook/ +/bin/ +/vtdataroot/ diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 32f0a000966..b4b82473d97 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -2,3 +2,5 @@ /docker/ @derekperkins @dkhenry /helm/ @derekperkins @dkhenry +/config/mycnf/ @morgo +/go/vt/mysqlctl/mysqld.go @morgo diff --git a/.github/bootstrap.sh b/.github/bootstrap.sh deleted file mode 100755 index f02bffd1f1b..00000000000 --- a/.github/bootstrap.sh +++ /dev/null @@ -1,175 +0,0 @@ -#!/bin/bash -# shellcheck disable=SC2164 - -# Copyright 2019 The Vitess Authors. -# -# 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 is a next-gen bootstrap which skips Python and Java tests, -# and does not use the VTROOT/VTTOP layout. -# -# My original intention was to use the same bootstrap.sh and gate -# for new features, but it has turned out to be difficult to do, -# due to the way that Docker cache works in the CI environment. - -function fail() { - echo "ERROR: $1" - exit 1 -} - -[[ "$(dirname "$0")" = "." ]] || fail "bootstrap.sh must be run from its current directory" - -# Create main directories. - -VTROOT="$PWD" - -mkdir -p dist -mkdir -p bin -mkdir -p lib -mkdir -p vthook - -source ./dev.env - -go version &>/dev/null || fail "Go is not installed or is not on \$PATH" -goversion_min 1.12 || fail "Go is not version 1.12+" - -# Set up required soft links. -# TODO(mberlin): Which of these can be deleted? -ln -snf "$VTROOT/py" "$VTROOT/py-vtdb" -ln -snf "$VTROOT/go/vt/zkctl/zksrv.sh" "$VTROOT/bin/zksrv.sh" -ln -snf "$VTROOT/test/vthook-test.sh" "$VTROOT/vthook/test.sh" -ln -snf "$VTROOT/test/vthook-test_backup_error" "$VTROOT/vthook/test_backup_error" -ln -snf "$VTROOT/test/vthook-test_backup_transform" "$VTROOT/vthook/test_backup_transform" - -# git hooks are only required if someone intends to contribute. - -echo "creating git hooks" -mkdir -p "$VTROOT/.git/hooks" -ln -sf "$VTROOT/misc/git/pre-commit" "$VTROOT/.git/hooks/pre-commit" -ln -sf "$VTROOT/misc/git/commit-msg" "$VTROOT/.git/hooks/commit-msg" -git config core.hooksPath "$VTROOT/.git/hooks" - -# install_dep is a helper function to generalize the download and installation of dependencies. -# -# If the installation is successful, it puts the installed version string into -# the $dist/.installed_version file. If the version has not changed, bootstrap -# will skip future installations. -function install_dep() { - if [[ $# != 4 ]]; then - fail "install_dep function requires exactly 4 parameters (and not $#). Parameters: $*" - fi - local name="$1" - local version="$2" - local dist="$3" - local install_func="$4" - - version_file="$dist/.installed_version" - if [[ -f "$version_file" && "$(cat "$version_file")" == "$version" ]]; then - echo "skipping $name install. remove $dist to force re-install." - return - fi - - echo "installing $name $version" - - # shellcheck disable=SC2064 - trap "fail '$name build failed'; exit 1" ERR - - # Cleanup any existing data and re-create the directory. - rm -rf "$dist" - mkdir -p "$dist" - - # Change $CWD to $dist before calling "install_func". - pushd "$dist" >/dev/null - # -E (same as "set -o errtrace") makes sure that "install_func" inherits the - # trap. If here's an error, the trap will be called which will exit this - # script. - set -E - $install_func "$version" "$dist" - set +E - popd >/dev/null - - trap - ERR - - echo "$version" > "$version_file" -} - - -# -# 1. Installation of dependencies. -# - -# Wrapper around the `arch` command which plays nice with OS X -function get_arch() { - case $(uname) in - Linux) arch;; - Darwin) uname -m;; - esac -} - -# Install protoc. -function install_protoc() { - local version="$1" - local dist="$2" - - case $(uname) in - Linux) local platform=linux;; - Darwin) local platform=osx;; - esac - - case $(get_arch) in - aarch64) local target=aarch_64;; - x86_64) local target=x86_64;; - *) echo "ERROR: unsupported architecture"; exit 1;; - esac - - wget https://github.com/protocolbuffers/protobuf/releases/download/v$version/protoc-$version-$platform-${target}.zip - unzip "protoc-$version-$platform-${target}.zip" - ln -snf "$dist/bin/protoc" "$VTROOT/bin/protoc" -} -protoc_ver=3.6.1 -install_dep "protoc" "$protoc_ver" "$VTROOT/dist/vt-protoc-$protoc_ver" install_protoc - -# Download and install etcd, link etcd binary into our root. -function install_etcd() { - local version="$1" - local dist="$2" - - case $(uname) in - Linux) local platform=linux; local ext=tar.gz;; - Darwin) local platform=darwin; local ext=zip;; - esac - - case $(get_arch) in - aarch64) local target=arm64;; - x86_64) local target=amd64;; - *) echo "ERROR: unsupported architecture"; exit 1;; - esac - - download_url=https://github.com/coreos/etcd/releases/download - file="etcd-${version}-${platform}-${target}.${ext}" - - wget "$download_url/$version/$file" - if [ "$ext" = "tar.gz" ]; then - tar xzf "$file" - else - unzip "$file" - fi - rm "$file" - ln -snf "$dist/etcd-${version}-${platform}-${target}/etcd" "$VTROOT/bin/etcd" -} - -# Install etcd if not detected -which etcd || install_dep "etcd" "v3.3.10" "$VTROOT/dist/etcd" install_etcd - -echo -echo "bootstrap finished" diff --git a/.github/workflows/check_formatting.yml b/.github/workflows/check_formatting.yml new file mode 100644 index 00000000000..7233082da38 --- /dev/null +++ b/.github/workflows/check_formatting.yml @@ -0,0 +1,21 @@ +name: check_formatting +on: [pull_request] +jobs: + + build: + name: Check Formatting + runs-on: ubuntu-latest + steps: + + - name: Set up Go + uses: actions/setup-go@v1 + with: + go-version: 1.13 + + - name: Check out code + uses: actions/checkout@v2 + + - name: Run go fmt + run: | + gofmt -l . | grep -vF vendor/ && exit 1 || echo "All files formatted correctly" + diff --git a/.github/workflows/e2e-test-cluster.yml b/.github/workflows/check_make_parser.yml similarity index 55% rename from .github/workflows/e2e-test-cluster.yml rename to .github/workflows/check_make_parser.yml index 969008305ef..4f89fe56c9c 100644 --- a/.github/workflows/e2e-test-cluster.yml +++ b/.github/workflows/check_make_parser.yml @@ -1,9 +1,9 @@ -name: e2e Test Cluster +name: check_make_parser on: [push, pull_request] jobs: build: - name: Build + name: Check Make Parser runs-on: ubuntu-latest steps: @@ -13,10 +13,11 @@ jobs: go-version: 1.13 - name: Check out code - uses: actions/checkout@v1 + uses: actions/checkout@v2 - name: Get dependencies run: | + sudo apt-get update sudo apt-get install -y mysql-server mysql-client make unzip g++ etcd curl git wget sudo service mysql stop sudo service etcd stop @@ -24,18 +25,11 @@ jobs: sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld go mod download - - name: Run bootstrap.sh + - name: Run make minimaltools run: | - echo "Copying new bootstrap over location of legacy one." - cp .github/bootstrap.sh . - ./bootstrap.sh + make minimaltools - - name: Build + - name: check_make_parser run: | - GOBIN=$PWD/bin make build + tools/check_make_parser.sh - - name: Run e2e test cluster - run: | - export PATH=$PWD/bin:$PATH - source ./dev.env - VTDATAROOT=/tmp/vtdataroot VTTOP=$PWD VTROOT=$PWD tools/e2e_test_cluster.sh diff --git a/.github/workflows/check_make_visitor.yml b/.github/workflows/check_make_visitor.yml new file mode 100644 index 00000000000..68d8660ba84 --- /dev/null +++ b/.github/workflows/check_make_visitor.yml @@ -0,0 +1,35 @@ +name: check_make_visitor +on: [push, pull_request] +jobs: + + build: + name: Check Make Visitor + runs-on: ubuntu-latest + steps: + + - name: Set up Go + uses: actions/setup-go@v1 + with: + go-version: 1.13 + + - name: Check out code + uses: actions/checkout@v2 + + - name: Get dependencies + run: | + sudo apt-get update + sudo apt-get install -y mysql-server mysql-client make unzip g++ etcd curl git wget + sudo service mysql stop + sudo service etcd stop + sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/ + sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld + go mod download + + - name: Run make minimaltools + run: | + make minimaltools + + - name: check_make_visitor + run: | + misc/git/hooks/visitorgen + diff --git a/.github/workflows/cluster_endtoend.yml b/.github/workflows/cluster_endtoend.yml new file mode 100644 index 00000000000..1761630018b --- /dev/null +++ b/.github/workflows/cluster_endtoend.yml @@ -0,0 +1,46 @@ +name: cluster_endtoend +on: [push, pull_request] +jobs: + + build: + runs-on: ubuntu-latest + strategy: + matrix: + name: [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] + + steps: + - name: Set up Go + uses: actions/setup-go@v1 + with: + go-version: 1.13 + + - name: Check out code + uses: actions/checkout@v2 + + - name: Get dependencies + run: | + sudo apt-get update + sudo apt-get install -y mysql-server mysql-client make unzip g++ etcd curl git wget eatmydata + sudo service mysql stop + sudo service etcd stop + sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/ + sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld + go mod download + wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb + sudo apt-get install -y gnupg2 + sudo dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb + sudo apt-get update + sudo apt-get install percona-xtrabackup-24 + + - name: Installing zookeeper and consul + run: | + # Only running for shard 18 and 24 where we need to install consul and zookeeper + if [[ ${{matrix.name}} == 18 || ${{matrix.name}} == 24 ]]; then + make tools + fi + + - name: sharded cluster_endtoend + run: | + source build.env + eatmydata -- go run test.go -docker=false -print-log -shard ${{matrix.name}} + diff --git a/.github/workflows/cluster_vtctl_web.yml b/.github/workflows/cluster_vtctl_web.yml new file mode 100644 index 00000000000..82597559b0e --- /dev/null +++ b/.github/workflows/cluster_vtctl_web.yml @@ -0,0 +1,22 @@ +name: cluster_vtctl_web +on: [push, pull_request] +jobs: + + build: + name: cluster vtctl web + runs-on: ubuntu-latest + steps: + + - name: Set up Go + uses: actions/setup-go@v1 + with: + go-version: 1.13 + + - name: Check out code + uses: actions/checkout@v2 + + - name: Run vtctl web + run: | + # Running web test inside docker + go run test.go -docker=true -print-log -shard 10 + diff --git a/.github/workflows/create_release.yml b/.github/workflows/create_release.yml new file mode 100644 index 00000000000..4759963a66c --- /dev/null +++ b/.github/workflows/create_release.yml @@ -0,0 +1,40 @@ +# This creates a {tar.gz,deb,rpm} file and uploads it to a release. +# To trigger this, create a new release.. but make sure that you publish +# it immediately and do not save it as a DRAFT. + +name: Release +on: + release: + types: [created] + +jobs: + build: + name: Create Release + runs-on: ubuntu-latest + steps: + + - name: Set up Go + uses: actions/setup-go@v1 + with: + go-version: 1.12 + + - name: Check out code + uses: actions/checkout@v2 + + - name: Get dependencies + run: | + sudo apt-get update + sudo apt-get install -y make ruby ruby-dev + go mod download + sudo gem install --no-ri --no-rdoc fpm + + - name: Make Packages + run: | + ./tools/make-release-packages.sh + + - name: Upload Files + uses: csexton/release-asset-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + pattern: "releases/*.{tar.gz,rpm,deb}" + diff --git a/.github/workflows/e2e_race.yml b/.github/workflows/e2e_race.yml new file mode 100644 index 00000000000..3909974b1ce --- /dev/null +++ b/.github/workflows/e2e_race.yml @@ -0,0 +1,34 @@ +name: e2e_race +on: [push, pull_request] +jobs: + + build: + name: End-to-End Test (Race) + runs-on: ubuntu-latest + steps: + + - name: Set up Go + uses: actions/setup-go@v1 + with: + go-version: 1.13 + + - name: Check out code + uses: actions/checkout@v2 + + - name: Get dependencies + run: | + sudo apt-get update + sudo apt-get install -y mysql-server mysql-client make unzip g++ etcd curl git wget + sudo service mysql stop + sudo service etcd stop + sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/ + sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld + go mod download + + - name: Run make minimaltools + run: | + make minimaltools + + - name: e2e_race + run: | + make e2e_test_race diff --git a/.github/workflows/local-example.yml b/.github/workflows/endtoend.yml similarity index 60% rename from .github/workflows/local-example.yml rename to .github/workflows/endtoend.yml index 03a358d8161..37f2c866343 100644 --- a/.github/workflows/local-example.yml +++ b/.github/workflows/endtoend.yml @@ -1,9 +1,9 @@ -name: Local Example +name: endtoend on: [push, pull_request] jobs: build: - name: Build + name: End-to-End Test runs-on: ubuntu-latest steps: @@ -13,10 +13,11 @@ jobs: go-version: 1.13 - name: Check out code - uses: actions/checkout@v1 + uses: actions/checkout@v2 - name: Get dependencies run: | + sudo apt-get update sudo apt-get install -y mysql-server mysql-client make unzip g++ etcd curl git wget sudo service mysql stop sudo service etcd stop @@ -24,18 +25,14 @@ jobs: sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld go mod download - - name: Run bootstrap.sh + - name: Run make minimaltools run: | - echo "Copying new bootstrap over location of legacy one." - cp .github/bootstrap.sh . - ./bootstrap.sh + make minimaltools - name: Build run: | - GOBIN=$PWD/bin make build + make build - - name: Run Local Example + - name: endtoend run: | - export PATH=$PWD/bin:$PATH - VTDATAROOT=/tmp/vtdataroot VTTOP=$PWD VTROOT=$PWD test/local_example.sh - + tools/e2e_test_runner.sh diff --git a/.github/workflows/local_example.yml b/.github/workflows/local_example.yml new file mode 100644 index 00000000000..c702a9684aa --- /dev/null +++ b/.github/workflows/local_example.yml @@ -0,0 +1,51 @@ +name: local_example +on: [push, pull_request] +jobs: + + build: + name: Local Example on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest] + + steps: + + - name: Set up Go + uses: actions/setup-go@v1 + with: + go-version: 1.13 + + - name: Check out code + uses: actions/checkout@v2 + + - name: Get dependencies + run: | + if [ ${{matrix.os}} = "ubuntu-latest" ]; then + sudo apt-get update + sudo apt-get install -y mysql-server mysql-client make unzip g++ etcd curl git wget eatmydata + sudo service mysql stop + sudo service etcd stop + sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/ + sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld + elif [ ${{matrix.os}} = "macos-latest" ]; then + brew install mysql@5.7 make unzip etcd curl git wget + fi + go mod download + + - name: Run make minimaltools + run: | + make minimaltools + + - name: Build + run: | + make build + + - name: local_example + run: | + if [ ${{matrix.os}} = "macos-latest" ]; then + export PATH="/usr/local/opt/mysql@5.7/bin:$PATH" + fi + # Make sure that testing is entirely non-reliant on config + mv config config-moved + eatmydata -- test/local_example.sh diff --git a/.github/workflows/misc_test_docker.yml b/.github/workflows/misc_test_docker.yml new file mode 100644 index 00000000000..fd617e46b34 --- /dev/null +++ b/.github/workflows/misc_test_docker.yml @@ -0,0 +1,20 @@ +name: misc test +on: [push, pull_request] +jobs: + + build: + name: Misc Test + runs-on: ubuntu-latest + steps: + + - name: Set up Go + uses: actions/setup-go@v1 + with: + go-version: 1.13 + + - name: Check out code + uses: actions/checkout@v2 + + - name: Run Misc test which requires docker + run: | + go run test.go -docker=true -shard 25 \ No newline at end of file diff --git a/.github/workflows/sonar_analysis.yml b/.github/workflows/sonar_analysis.yml new file mode 100644 index 00000000000..f901499a853 --- /dev/null +++ b/.github/workflows/sonar_analysis.yml @@ -0,0 +1,53 @@ +name: sonar_analysis +on: + push: + branches: + - 'master' +jobs: + + build: + runs-on: ubuntu-latest + + steps: + - name: Set up Go + uses: actions/setup-go@v1 + with: + go-version: 1.13 + + - name: Check out code + uses: actions/checkout@v2 + + - name: Get dependencies + run: | + sudo apt-get update + sudo apt-get install -y mysql-server mysql-client make unzip g++ etcd curl git wget eatmydata + sudo service mysql stop + sudo service etcd stop + sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/ + sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld + go mod download + + - name: Execute unit test and cluster endtoend test + run: | + eatmydata -- ./tools/all_test_for_coverage.sh + mkdir report + cp /tmp/*.out ./report/. + + - name: Analyse sonar + run: | + export SONAR_SCANNER_VERSION=4.2.0.1873 + export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION-linux + curl --create-dirs -sSLo $HOME/.sonar/sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$SONAR_SCANNER_VERSION-linux.zip + unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/ + export PATH=$SONAR_SCANNER_HOME/bin:$PATH + export SONAR_SCANNER_OPTS="-server" + + sonar-scanner \ + -Dsonar.projectKey=vitessio \ + -Dsonar.organization=vitess \ + -Dsonar.host.url=https://sonarcloud.io \ + -Dsonar.login=${SONAR_TOKEN} \ + -Dsonar.go.coverage.reportPaths=report/*.out + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml new file mode 100644 index 00000000000..72f851beb82 --- /dev/null +++ b/.github/workflows/unit.yml @@ -0,0 +1,89 @@ +name: unit +on: [push, pull_request] +jobs: + + build: + runs-on: ubuntu-latest + strategy: + matrix: + name: [percona56, mysql57, mysql80, mariadb101, mariadb102, mariadb103] + + steps: + - name: Set up Go + uses: actions/setup-go@v1 + with: + go-version: 1.13 + + - name: Check out code + uses: actions/checkout@v2 + + - name: Get dependencies + run: | + export DEBIAN_FRONTEND="noninteractive" + sudo apt-get update + + if [ ${{matrix.name}} = "mysql57" ]; then + sudo apt-get install -y mysql-server mysql-client + else + # Uninstall likely installed MySQL first + sudo systemctl stop apparmor + sudo DEBIAN_FRONTEND="noninteractive" apt-get remove -y --purge mysql-server mysql-client mysql-common + sudo apt-get -y autoremove + sudo apt-get -y autoclean + sudo deluser mysql + sudo rm -rf /var/lib/mysql + sudo rm -rf /etc/mysql + + if [ ${{matrix.name}} = "percona56" ]; then + sudo rm -rf /var/lib/mysql + sudo apt install -y gnupg2 + wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb + sudo dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb + sudo apt update + sudo DEBIAN_FRONTEND="noninteractive" apt-get install -y percona-server-server-5.6 percona-server-client-5.6 + elif [ ${{matrix.name}} = "mysql80" ]; then + wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.14-1_all.deb + echo mysql-apt-config mysql-apt-config/select-server select mysql-8.0 | sudo debconf-set-selections + sudo DEBIAN_FRONTEND="noninteractive" dpkg -i mysql-apt-config* + sudo apt-get update + sudo DEBIAN_FRONTEND="noninteractive" apt-get install -y mysql-server mysql-client + elif [ ${{matrix.name}} = "mariadb101" ]; then + sudo apt-get install -y software-properties-common + sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8 + sudo add-apt-repository 'deb [arch=amd64,arm64,ppc64el] http://nyc2.mirrors.digitalocean.com/mariadb/repo/10.1/ubuntu bionic main' + sudo apt update + sudo DEBIAN_FRONTEND="noninteractive" apt install -y mariadb-server + elif [ ${{matrix.name}} = "mariadb102" ]; then + sudo apt-get install -y software-properties-common + sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8 + sudo add-apt-repository 'deb [arch=amd64,arm64,ppc64el] http://nyc2.mirrors.digitalocean.com/mariadb/repo/10.2/ubuntu bionic main' + sudo apt update + sudo DEBIAN_FRONTEND="noninteractive" apt install -y mariadb-server + elif [ ${{matrix.name}} = "mariadb103" ]; then + sudo apt-get install -y software-properties-common + sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8 + sudo add-apt-repository 'deb [arch=amd64,arm64,ppc64el] http://nyc2.mirrors.digitalocean.com/mariadb/repo/10.3/ubuntu bionic main' + sudo apt update + sudo DEBIAN_FRONTEND="noninteractive" apt install -y mariadb-server + fi + fi + + sudo apt-get install -y make unzip g++ curl git wget ant openjdk-8-jdk eatmydata + sudo service mysql stop + sudo bash -c "echo '/usr/sbin/mysqld { }' > /etc/apparmor.d/usr.sbin.mysqld" # https://bugs.launchpad.net/ubuntu/+source/mariadb-10.1/+bug/1806263 + sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/ + sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld || echo "could not remove mysqld profile" + + mkdir -p dist bin + curl -L https://github.com/coreos/etcd/releases/download/v3.3.10/etcd-v3.3.10-linux-amd64.tar.gz | tar -zxC dist + mv dist/etcd-v3.3.10-linux-amd64/{etcd,etcdctl} bin/ + + go mod download + + - name: Run make tools + run: | + make tools + + - name: unit + run: | + eatmydata -- make unit_test diff --git a/.github/workflows/unit_race.yml b/.github/workflows/unit_race.yml new file mode 100644 index 00000000000..96219e5991c --- /dev/null +++ b/.github/workflows/unit_race.yml @@ -0,0 +1,38 @@ +name: unit_race +on: [push, pull_request] +jobs: + + build: + name: Unit Test (Race) + runs-on: ubuntu-latest + steps: + + - name: Set up Go + uses: actions/setup-go@v1 + with: + go-version: 1.13 + + - name: Check out code + uses: actions/checkout@v2 + + - name: Get dependencies + run: | + sudo apt-get update + sudo apt-get install -y mysql-server mysql-client make unzip g++ curl git wget eatmydata + sudo service mysql stop + sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/ + sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld + + mkdir -p dist bin + curl -L https://github.com/coreos/etcd/releases/download/v3.3.10/etcd-v3.3.10-linux-amd64.tar.gz | tar -zxC dist + mv dist/etcd-v3.3.10-linux-amd64/{etcd,etcdctl} bin/ + + go mod download + + - name: Run make tools + run: | + make tools + + - name: unit_race + run: | + eatmydata -- make unit_test_race diff --git a/.gitignore b/.gitignore index 86b6f1b3850..57701a9c309 100644 --- a/.gitignore +++ b/.gitignore @@ -30,9 +30,6 @@ tags # C build dirs **/build -# site-local example files -/examples/kubernetes/config.sh - # generated protobuf files /go/vt/.proto.tmp @@ -79,3 +76,12 @@ releases # Vagrant .vagrant + +/dist/ +/py-vtdb +/vthook/ +/bin/ +/vtdataroot/ + +.scannerwork +report \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 733f8213a21..00000000000 --- a/.travis.yml +++ /dev/null @@ -1,61 +0,0 @@ -# Travis CI configuration for Vitess. -# -# Note that we have our own test runner written in Go (test.go) which downloads -# our bootstrap Docker image and runs all tests within Docker. -# This solution is slower than running the tests natively, but has the -# advantage that we do not have to install (and cache) any dependencies within -# Travis itself. -# -# For the record, we expect the following overhead per Travis build: -# - 20 seconds Travis starting up the VM. -# - Up to 2 minutes to pull the Docker image. -# - More than a minute to run "make build" and cache the result as temporary -# Docker image. -# -# In total, it will always take up to 4 minutes until the environment is -# bootstrapped and the first test can be run. -# -# Open TODOs: -# - Re-add travis/check_make_proto.sh, ideally as part of test/config.json. -# - Add a presubmit which checks that if bootstrap has changed, and docker image is out of date. - -# sudo is required because we run Docker in our builds. -# See: https://docs.travis-ci.com/user/docker/ -sudo: required - -services: - - docker - -language: go -go: - - 1.12.x -go_import_path: vitess.io/vitess -env: - global: - # Run go build and test with -p 4 (i.e. up to 4 packages are compiled/tested in parallel). - # As of 07/2015 this value works best in a Travis CI container. - # TODO(mberlin): This will probably not be passed through to Docker. Verify and fix this. - - VT_GO_PARALLEL_VALUE=4 - # Note: The per test timeout must always be < 10 minutes because test.go - # does not produce any log output while running and Travis kills a - # build after 10 minutes without log output. - # See: https://docs.travis-ci.com/user/customizing-the-build#Build-Timeouts - # To diagnose stuck tests, add "-follow" to TEST_FLAGS below. Then test.go - # will print the test's output. - - TEST_FLAGS="-docker -use_docker_cache -timeout=8m -print-log" - matrix: - # NOTE: Travis CI schedules up to 5 tests simultaneously. - # All our tests should be spread out as evenly as possible across these 5 slots. - # We should always utilize all 5 slots because the cost of the setup is high (up to four minutes). - - TEST_MATRIX="-shard 0" - - TEST_MATRIX="-shard 1" - - TEST_MATRIX="-shard 2" - - TEST_MATRIX="-shard 3" - - TEST_MATRIX="-shard 4" -script: - - go run test.go $TEST_FLAGS $TEST_MATRIX - # Uncomment the next line to verify the GOMAXPROCS value (should be 2 as of 09/2017). - # - ./docker/test/run.sh mysql57 'go run travis/log_gomaxprocs.go' -notifications: - slack: - secure: S9n4rVWuEvSaF9RZUIx3Nkc2ycpM254zmalyMMbT5EmV1Xz6Zww2FL39RR5d57zsZ2M8GVW5n9uB8Bx57mr+L/wClEltzknYr7MA2/yYNMo5iK83tdQtNNw5U+dZG9/Plhlm4n883lcw9aZOyotNcLg2zBsd48Y74olk4NdmSfo= diff --git a/ADOPTERS.md b/ADOPTERS.md index 871f12640a8..d1e5329121f 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -4,7 +4,7 @@ This is an alphabetical list of known adopters of Vitess. Some have already gone * [BetterCloud](https://bettercloud.com) * [CloudSigma](https://www.cloudsigma.com/) * [FlipKart](https://flipkart.com) -* [GitHub](http://github.com/) +* [GitHub](https://github.com/) * [HubSpot](https://product.hubspot.com/) * [JD](https://jd.com/) * [New Relic](https://newrelic.com) diff --git a/MAINTAINERS.md b/MAINTAINERS.md index a11a8e6fc83..4ac0a3104f5 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -2,7 +2,7 @@ This page lists all active maintainers and their areas of expertise. This can be The following is the full list, alphabetically ordered. -* Andres Taylor ([systay](https://github.com/systay)) antaylor@squareup.com +* Andres Taylor ([systay](https://github.com/systay)) andres@planetscale.com * Anthony Yeh ([enisoc](https://github.com/enisoc)) enisoc@planetscale.com * Dan Kozlowski ([dkhenry](https://github.com/dkhenry)) koz@planetscale.com * David Weitzman ([dweitzman](https://github.com/dweitzman)) dweitzman@pinterest.com @@ -10,10 +10,10 @@ The following is the full list, alphabetically ordered. * Derek Perkins ([derekperkins](https://github.com/derekperkins)) derek@nozzle.io * Harshit Gangal ([harshit-gangal](https://github.com/harshit-gangal)) harshit.gangal@gmail.com * Jon Tirsen ([tirsen](https://github.com/tirsen)) jontirsen@squareup.com -* Leo X. Lin ([leoxlin](https://github.com/leoxlin)) llin@hubspot.com * Michael Demmer ([demmer](https://github.com/demmer)) mdemmer@slack-corp.com * Michael Pawliszyn ([mpawliszyn](https://github.com/mpawliszyn)) mikepaw@squareup.com * Morgan Tocker ([morgo](https://github.com/morgo)) morgan@planetscale.com +* Paul Hemberger ([pH14](https://github.com/pH14)) phemberger@hubspot.com * Rafael Chacon ([rafael](https://github.com/rafael)) rchacon@slack-corp.com * Sugu Sougoumarane ([sougou](https://github.com/sougou)) sougou@planetscale.com @@ -35,7 +35,7 @@ sougou, dweitzman, deepthi, systay deepthi, rafael, enisoc ### Java -mpawliszyn, leoxlin, harshit-gangal +mpawliszyn, pH14, harshit-gangal ### Kubernetes derekperkins, dkhenry, enisoc diff --git a/Makefile b/Makefile index 24eab88c988..6c8618fbed5 100644 --- a/Makefile +++ b/Makefile @@ -14,11 +14,16 @@ MAKEFLAGS = -s +export GOBIN=$(PWD)/bin +export GO111MODULE=on +export GODEBUG=tls13=0 +export REWRITER=go/vt/sqlparser/rewriter.go + # Disabled parallel processing of target prerequisites to avoid that integration tests are racing each other (e.g. for ports) and may fail. # Since we are not using this Makefile for compilation, limiting parallelism will not increase build time. .NOTPARALLEL: -.PHONY: all build build_web test clean unit_test unit_test_cover unit_test_race integration_test proto proto_banner site_test site_integration_test docker_bootstrap docker_test docker_unit_test java_test reshard_tests e2e_test e2e_test_race +.PHONY: all build build_web install test clean unit_test unit_test_cover unit_test_race integration_test proto proto_banner site_test site_integration_test docker_bootstrap docker_test docker_unit_test java_test reshard_tests e2e_test e2e_test_race minimaltools tools all: build @@ -33,13 +38,16 @@ ifdef VT_EXTRA_BUILD_FLAGS export EXTRA_BUILD_FLAGS := $(VT_EXTRA_BUILD_FLAGS) endif -# Link against the MySQL library in $VT_MYSQL_ROOT if it's specified. -ifdef VT_MYSQL_ROOT -# Clutter the env var only if it's a non-standard path. - ifneq ($(VT_MYSQL_ROOT),/usr) - CGO_LDFLAGS += -L$(VT_MYSQL_ROOT)/lib - endif -endif +# This target needs to be manually run every time any file within web/vtctld2/app is modified to regenerate rice-box.go +embed_static: + cd go/vt/vtctld + go run github.com/GeertJohan/go.rice/rice embed-go + go build . + +embed_config: + cd go/vt/mysqlctl + go run github.com/GeertJohan/go.rice/rice embed-go + go build . build_web: echo $$(date): Building web artifacts @@ -50,11 +58,37 @@ build: ifndef NOBANNER echo $$(date): Building source tree endif + bash ./build.env go install $(EXTRA_BUILD_FLAGS) $(VT_GO_PARALLEL) -ldflags "$(shell tools/build_version_flags.sh)" ./go/... +debug: +ifndef NOBANNER + echo $$(date): Building source tree +endif + bash ./build.env + go install $(EXTRA_BUILD_FLAGS) $(VT_GO_PARALLEL) -ldflags "$(shell tools/build_version_flags.sh)" -gcflags -'N -l' ./go/... + +# install copies the files needed to run Vitess into the given directory tree. +# Usage: make install PREFIX=/path/to/install/root +install: build + # binaries + mkdir -p "$${PREFIX}/bin" + cp "$${VTROOT}/bin/"{mysqlctld,vtctld,vtctlclient,vtgate,vttablet,vtworker,vtbackup} "$${PREFIX}/bin/" + # config files + mkdir -p "$${PREFIX}/src/vitess.io/vitess" + cp -R config "$${PREFIX}/src/vitess.io/vitess/" + # also symlink config files in the old location + ln -sf src/vitess.io/vitess/config "$${PREFIX}/config" + # vtctld web UI files + mkdir -p "$${PREFIX}/src/vitess.io/vitess/web/vtctld2" + cp -R web/vtctld2/app "$${PREFIX}/src/vitess.io/vitess/web/vtctld2/" + parser: make -C go/vt/sqlparser +visitor: + go generate go/vt/sqlparser/rewriter.go + # To pass extra flags, run test.go manually. # For example: go run test.go -docker=false -- --extra-flag # For more info see: go run test.go -help @@ -67,26 +101,19 @@ clean: go clean -i ./go/... rm -rf third_party/acolyte rm -rf go/vt/.proto.tmp - -# This will remove object files for all Go projects in the same GOPATH. -# This is necessary, for example, to make sure dependencies are rebuilt -# when switching between different versions of Go. -clean_pkg: - rm -rf ../../../../pkg Godeps/_workspace/pkg + rm -rf ./visitorgen # Remove everything including stuff pulled down by bootstrap.sh -cleanall: - # symlinks - for f in config data py-vtdb; do test -L ../../../../$$f && rm ../../../../$$f; done +cleanall: clean # directories created by bootstrap.sh # - exclude vtdataroot and vthook as they may have data we want - rm -rf ../../../../bin ../../../../dist ../../../../lib ../../../../pkg + rm -rf bin dist lib pkg # Remind people to run bootstrap.sh again - echo "Please run bootstrap.sh again to setup your environment" + echo "Please run 'make tools' again to setup your environment" -unit_test: build +unit_test: build dependency_check echo $$(date): Running unit tests - go test $(VT_GO_PARALLEL) ./go/... + tools/unit_test_runner.sh e2e_test: build echo $$(date): Running endtoend tests @@ -98,7 +125,7 @@ e2e_test: build unit_test_cover: build go test $(VT_GO_PARALLEL) -cover ./go/... | misc/parse_cover.py -unit_test_race: build +unit_test_race: build dependency_check tools/unit_test_race.sh e2e_test_race: build @@ -120,7 +147,7 @@ site_integration_test: java_test: go install ./go/cmd/vtgateclienttest ./go/cmd/vtcombo - mvn -f java/pom.xml -B clean verify + VTROOT=${PWD} mvn -f java/pom.xml -B clean verify install_protoc-gen-go: go install github.com/golang/protobuf/protoc-gen-go @@ -156,9 +183,13 @@ endif $(PROTO_PY_OUTS): py/vtproto/%_pb2.py: proto/%.proto $(PROTOC_COMMAND) -Iproto $< --python_out=py/vtproto --grpc_python_out=py/vtproto +# TODO(sougou): find a better way around this temp hack. +VTTOP=$(VTROOT)/../../.. $(PROTO_GO_OUTS): install_protoc-gen-go proto/*.proto for name in $(PROTO_SRC_NAMES); do \ - cd $(VTROOT)/src && PATH=$(VTROOT)/bin:$(PATH) $(VTROOT)/bin/protoc --go_out=plugins=grpc:. -Ivitess.io/vitess/proto vitess.io/vitess/proto/$${name}.proto; \ + cd $(VTTOP)/src && \ + $(VTROOT)/bin/protoc --go_out=plugins=grpc:. -Ivitess.io/vitess/proto vitess.io/vitess/proto/$${name}.proto && \ + goimports -w $(VTROOT)/go/vt/proto/$${name}/$${name}.pb.go; \ done # Helper targets for building Docker images. @@ -213,44 +244,45 @@ docker_base_percona80: chmod -R o=g * docker build -f docker/base/Dockerfile.percona80 -t vitess/base:percona80 . -# Run "make docker_lite PROMPT_NOTICE=false" to avoid that the script -# prompts you to press ENTER and confirm that the vitess/base image is not -# rebuild by this target as well. docker_lite: - cd docker/lite && ./build.sh --prompt=$(PROMPT_NOTICE) + chmod -R o=g * + docker build -f docker/lite/Dockerfile -t vitess/lite . docker_lite_mysql56: - cd docker/lite && ./build.sh --prompt=$(PROMPT_NOTICE) mysql56 + chmod -R o=g * + docker build -f docker/lite/Dockerfile.mysql56 -t vitess/lite:mysql56 . docker_lite_mysql57: - cd docker/lite && ./build.sh --prompt=$(PROMPT_NOTICE) mysql57 + chmod -R o=g * + docker build -f docker/lite/Dockerfile.mysql57 -t vitess/lite:mysql57 . docker_lite_mysql80: - cd docker/lite && ./build.sh --prompt=$(PROMPT_NOTICE) mysql80 + chmod -R o=g * + docker build -f docker/lite/Dockerfile.mysql80 -t vitess/lite:mysql80 . docker_lite_mariadb: - cd docker/lite && ./build.sh --prompt=$(PROMPT_NOTICE) mariadb + chmod -R o=g * + docker build -f docker/lite/Dockerfile.mariadb -t vitess/lite:mariadb . docker_lite_mariadb103: - cd docker/lite && ./build.sh --prompt=$(PROMPT_NOTICE) mariadb103 + chmod -R o=g * + docker build -f docker/lite/Dockerfile.mariadb103 -t vitess/lite:mariadb103 . docker_lite_percona: - cd docker/lite && ./build.sh --prompt=$(PROMPT_NOTICE) percona + chmod -R o=g * + docker build -f docker/lite/Dockerfile.percona -t vitess/lite:percona . docker_lite_percona57: - cd docker/lite && ./build.sh --prompt=$(PROMPT_NOTICE) percona57 + chmod -R o=g * + docker build -f docker/lite/Dockerfile.percona57 -t vitess/lite:percona57 . docker_lite_percona80: - cd docker/lite && ./build.sh --prompt=$(PROMPT_NOTICE) percona80 + chmod -R o=g * + docker build -f docker/lite/Dockerfile.percona80 -t vitess/lite:percona80 . docker_lite_alpine: - cd docker/lite && ./build.sh --prompt=$(PROMPT_NOTICE) alpine - -docker_guestbook: - cd examples/kubernetes/guestbook && ./build.sh - -docker_publish_site: - docker build -f docker/publish-site/Dockerfile -t vitess/publish-site . + chmod -R o=g * + docker build -f docker/lite/Dockerfile.alpine -t vitess/lite:alpine . # This rule loads the working copy of the code into a bootstrap image, # and then runs the tests inside Docker. @@ -289,3 +321,14 @@ packages: docker_base docker build -f docker/packaging/Dockerfile -t vitess/packaging . docker run --rm -v ${PWD}/releases:/vt/releases --env VERSION=$(VERSION) vitess/packaging --package /vt/releases -t deb --deb-no-default-config-files docker run --rm -v ${PWD}/releases:/vt/releases --env VERSION=$(VERSION) vitess/packaging --package /vt/releases -t rpm + +tools: + echo $$(date): Installing dependencies + ./bootstrap.sh + +minimaltools: + echo $$(date): Installing minimal dependencies + BUILD_JAVA=0 BUILD_CONSUL=0 ./bootstrap.sh + +dependency_check: + ./tools/dependency_check.sh diff --git a/README.md b/README.md index bbe10c4c8c7..c541c544693 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![Go Report Card](https://goreportcard.com/badge/vitess.io/vitess)](https://goreportcard.com/report/vitess.io/vitess) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fvitessio%2Fvitess.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fvitessio%2Fvitess?ref=badge_shield) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1724/badge)](https://bestpractices.coreinfrastructure.org/projects/1724) +[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=vitessio&metric=coverage)](https://sonarcloud.io/dashboard?id=vitessio) # Vitess diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index 03a4ca827af..00000000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,21 +0,0 @@ -pr: -- master - -pool: - vmImage: 'ubuntu-latest' - -variables: - flags: "-docker -use_docker_cache -timeout=8m -print-log" - shards: [0, 1, 2, 3, 4] - flavors: ["mysql56", "mysql57", "mysql80", "mariadb", "mariadb103", "percona57", "percona80"] -jobs: -- job: tests - strategy: - matrix: - ${{ each flavor in variables.flavors }}: - ${{ each shard in variables.shards }}: - ${{ format('{0}{1}', flavor, shard) }}: - flavor: ${{ flavor }} - shard: ${{ shard }} - steps: - - script: go run test.go -shard $(shard) -flavor $(flavor) $(flags) diff --git a/bootstrap.sh b/bootstrap.sh index d8bd3b3a8b9..bc9f9170357 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -15,69 +15,23 @@ # See the License for the specific language governing permissions and # limitations under the License. +### This file is executed by 'make tools'. You do not need to execute it directly. + +source ./dev.env # Outline of this file. # 0. Initialization and helper methods. # 1. Installation of dependencies. -BUILD_TESTS=${BUILD_TESTS:-1} -BUILD_PYTHON=${BUILD_PYTHON:-1} BUILD_JAVA=${BUILD_JAVA:-1} +BUILD_CONSUL=${BUILD_CONSUL:-1} # # 0. Initialization and helper methods. # -function fail() { - echo "ERROR: $1" - exit 1 -} - [[ "$(dirname "$0")" = "." ]] || fail "bootstrap.sh must be run from its current directory" -# Create main directories. -VTROOT="${VTROOT:-${PWD/\/src\/vitess.io\/vitess/}}" -mkdir -p "$VTROOT/dist" -mkdir -p "$VTROOT/bin" -mkdir -p "$VTROOT/lib" -mkdir -p "$VTROOT/vthook" - -# This is required for VIRTUALENV -# Used by Python below - -if [ "$BUILD_TESTS" == 1 ] ; then - source ./dev.env -else - source ./build.env -fi - -go version &>/dev/null || fail "Go is not installed or is not on \$PATH" -goversion_min 1.12 || fail "Go is not version 1.12+" - -if [ "$BUILD_TESTS" == 1 ] ; then - # Set up required soft links. - # TODO(mberlin): Which of these can be deleted? - ln -snf "$VTTOP/config" "$VTROOT/config" - ln -snf "$VTTOP/data" "$VTROOT/data" - ln -snf "$VTTOP/py" "$VTROOT/py-vtdb" - ln -snf "$VTTOP/go/vt/zkctl/zksrv.sh" "$VTROOT/bin/zksrv.sh" - ln -snf "$VTTOP/test/vthook-test.sh" "$VTROOT/vthook/test.sh" - ln -snf "$VTTOP/test/vthook-test_backup_error" "$VTROOT/vthook/test_backup_error" - ln -snf "$VTTOP/test/vthook-test_backup_transform" "$VTROOT/vthook/test_backup_transform" -else - ln -snf "$VTTOP/config" "$VTROOT/config" - ln -snf "$VTTOP/data" "$VTROOT/data" - ln -snf "$VTTOP/go/vt/zkctl/zksrv.sh" "$VTROOT/bin/zksrv.sh" -fi - -# git hooks are only required if someone intends to contribute. - -echo "creating git hooks" -mkdir -p "$VTTOP/.git/hooks" -ln -sf "$VTTOP/misc/git/pre-commit" "$VTTOP/.git/hooks/pre-commit" -ln -sf "$VTTOP/misc/git/commit-msg" "$VTTOP/.git/hooks/commit-msg" -(cd "$VTTOP" && git config core.hooksPath "$VTTOP/.git/hooks") - # install_dep is a helper function to generalize the download and installation of dependencies. # # If the installation is successful, it puts the installed version string into @@ -127,42 +81,13 @@ function install_dep() { # 1. Installation of dependencies. # -# Wrapper around the `arch` command which plays nice with OS X +# We should not use the arch command, since it is not reliably +# available on macOS or some linuxes: +# https://www.gnu.org/software/coreutils/manual/html_node/arch-invocation.html function get_arch() { - case $(uname) in - Linux) arch;; - Darwin) uname -m;; - esac + uname -m } - -# Install the gRPC Python library (grpcio) and the protobuf gRPC Python plugin (grpcio-tools) from PyPI. -# Dependencies like the Python protobuf package will be installed automatically. -function install_grpc() { - local version="$1" - local dist="$2" - - # Python requires a very recent version of virtualenv. - # We also require a recent version of pip, as we use it to - # upgrade the other tools. - # For instance, setuptools doesn't work with pip 6.0: - # https://github.com/pypa/setuptools/issues/945 - # (and setuptools is used by grpc install). - grpc_virtualenv="$dist/usr/local" - $VIRTUALENV -v "$grpc_virtualenv" - PIP=$grpc_virtualenv/bin/pip - $PIP install --upgrade pip - $PIP install --upgrade --ignore-installed virtualenv - $PIP install mysql-connector-python - - grpcio_ver=$version - $PIP install --upgrade grpcio=="$grpcio_ver" grpcio-tools=="$grpcio_ver" -} - -if [ "$BUILD_PYTHON" == 1 ] ; then - install_dep "gRPC" "1.16.0" "$VTROOT/dist/grpc" install_grpc -fi - # Install protoc. function install_protoc() { local version="$1" @@ -235,8 +160,9 @@ function install_etcd() { fi rm "$file" ln -snf "$dist/etcd-${version}-${platform}-${target}/etcd" "$VTROOT/bin/etcd" + ln -snf "$dist/etcd-${version}-${platform}-${target}/etcdctl" "$VTROOT/bin/etcdctl" } -which etcd || install_dep "etcd" "v3.3.10" "$VTROOT/dist/etcd" install_etcd +command -v etcd && echo "etcd already installed" || install_dep "etcd" "v3.3.10" "$VTROOT/dist/etcd" install_etcd # Download and install consul, link consul binary into our root. @@ -260,79 +186,10 @@ function install_consul() { unzip "consul_${version}_${platform}_${target}.zip" ln -snf "$dist/consul" "$VTROOT/bin/consul" } -install_dep "Consul" "1.4.0" "$VTROOT/dist/consul" install_consul - - -# Install py-mock. -function install_pymock() { - local version="$1" - local dist="$2" - - # For some reason, it seems like setuptools won't create directories even with the --prefix argument - mkdir -p lib/python2.7/site-packages - PYTHONPATH=$(prepend_path "$PYTHONPATH" "$dist/lib/python2.7/site-packages") - export PYTHONPATH - - pushd "$VTTOP/third_party/py" >/dev/null - tar -xzf "mock-$version.tar.gz" - cd "mock-$version" - $PYTHON ./setup.py install --prefix="$dist" - cd .. - rm -r "mock-$version" - popd >/dev/null -} -pymock_version=1.0.1 -if [ "$BUILD_PYTHON" == 1 ] ; then - install_dep "py-mock" "$pymock_version" "$VTROOT/dist/py-mock-$pymock_version" install_pymock -fi - -# Download Selenium (necessary to run test/vtctld_web_test.py). -function install_selenium() { - local version="$1" - local dist="$2" - - $VIRTUALENV "$dist" - PIP="$dist/bin/pip" - # PYTHONPATH is removed for `pip install` because otherwise it can pick up go/dist/grpc/usr/local/lib/python2.7/site-packages - # instead of go/dist/selenium/lib/python3.5/site-packages and then can't find module 'pip._vendor.requests' - PYTHONPATH='' $PIP install selenium -} -if [ "$BUILD_PYTHON" == 1 ] ; then - install_dep "Selenium" "latest" "$VTROOT/dist/selenium" install_selenium -fi - -# Download chromedriver (necessary to run test/vtctld_web_test.py). -function install_chromedriver() { - local version="$1" - local dist="$2" - - if [ "$(arch)" == "aarch64" ] ; then - os=$(cat /etc/*release | grep "^ID=" | cut -d '=' -f 2) - case $os in - ubuntu|debian) - sudo apt-get update -y && sudo apt install -y --no-install-recommends unzip libglib2.0-0 libnss3 libx11-6 - ;; - centos|fedora) - sudo yum update -y && yum install -y libX11 unzip wget - ;; - esac - echo "For Arm64, using prebuilt binary from electron (https://github.com/electron/electron/) of version 76.0.3809.126" - wget https://github.com/electron/electron/releases/download/v6.0.3/chromedriver-v6.0.3-linux-arm64.zip - unzip -o -q chromedriver-v6.0.3-linux-arm64.zip -d "$dist" - rm chromedriver-v6.0.3-linux-arm64.zip - else - curl -sL "https://chromedriver.storage.googleapis.com/$version/chromedriver_linux64.zip" > chromedriver_linux64.zip - unzip -o -q chromedriver_linux64.zip -d "$dist" - rm chromedriver_linux64.zip - fi -} -if [ "$BUILD_PYTHON" == 1 ] ; then - install_dep "chromedriver" "73.0.3683.20" "$VTROOT/dist/chromedriver" install_chromedriver -fi -if [ "$BUILD_PYTHON" == 1 ] ; then - PYTHONPATH='' $PIP install mysql-connector-python +if [ "$BUILD_CONSUL" == 1 ] ; then + install_dep "Consul" "1.4.0" "$VTROOT/dist/consul" install_consul fi echo -echo "bootstrap finished - run 'source dev.env' or 'source build.env' in your shell before building." +echo "bootstrap finished - run 'make build' to compile" diff --git a/build.env b/build.env old mode 100644 new mode 100755 index 3af09b3014a..467749a10f1 --- a/build.env +++ b/build.env @@ -14,28 +14,33 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Plese ensure dev.env is written in a way which is POSIX (bourne) -# shell compatible. -# - Some build systems like rpm require the different scriptlets used -# to build a package to be run under a POSIX shell so non-POSIX -# syntax will break that as dev.env will not be sourced by bash.. - -# Import prepend_path function. -dir="$(dirname "${BASH_SOURCE[0]}")" -# shellcheck source=tools/shell_functions.inc -if ! source "${dir}/tools/shell_functions.inc"; then - echo "failed to load tools/shell_functions.inc" - return 1 -fi - -VTTOP=$(pwd) -export VTTOP -VTROOT="${VTROOT:-${VTTOP/\/src\/vitess.io\/vitess/}}" -export VTROOT -# VTTOP sanity check -if [[ "$VTTOP" == "${VTTOP/\/src\/vitess.io\/vitess/}" ]]; then - echo "WARNING: VTTOP($VTTOP) does not contain src/vitess.io/vitess" -fi - -export GOBIN="$VTROOT/bin" -export GO111MODULE=on +source ./tools/shell_functions.inc + +go version >/dev/null 2>&1 || fail "Go is not installed or is not in \$PATH. See https://vitess.io/contributing/build-from-source for install instructions." +goversion_min 1.12 || fail "Go is not version 1.12+. See https://vitess.io/contributing/build-from-source for install instructions." + +mkdir -p dist +mkdir -p bin +mkdir -p lib +mkdir -p vthook + +export VTROOT="$PWD" +export VTDATAROOT="${VTDATAROOT:-${VTROOT}/vtdataroot}" +export PATH="$PWD/bin:$PATH" + +mkdir -p "$VTDATAROOT" + +# Set up required soft links. +# TODO(mberlin): Which of these can be deleted? +ln -snf "$PWD/py" py-vtdb +ln -snf "$PWD/go/vt/zkctl/zksrv.sh" bin/zksrv.sh +ln -snf "$PWD/test/vthook-test.sh" vthook/test.sh +ln -snf "$PWD/test/vthook-test_backup_error" vthook/test_backup_error +ln -snf "$PWD/test/vthook-test_backup_transform" vthook/test_backup_transform + +# install git hooks + +mkdir -p .git/hooks +ln -sf "$PWD/misc/git/pre-commit" .git/hooks/pre-commit +ln -sf "$PWD/misc/git/commit-msg" .git/hooks/commit-msg +git config core.hooksPath .git/hooks diff --git a/config/init_db.sql b/config/init_db.sql index 5b56939c3c3..836c8c997e6 100644 --- a/config/init_db.sql +++ b/config/init_db.sql @@ -84,6 +84,13 @@ GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO 'vt_filtered'@'localhost'; +# User for general MySQL monitoring. +CREATE USER 'vt_monitoring'@'localhost'; +GRANT SELECT, PROCESS, SUPER, REPLICATION CLIENT, RELOAD + ON *.* TO 'vt_monitoring'@'localhost'; +GRANT SELECT, UPDATE, DELETE, DROP + ON performance_schema.* TO 'vt_monitoring'@'localhost'; + # User for Orchestrator (https://github.com/github/orchestrator). CREATE USER 'orc_client_user'@'%' IDENTIFIED BY 'orc_client_user_password'; GRANT SUPER, PROCESS, REPLICATION SLAVE, RELOAD diff --git a/config/mycnf/default-fast.cnf b/config/mycnf/default-fast.cnf index 969b51baa34..1880704e05b 100644 --- a/config/mycnf/default-fast.cnf +++ b/config/mycnf/default-fast.cnf @@ -1,37 +1,22 @@ -# basic config parameters for all db instances in the grid +# This sets some unsafe settings specifically for +# the test-suite which is currently MySQL 5.7 based +# In future it should be renamed testsuite.cnf -sql_mode = STRICT_TRANS_TABLES -character_set_server = utf8 -collation_server = utf8_general_ci -connect_timeout = 30 -datadir = {{.DataDir}} -expire_logs_days = 3 -innodb_buffer_pool_size = 64M -innodb_data_home_dir = {{.InnodbDataHomeDir}} -innodb_flush_log_at_trx_commit = 2 -innodb_lock_wait_timeout = 20 +innodb_buffer_pool_size = 32M +innodb_flush_log_at_trx_commit = 0 innodb_log_buffer_size = 1M -innodb_log_file_size = 4M -innodb_log_group_home_dir = {{.InnodbLogGroupHomeDir}} +innodb_log_file_size = 5M + +# Native AIO tends to run into aio-max-nr limit during test startup. +innodb_use_native_aio = 0 + key_buffer_size = 2M -log-error = {{.ErrorLogPath}} -long_query_time = 2 -pid-file = {{.PidFile}} -port = {{.MysqlPort}} -# all db instances should start in read-only mode - once the db is started and -# fully functional, we'll push it into read-write mode -read-only -server-id = {{.ServerID}} -skip-name-resolve -# we now need networking for replication. this is a tombstone to simpler times. -#skip_networking -# all db instances should skip the slave startup - that way we can do any -# out-of-bounds checking before we restart everything - in case we need to do -# some extra work to skip mangled transactions or fudge the slave start -skip_slave_start -slave_net_timeout = 60 -slave_load_tmpdir = {{.SlaveLoadTmpDir}} -slow-query-log -slow-query-log-file = {{.SlowLogPath}} -socket = {{.SocketFile}} -tmpdir = {{.TmpDir}} +sync_binlog=0 +innodb_doublewrite=0 + +# These two settings are required for the testsuite to pass, +# but enabling them does not spark joy. They should be removed +# in the future. See: +# https://github.com/vitessio/vitess/issues/5396 + +sql_mode = STRICT_TRANS_TABLES diff --git a/config/mycnf/default.cnf b/config/mycnf/default.cnf index 61f767a8032..14d1feaa12f 100644 --- a/config/mycnf/default.cnf +++ b/config/mycnf/default.cnf @@ -1,35 +1,38 @@ -# basic config parameters for all db instances in the grid +# Global configuration that is auto-included for all MySQL/MariaDB versions -sql_mode = STRICT_TRANS_TABLES -binlog_format = statement -character_set_server = utf8 -collation_server = utf8_general_ci -connect_timeout = 30 datadir = {{.DataDir}} -expire_logs_days = 3 -innodb_buffer_pool_size = 32M innodb_data_home_dir = {{.InnodbDataHomeDir}} -innodb_flush_log_at_trx_commit = 2 -innodb_lock_wait_timeout = 20 innodb_log_group_home_dir = {{.InnodbLogGroupHomeDir}} log-error = {{.ErrorLogPath}} -long_query_time = 2 -max_allowed_packet = 64M -max_connections = 500 +log-bin = {{.BinLogPath}} +relay-log = {{.RelayLogPath}} +relay-log-index = {{.RelayLogIndexPath}} pid-file = {{.PidFile}} port = {{.MysqlPort}} + # all db instances should start in read-only mode - once the db is started and # fully functional, we'll push it into read-write mode read-only server-id = {{.ServerID}} -skip-name-resolve + # all db instances should skip the slave startup - that way we can do any # additional configuration (like enabling semi-sync) before we connect to # the master. skip_slave_start -slave_net_timeout = 60 slave_load_tmpdir = {{.SlaveLoadTmpDir}} -slow-query-log -slow-query-log-file = {{.SlowLogPath}} socket = {{.SocketFile}} tmpdir = {{.TmpDir}} + +slow-query-log-file = {{.SlowLogPath}} + +# These are sensible defaults that apply to all MySQL/MariaDB versions + +long_query_time = 2 +slow-query-log +skip-name-resolve +connect_timeout = 30 +innodb_lock_wait_timeout = 20 +max_allowed_packet = 64M +max_connections = 500 + + diff --git a/config/mycnf/master.cnf b/config/mycnf/master.cnf deleted file mode 100644 index 481f06f5ffd..00000000000 --- a/config/mycnf/master.cnf +++ /dev/null @@ -1,5 +0,0 @@ -# master.cnf parameters - -log-bin = {{.BinLogPath}} -log-slave-updates -sync_binlog = 1 diff --git a/config/mycnf/master_mariadb100.cnf b/config/mycnf/master_mariadb100.cnf index 3eed4d8ea5f..4772ab3d5e1 100644 --- a/config/mycnf/master_mariadb100.cnf +++ b/config/mycnf/master_mariadb100.cnf @@ -1,7 +1,5 @@ # This file is auto-included when MariaDB 10.0 is detected. -innodb_support_xa = 0 - # Semi-sync replication is required for automated unplanned failover # (when the master goes away). Here we just load the plugin so it's # available if desired, but it's disabled at startup. @@ -11,6 +9,11 @@ innodb_support_xa = 0 # promoted or demoted. plugin-load = rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so +slave_net_timeout = 60 + +# MariaDB 10.0 is unstrict by default +sql_mode = STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION + # enable strict mode so it's safe to compare sequence numbers across different server IDs. gtid_strict_mode = 1 innodb_stats_persistent = 0 @@ -21,3 +24,20 @@ innodb_stats_persistent = 0 # a master that becomes unresponsive. rpl_semi_sync_master_timeout = 1000000000000000000 rpl_semi_sync_master_wait_no_slave = 1 + + +character_set_server = utf8 +collation_server = utf8_general_ci + +expire_logs_days = 3 + +sync_binlog = 1 +binlog_format = ROW +log_slave_updates +expire_logs_days = 3 + +# In MariaDB the default charset is latin1 + +character_set_server = utf8 +collation_server = utf8_general_ci + diff --git a/config/mycnf/master_mariadb101.cnf b/config/mycnf/master_mariadb101.cnf index 8c5b9e47fac..245ffdc452a 100644 --- a/config/mycnf/master_mariadb101.cnf +++ b/config/mycnf/master_mariadb101.cnf @@ -1,7 +1,5 @@ # This file is auto-included when MariaDB 10.1 is detected. -innodb_support_xa = 0 - # Semi-sync replication is required for automated unplanned failover # (when the master goes away). Here we just load the plugin so it's # available if desired, but it's disabled at startup. @@ -11,6 +9,11 @@ innodb_support_xa = 0 # promoted or demoted. plugin-load = rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so +slave_net_timeout = 60 + +# MariaDB 10.1 default is only no-engine-substitution and no-auto-create-user +sql_mode = STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,NO_AUTO_CREATE_USER + # enable strict mode so it's safe to compare sequence numbers across different server IDs. gtid_strict_mode = 1 innodb_stats_persistent = 0 @@ -21,3 +24,19 @@ innodb_stats_persistent = 0 # a master that becomes unresponsive. rpl_semi_sync_master_timeout = 1000000000000000000 rpl_semi_sync_master_wait_no_slave = 1 + + +character_set_server = utf8 +collation_server = utf8_general_ci + +expire_logs_days = 3 + +sync_binlog = 1 +binlog_format = ROW +log_slave_updates +expire_logs_days = 3 + +# In MariaDB the default charset is latin1 + +character_set_server = utf8 +collation_server = utf8_general_ci diff --git a/config/mycnf/master_mariadb102.cnf b/config/mycnf/master_mariadb102.cnf index 1ea39a2a47c..2f04d680505 100644 --- a/config/mycnf/master_mariadb102.cnf +++ b/config/mycnf/master_mariadb102.cnf @@ -1,7 +1,5 @@ # This file is auto-included when MariaDB 10.2 is detected. -innodb_support_xa = 0 - # Semi-sync replication is required for automated unplanned failover # (when the master goes away). Here we just load the plugin so it's # available if desired, but it's disabled at startup. @@ -21,3 +19,19 @@ innodb_stats_persistent = 0 # a master that becomes unresponsive. rpl_semi_sync_master_timeout = 1000000000000000000 rpl_semi_sync_master_wait_no_slave = 1 + + +character_set_server = utf8 +collation_server = utf8_general_ci + +expire_logs_days = 3 + +sync_binlog = 1 +binlog_format = ROW +log_slave_updates +expire_logs_days = 3 + +# In MariaDB the default charset is latin1 + +character_set_server = utf8 +collation_server = utf8_general_ci diff --git a/config/mycnf/master_mariadb103.cnf b/config/mycnf/master_mariadb103.cnf index ac8b38404fd..3181e3685d5 100644 --- a/config/mycnf/master_mariadb103.cnf +++ b/config/mycnf/master_mariadb103.cnf @@ -4,20 +4,27 @@ gtid_strict_mode = 1 innodb_stats_persistent = 0 -# Semi-sync replication is required for automated unplanned failover -# (when the master goes away). Here we just load the plugin so it's -# available if desired, but it's disabled at startup. -# -# If the -enable_semi_sync flag is used, VTTablet will enable semi-sync -# at the proper time when replication is set up, or when masters are -# promoted or demoted. - -# semi_sync has been merged into master as of mariadb 10.3 so this is no longer needed -#plugin-load = rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so - # When semi-sync is enabled, don't allow fallback to async # if you get no ack, or have no slaves. This is necessary to # prevent alternate futures when doing a failover in response to # a master that becomes unresponsive. rpl_semi_sync_master_timeout = 1000000000000000000 rpl_semi_sync_master_wait_no_slave = 1 + + +character_set_server = utf8 +collation_server = utf8_general_ci + +expire_logs_days = 3 + +sync_binlog = 1 +binlog_format = ROW +log_slave_updates +expire_logs_days = 3 + +# In MariaDB the default charset is latin1 + +character_set_server = utf8 +collation_server = utf8_general_ci + + diff --git a/config/mycnf/master_mariadb104.cnf b/config/mycnf/master_mariadb104.cnf index a144f352561..a1111d8562a 100644 --- a/config/mycnf/master_mariadb104.cnf +++ b/config/mycnf/master_mariadb104.cnf @@ -4,20 +4,27 @@ gtid_strict_mode = 1 innodb_stats_persistent = 0 -# Semi-sync replication is required for automated unplanned failover -# (when the master goes away). Here we just load the plugin so it's -# available if desired, but it's disabled at startup. -# -# If the -enable_semi_sync flag is used, VTTablet will enable semi-sync -# at the proper time when replication is set up, or when masters are -# promoted or demoted. - -# semi_sync has been merged into master as of mariadb 10.3 so this is no longer needed -#plugin-load = rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so - # When semi-sync is enabled, don't allow fallback to async # if you get no ack, or have no slaves. This is necessary to # prevent alternate futures when doing a failover in response to # a master that becomes unresponsive. rpl_semi_sync_master_timeout = 1000000000000000000 rpl_semi_sync_master_wait_no_slave = 1 + + +character_set_server = utf8 +collation_server = utf8_general_ci + +expire_logs_days = 3 + +sync_binlog = 1 +binlog_format = ROW +log_slave_updates +expire_logs_days = 3 + +# In MariaDB the default charset is latin1 + +character_set_server = utf8 +collation_server = utf8_general_ci + + diff --git a/config/mycnf/master_mysql56.cnf b/config/mycnf/master_mysql56.cnf index dcb8a4e113f..f38e1c175fc 100644 --- a/config/mycnf/master_mysql56.cnf +++ b/config/mycnf/master_mysql56.cnf @@ -1,20 +1,28 @@ # This file is auto-included when MySQL 5.6 is detected. -# Options for enabling GTID -# https://dev.mysql.com/doc/refman/5.6/en/replication-gtids-howto.html +# MySQL 5.6 does not enable the binary log by default, and +# the default for sync_binlog is unsafe. The format is TABLE, and +# info repositories also default to file. + +sync_binlog = 1 gtid_mode = ON -log_bin +binlog_format = ROW log_slave_updates enforce_gtid_consistency - -# Crash-safe replication settings. +expire_logs_days = 3 master_info_repository = TABLE relay_log_info_repository = TABLE relay_log_purge = 1 relay_log_recovery = 1 +slave_net_timeout = 60 + +# In MySQL 5.6 the default charset is latin1 -# Native AIO tends to run into aio-max-nr limit during test startup. -innodb_use_native_aio = 0 +character_set_server = utf8 +collation_server = utf8_general_ci + +# MySQL 5.6 is unstrict by default +sql_mode = STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION # Semi-sync replication is required for automated unplanned failover # (when the master goes away). Here we just load the plugin so it's @@ -31,3 +39,4 @@ plugin-load = rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisy # a master that becomes unresponsive. rpl_semi_sync_master_timeout = 1000000000000000000 rpl_semi_sync_master_wait_no_slave = 1 + diff --git a/config/mycnf/master_mysql57.cnf b/config/mycnf/master_mysql57.cnf index 381b05ac14c..4282f788a75 100644 --- a/config/mycnf/master_mysql57.cnf +++ b/config/mycnf/master_mysql57.cnf @@ -1,19 +1,22 @@ # This file is auto-included when MySQL 5.7 is detected. -# Options for enabling GTID -# https://dev.mysql.com/doc/refman/5.6/en/replication-gtids-howto.html +# MySQL 5.7 does not enable the binary log by default, and +# info repositories default to file + gtid_mode = ON -log_bin log_slave_updates enforce_gtid_consistency -innodb_use_native_aio = 0 - -# Crash-safe replication settings. +expire_logs_days = 3 master_info_repository = TABLE relay_log_info_repository = TABLE relay_log_purge = 1 relay_log_recovery = 1 +# In MySQL 5.7 the default charset is latin1 + +character_set_server = utf8 +collation_server = utf8_general_ci + # Semi-sync replication is required for automated unplanned failover # (when the master goes away). Here we just load the plugin so it's # available if desired, but it's disabled at startup. diff --git a/config/mycnf/master_mysql80.cnf b/config/mycnf/master_mysql80.cnf index e92b794ef9b..6c3d77d5135 100644 --- a/config/mycnf/master_mysql80.cnf +++ b/config/mycnf/master_mysql80.cnf @@ -1,20 +1,18 @@ # This file is auto-included when MySQL 8.0 is detected. -# Options for enabling GTID -# https://dev.mysql.com/doc/refman/5.6/en/replication-gtids-howto.html +# MySQL 8.0 enables binlog by default with sync_binlog and TABLE info repositories +# It does not enable GTIDs or enforced GTID consistency + gtid_mode = ON -log_bin -log_slave_updates enforce_gtid_consistency - -# Crash-safe replication settings. -master_info_repository = TABLE -relay_log_info_repository = TABLE -relay_log_purge = 1 relay_log_recovery = 1 +binlog_expire_logs_seconds = 259200 + +# disable mysqlx +mysqlx = 0 -# Native AIO tends to run into aio-max-nr limit during test startup. -innodb_use_native_aio = 0 +# 8.0 changes the default auth-plugin to caching_sha2_password +default_authentication_plugin = mysql_native_password # Semi-sync replication is required for automated unplanned failover # (when the master goes away). Here we just load the plugin so it's @@ -25,16 +23,9 @@ innodb_use_native_aio = 0 # promoted or demoted. plugin-load = rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so -# When semi-sync is enabled, don't allow fallback to async -# if you get no ack, or have no slaves. This is necessary to -# prevent alternate futures when doing a failover in response to -# a master that becomes unresponsive. -rpl_semi_sync_master_timeout = 1000000000000000000 -rpl_semi_sync_master_wait_no_slave = 1 - -# disable mysqlx -mysqlx = 0 +# MySQL 8.0 will not load plugins during --initialize +# which makes these options unknown. Prefixing with --loose +# tells the server it's fine if they are not understood. +loose_rpl_semi_sync_master_timeout = 1000000000000000000 +loose_rpl_semi_sync_master_wait_no_slave = 1 -# 8.0 changes the default auth-plugin to caching_sha2_password -default_authentication_plugin = mysql_native_password -secure_file_priv = NULL diff --git a/config/mycnf/rbr.cnf b/config/mycnf/rbr.cnf deleted file mode 100644 index 5dde64cda57..00000000000 --- a/config/mycnf/rbr.cnf +++ /dev/null @@ -1 +0,0 @@ -binlog-format=row diff --git a/config/mycnf/replica.cnf b/config/mycnf/replica.cnf deleted file mode 100644 index 74e9f2b34ea..00000000000 --- a/config/mycnf/replica.cnf +++ /dev/null @@ -1,13 +0,0 @@ -# replica.cnf - reserved for future tuning - -relay-log = {{.RelayLogPath}} -relay-log-index = {{.RelayLogIndexPath}} -relay-log-info-file = {{.RelayLogInfoPath}} -master-info-file = {{.MasterInfoFile}} - -# required if this master is chained -# probably safe to turn on all the time at the expense of some disk I/O -# note: this is in the master conf too -log-slave-updates - -#slave_compressed_protocol diff --git a/config/mycnf/sbr.cnf b/config/mycnf/sbr.cnf new file mode 100644 index 00000000000..5808e0430f3 --- /dev/null +++ b/config/mycnf/sbr.cnf @@ -0,0 +1,3 @@ +# This file is used to allow legacy tests to pass +# In theory it should not be required +binlog_format=statement diff --git a/config/mycnf/vtcombo.cnf b/config/mycnf/vtcombo.cnf deleted file mode 100644 index de6141f2c97..00000000000 --- a/config/mycnf/vtcombo.cnf +++ /dev/null @@ -1 +0,0 @@ -max_connections = 5000 diff --git a/dev.env b/dev.env index 54dd9cb41b9..f256abbd93a 100644 --- a/dev.env +++ b/dev.env @@ -22,12 +22,6 @@ source ./build.env -export GOTOP=$VTTOP/go -export PYTOP=$VTTOP/py - -export VTDATAROOT="${VTDATAROOT:-${VTROOT}/vtdataroot}" -mkdir -p "$VTDATAROOT" - export VTPORTSTART=15000 # Add all site-packages or dist-packages directories below $VTROOT/dist to $PYTHONPATH. @@ -43,8 +37,8 @@ IFS="$BACKUP_IFS" PYTHONPATH=$(prepend_path "$PYTHONPATH" "$VTROOT/py-vtdb") PYTHONPATH=$(prepend_path "$PYTHONPATH" "$VTROOT/dist/selenium") -PYTHONPATH=$(prepend_path "$PYTHONPATH" "$VTTOP/test") -PYTHONPATH=$(prepend_path "$PYTHONPATH" "$VTTOP/test/cluster/sandbox") +PYTHONPATH=$(prepend_path "$PYTHONPATH" "$VTROOT/test") +PYTHONPATH=$(prepend_path "$PYTHONPATH" "$VTROOT/test/cluster/sandbox") export PYTHONPATH # Ensure bootstrap.sh uses python2 on systems which default to python3. @@ -62,28 +56,8 @@ PATH=$(prepend_path "$PATH" "$VTROOT/dist/chromedriver") PATH=$(prepend_path "$PATH" "$VTROOT/dist/node/bin") export PATH -# mysql install location. Please set based on your environment. -# Build will not work if this is incorrect. - -if [[ "$VT_MYSQL_ROOT" == "" ]]; then - if [[ "$(which mysql)" == "" ]]; then - echo "WARNING: VT_MYSQL_ROOT unset because mysql not found. Did you install a client package?" - else - VT_MYSQL_ROOT=$(dirname "$(dirname "$(which mysql)")") - export VT_MYSQL_ROOT - fi -fi - -PKG_CONFIG_PATH=$(prepend_path "$PKG_CONFIG_PATH" "$VTROOT/lib") -export PKG_CONFIG_PATH - # According to https://github.com/etcd-io/etcd/blob/a621d807f061e1dd635033a8d6bc261461429e27/Documentation/op-guide/supported-platform.md, # currently, etcd is unstable on arm64, so ETCD_UNSUPPORTED_ARCH should be set. -if [ "$(arch)" == aarch64 ]; then +if [ "$(uname -m)" == aarch64 ]; then export ETCD_UNSUPPORTED_ARCH=arm64 fi - -# Useful aliases. Remove if inconvenient. -alias gt='cd $GOTOP' -alias pt='cd $PYTOP' -alias vt='cd $VTTOP' diff --git a/doc/DockerBuild.md b/doc/DockerBuild.md index 986b8e672c6..afb96430655 100644 --- a/doc/DockerBuild.md +++ b/doc/DockerBuild.md @@ -1,4 +1,4 @@ -By default, the [Kubernetes configs](https://github.com/vitessio/vitess/tree/master/examples/kubernetes) +By default, the [Helm Charts](https://github.com/vitessio/vitess/tree/master/helm) point to the `vitess/lite` image on [Docker Hub](https://hub.docker.com/u/vitess/). We created the `lite` image as a stripped down version of our main image `base` such that Kubernetes pods can start faster. @@ -81,19 +81,5 @@ Then you can run our build script for the `lite` image which extracts the Vitess **Note:** If you chose a non-default flavor above, then change `vitess/lite` in the above command to `vitess/lite:`. -1. Change the Kubernetes configs to point to your personal repository: - ```sh - vitess/examples/kubernetes$ sed -i -e 's,image: vitess/lite,image: yourname/vitess:latest,' *.yaml - ``` - - Adding the `:latest` label at the end of the image name tells Kubernetes - to check for a newer image every time a pod is launched. - When you push a new version of your image, any new pods will use it - automatically without you having to clear the Kubernetes image cache. - - Once you've stabilized your image, you'll probably want to replace `:latest` - with a specific label that you change each time you make a new build, - so you can control when pods update. - -1. Launch [Vitess on Kubernetes]({% link getting-started/index.md %}) as usual. +1. Launch [Vitess on Kubernetes](https://vitess.io/docs/get-started/index.html) as usual. diff --git a/doc/V3HighLevelDesign.md b/doc/V3HighLevelDesign.md index 5becdb0d46b..72fc15d43c4 100644 --- a/doc/V3HighLevelDesign.md +++ b/doc/V3HighLevelDesign.md @@ -641,7 +641,7 @@ All other operations are considered ‘cheap’ because they can be applied as t ## Preserving the original representation -In the case of VTGate, the ‘Route’ operation is capable of performing all 9 functions, as long as all the rows needed to fulfil the query reside in a single database. However, those functions have to be expressed as an SQL query. Most often, the original query could just be passed-through to a single shard. So, the one important question is: If we converted a query to its relational representation, can we then convert it back to the original query? The answer is no, or at least not trivially; The relational operators don’t always map one-to-one with the constructs of an SQL statement. Here’s a specific example: +In the case of VTGate, the ‘Route’ operation is capable of performing all 9 functions, as long as all the rows needed to fulfill the query reside in a single database. However, those functions have to be expressed as an SQL query. Most often, the original query could just be passed-through to a single shard. So, the one important question is: If we converted a query to its relational representation, can we then convert it back to the original query? The answer is no, or at least not trivially; The relational operators don’t always map one-to-one with the constructs of an SQL statement. Here’s a specific example: `select count(*), a+1, b from t group by a+1, b` diff --git a/docker/README.md b/docker/README.md index 0b0e47d19fe..0741e7a2f1a 100644 --- a/docker/README.md +++ b/docker/README.md @@ -5,7 +5,7 @@ This file describes the purpose of the different images. **TL;DR:** Use the [vitess/lite](https://hub.docker.com/r/vitess/lite/) image for running Vitess. Our Kubernetes Tutorial uses it as well. -Instead of using the `latest` tag, you can pin it to a known stable version e.g. `v2.0`. +Instead of using the `latest` tag, you can pin it to a known stable version e.g. `v4.0`. ## Principles @@ -37,24 +37,6 @@ Our list of images can be grouped into: All these Vitess images include a specific MySQL/MariaDB version ("flavor"). * We provide Dockerfile files for multiple flavors (`Dockerfile.`). - * As of April 2017, the following flavors are supported: `mariadb`, `mysql56`, `mysql57`, `percona`(56), `percona57` * On Docker Hub we publish only images with MySQL 5.7 to minimize maintenance overhead and avoid confusion. - * If you need an image for a different flavor, it is very easy to build it yourself. See the [Custom Docker Build instructions](https://vitess.io/getting-started/docker-build/). If you are looking for a stable version of Vitess, use the **lite** image with a fixed version. If you are looking for the latest Vitess code in binary form, use the "latest" tag of the **base** image. - -### Kubernetes Tutorial Dependencies - -| Image | How (When) Updated | Description | -| --- | --- | --- | -| **guestbook** | manual (updated with every Vitess release) | Vitess adaption of the Kubernetes guestbook example. Used to showcase sharding in Vitess. Dockerfile is located in [`examples/kubernetes/guestbook/`](https://github.com/vitessio/vitess/tree/master/examples/kubernetes/guestbook). | -| **orchestrator** | manual | Binaries for [Orchestrator](https://github.com/github/orchestrator). It can be used with Vitess for automatic failovers. Currently not part of the Kubernetes Tutorial and only used in tests. | - -### Internal Tools - -These images are used by the Vitess project for internal workflows and testing infrastructure and can be ignored by users. - -| Image | How (When) Updated | Description | -| --- | --- | --- | -| **publish-site** | manual | Contains [Jekyll](https://jekyllrb.com/) which we use to generate our [vitess.io](https://vitess.io) website from the Markdown files located in [doc/](https://github.com/vitessio/vitess/tree/master/doc). | -| **keytar** | manual | Keytar is a Vitess testing framework to run our Kubernetes cluster tests. Dockerfile is located in [`test/cluster/keytar/`](https://github.com/vitessio/vitess/tree/master/test/cluster/keytar). | diff --git a/docker/bootstrap/Dockerfile.common b/docker/bootstrap/Dockerfile.common index 4b6a21beb49..6a9255b38e7 100644 --- a/docker/bootstrap/Dockerfile.common +++ b/docker/bootstrap/Dockerfile.common @@ -14,7 +14,6 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins libtool \ make \ openjdk-8-jdk \ - pkg-config \ python-crypto \ python-dev \ python-mysqldb \ @@ -31,26 +30,19 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins && rm -rf /var/lib/apt/lists/* # Install Maven 3.1+ -RUN mkdir -p /vt/dist && \ - cd /vt/dist && \ +RUN mkdir -p /vt/src/vitess.io/vitess/dist && \ + cd /vt/src/vitess.io/vitess/dist && \ curl -sL --connect-timeout 10 --retry 3 \ http://www-us.apache.org/dist/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz | tar -xz && \ mv apache-maven-3.3.9 maven # Set up Vitess environment (equivalent to '. dev.env') -ENV VTTOP /vt/src/vitess.io/vitess -ENV VTROOT /vt -ENV GOTOP $VTTOP/go -ENV PYTOP $VTTOP/py -ENV VTDATAROOT $VTROOT/vtdataroot +ENV VTROOT /vt/src/vitess.io/vitess +ENV VTDATAROOT /vt/vtdataroot ENV VTPORTSTART 15000 ENV PYTHONPATH $VTROOT/dist/grpc/usr/local/lib/python2.7/site-packages:$VTROOT/dist/py-mock-1.0.1/lib/python2.7/site-packages:$VTROOT/py-vtdb:$VTROOT/dist/selenium/lib/python2.7/site-packages -ENV GOBIN $VTROOT/bin ENV PATH $VTROOT/bin:$VTROOT/dist/maven/bin:$VTROOT/dist/chromedriver:$PATH -ENV VT_MYSQL_ROOT /usr -ENV PKG_CONFIG_PATH $VTROOT/lib ENV USER vitess -ENV GO111MODULE on # Copy files needed for bootstrap COPY bootstrap.sh dev.env build.env go.mod go.sum /vt/src/vitess.io/vitess/ @@ -71,6 +63,10 @@ RUN cd /vt/src/vitess.io/vitess && \ # Create mount point for actual data (e.g. MySQL data dir) VOLUME /vt/vtdataroot +# The docker lite images copy from the builder in /vt/bin +# Add compatibility to the previous layout for now +RUN su vitess -c "mkdir -p /vt/src/vitess.io/vitess/bin && rm -rf /vt/bin && ln -s /vt/src/vitess.io/vitess/bin /vt/bin" + # If the user doesn't specify a command, load a shell. CMD ["/bin/bash"] diff --git a/docker/bootstrap/Dockerfile.mysql56 b/docker/bootstrap/Dockerfile.mysql56 index b07fddedb61..0cdb5ae84f2 100644 --- a/docker/bootstrap/Dockerfile.mysql56 +++ b/docker/bootstrap/Dockerfile.mysql56 @@ -1,7 +1,7 @@ FROM vitess/bootstrap:common # Install MySQL 5.6 -RUN for i in $(seq 1 10); do apt-key adv --no-tty --recv-keys --keyserver pool.sks-keyservers.net 5072E1F5 && break; done && \ +RUN for i in $(seq 1 10); do apt-key adv --no-tty --recv-keys --keyserver pool.sks-keyservers.net 8C718D3B5072E1F5 && break; done && \ add-apt-repository 'deb http://repo.mysql.com/apt/debian/ stretch mysql-5.6' && \ for i in $(seq 1 10); do apt-key adv --no-tty --keyserver keys.gnupg.net --recv-keys 9334A25F8507EFA5 && break; done && \ echo 'deb http://repo.percona.com/apt stretch main' > /etc/apt/sources.list.d/percona.list && \ @@ -17,6 +17,5 @@ RUN for i in $(seq 1 10); do apt-key adv --no-tty --recv-keys --keyserver pool.s # Bootstrap Vitess WORKDIR /vt/src/vitess.io/vitess -ENV MYSQL_FLAVOR MySQL56 USER vitess RUN ./bootstrap.sh diff --git a/docker/bootstrap/Dockerfile.mysql57 b/docker/bootstrap/Dockerfile.mysql57 index 2fb1f4e1aa5..7e0c5f99f96 100644 --- a/docker/bootstrap/Dockerfile.mysql57 +++ b/docker/bootstrap/Dockerfile.mysql57 @@ -2,7 +2,7 @@ FROM vitess/bootstrap:common # Install MySQL 5.7 RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends gnupg dirmngr ca-certificates && \ - for i in $(seq 1 10); do apt-key adv --no-tty --recv-keys --keyserver ha.pool.sks-keyservers.net 5072E1F5 && break; done && \ + for i in $(seq 1 10); do apt-key adv --no-tty --recv-keys --keyserver ha.pool.sks-keyservers.net 8C718D3B5072E1F5 && break; done && \ add-apt-repository 'deb http://repo.mysql.com/apt/debian/ stretch mysql-5.7' && \ for i in $(seq 1 10); do apt-key adv --no-tty --keyserver keys.gnupg.net --recv-keys 9334A25F8507EFA5 && break; done && \ echo 'deb http://repo.percona.com/apt stretch main' > /etc/apt/sources.list.d/percona.list && \ @@ -18,7 +18,5 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins # Bootstrap Vitess WORKDIR /vt/src/vitess.io/vitess - -ENV MYSQL_FLAVOR MySQL56 USER vitess -RUN ./bootstrap.sh \ No newline at end of file +RUN ./bootstrap.sh diff --git a/docker/bootstrap/Dockerfile.mysql57-arm64v8 b/docker/bootstrap/Dockerfile.mysql57-arm64v8 new file mode 100644 index 00000000000..6687307bdd8 --- /dev/null +++ b/docker/bootstrap/Dockerfile.mysql57-arm64v8 @@ -0,0 +1,62 @@ +FROM debian:9 AS builder + +WORKDIR /opt +#Build xtrabackup +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + autoconf \ + automake \ + bison \ + build-essential \ + bzr \ + ca-certificates \ + cmake \ + flex \ + libaio-dev \ + libcurl4-gnutls-dev \ + libev-dev \ + libgcrypt11-dev \ + libncurses-dev \ + libtool \ + mysql-client \ + vim-common \ + wget \ + zlib1g-dev && \ + wget https://github.com/percona/percona-xtrabackup/archive/percona-xtrabackup-2.4.13.tar.gz \ + -P /opt && \ + tar zxf /opt/percona-xtrabackup-2.4.13.tar.gz -C /opt && \ + rm /opt/percona-xtrabackup-2.4.13.tar.gz && \ + cd /opt/percona-xtrabackup-percona-xtrabackup-2.4.13 && \ + mkdir bld && cd bld && \ + cmake .. -DBUILD_CONFIG=xtrabackup_release -DWITH_MAN_PAGES=OFF \ + -DDOWNLOAD_BOOST=1 -DWITH_BOOST=/usr/local && \ + make -j4 && \ + make install + +FROM vitess/bootstrap:common + +# Install MySQL 5.7 +RUN add-apt-repository 'deb http://ftp.debian.org/debian sid main' && \ + apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + libmysqlclient-dev \ + mysql-client-5.7 \ + mysql-server-5.7 \ + libdbd-mysql-perl \ + python3-distutils-extra \ + rsync \ + libev4 \ + libcurl4-openssl-dev \ + libaio1 && \ + rm -rf /var/lib/apt/lists/* && \ + mkdir -p /usr/local/xtrabackup/bin && \ + mkdir -p /usr/local/xtrabackup/lib + +# Bootstrap Vitess +WORKDIR /vt/src/vitess.io/vitess +COPY --from=builder /usr/local/xtrabackup/bin /usr/local/xtrabackup/bin +COPY --from=builder /usr/local/xtrabackup/lib /usr/local/xtrabackup/lib +ENV PATH="/usr/local/xtrabackup/bin:${PATH}" +ENV MYSQL_FLAVOR MySQL56 +USER vitess +RUN ./bootstrap.sh diff --git a/docker/bootstrap/Dockerfile.mysql80 b/docker/bootstrap/Dockerfile.mysql80 index ec53895165f..0523a7847cc 100644 --- a/docker/bootstrap/Dockerfile.mysql80 +++ b/docker/bootstrap/Dockerfile.mysql80 @@ -17,7 +17,6 @@ RUN for i in $(seq 1 10); do apt-key adv --no-tty --recv-keys --keyserver ha.poo # Bootstrap Vitess WORKDIR /vt/src/vitess.io/vitess - ENV MYSQL_FLAVOR MySQL80 USER vitess -RUN ./bootstrap.sh \ No newline at end of file +RUN ./bootstrap.sh diff --git a/docker/bootstrap/Dockerfile.percona b/docker/bootstrap/Dockerfile.percona index 6d13fa4dfb0..910d3be10b1 100644 --- a/docker/bootstrap/Dockerfile.percona +++ b/docker/bootstrap/Dockerfile.percona @@ -16,6 +16,5 @@ RUN for i in $(seq 1 10); do apt-key adv --no-tty --keyserver keys.gnupg.net --r # Bootstrap Vitess WORKDIR /vt/src/vitess.io/vitess -ENV MYSQL_FLAVOR MySQL56 USER vitess RUN ./bootstrap.sh diff --git a/docker/bootstrap/Dockerfile.percona57 b/docker/bootstrap/Dockerfile.percona57 index 6ed54c76923..54c8477ffb6 100644 --- a/docker/bootstrap/Dockerfile.percona57 +++ b/docker/bootstrap/Dockerfile.percona57 @@ -17,6 +17,5 @@ RUN for i in $(seq 1 10); do apt-key adv --no-tty --keyserver keys.gnupg.net --r # Bootstrap Vitess WORKDIR /vt/src/vitess.io/vitess -ENV MYSQL_FLAVOR MySQL56 USER vitess RUN ./bootstrap.sh diff --git a/docker/bootstrap/build.sh b/docker/bootstrap/build.sh index 0a3a48c1253..699f0627618 100755 --- a/docker/bootstrap/build.sh +++ b/docker/bootstrap/build.sh @@ -29,4 +29,8 @@ fi # To avoid AUFS permission issues, files must allow access by "other" chmod -R o=g * -docker build --no-cache -f docker/bootstrap/Dockerfile.$flavor -t vitess/bootstrap:$flavor . +arch=$(uname -m) +[ "$arch" == "aarch64" ] && [ $flavor != "common" ] && arch_ext='-arm64v8' +if [ -f "docker/bootstrap/Dockerfile.$flavor$arch_ext" ]; then + docker build --no-cache -f docker/bootstrap/Dockerfile.$flavor$arch_ext -t vitess/bootstrap:$flavor$arch_ext . +fi diff --git a/docker/k8s/Dockerfile b/docker/k8s/Dockerfile index ddafcd95af7..391c352e4f8 100644 --- a/docker/k8s/Dockerfile +++ b/docker/k8s/Dockerfile @@ -25,9 +25,8 @@ RUN apt-get update && \ rm -rf /var/lib/apt/lists/* # Set up Vitess environment (just enough to run pre-built Go binaries) -ENV VTROOT /vt +ENV VTROOT /vt/src/vitess.io/vitess ENV VTDATAROOT /vtdataroot -ENV VTTOP /vt/src/vitess.io/vitess # Prepare directory structure. RUN mkdir -p /vt && \ @@ -50,13 +49,13 @@ COPY --from=base /vt/bin/vtworker /vt/bin/ COPY --from=base /vt/bin/vtbackup /vt/bin/ # copy web admin files -COPY --from=base $VTTOP/web /vt/web/ +COPY --from=base $VTROOT/web /vt/web/ # copy vitess config -COPY --from=base $VTTOP/config/init_db.sql /vt/config/ +COPY --from=base $VTROOT/config/init_db.sql /vt/config/ # my.cnf include files -COPY --from=base $VTTOP/config/mycnf /vt/config/mycnf +COPY --from=base $VTROOT/config/mycnf /vt/config/mycnf # add vitess user and add permissions RUN groupadd -r --gid 2000 vitess && useradd -r -g vitess --uid 1000 vitess && \ diff --git a/docker/k8s/vtctlclient/Dockerfile b/docker/k8s/vtctlclient/Dockerfile index 1b1b9be3bc3..0cf4956691d 100644 --- a/docker/k8s/vtctlclient/Dockerfile +++ b/docker/k8s/vtctlclient/Dockerfile @@ -1,11 +1,11 @@ # Copyright 2019 The Vitess Authors. -# +# # 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. @@ -28,5 +28,5 @@ COPY --from=k8s /vt/bin/vtctlclient /usr/bin/ # add vitess user/group and add permissions RUN groupadd -r --gid 2000 vitess && \ useradd -r -g vitess --uid 1000 vitess - + CMD ["/usr/bin/vtctlclient"] diff --git a/docker/lite/Dockerfile b/docker/lite/Dockerfile deleted file mode 100644 index 55ca5f969f9..00000000000 --- a/docker/lite/Dockerfile +++ /dev/null @@ -1,80 +0,0 @@ -# Copyright 2019 The Vitess Authors. -# -# 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. - -FROM vitess/base AS builder -FROM debian:stretch-slim AS staging - -RUN mkdir -p /vt/vtdataroot/ \ - && mkdir -p /vt/bin \ - && mkdir -p /vt/src/vitess.io/vitess/web/vtctld2 \ - && groupadd -r vitess && useradd -r -g vitess vitess - -COPY --from=builder /vt/src/vitess.io/vitess/web/vtctld /vt/src/vitess.io/vitess/web/vtctld -COPY --from=builder /vt/src/vitess.io/vitess/web/vtctld2/app /vt/src/vitess.io/vitess/web/vtctld2/app -COPY --from=builder /vt/src/vitess.io/vitess/config /vt/config -COPY --from=builder /vt/bin/mysqlctld /vt/bin/ -COPY --from=builder /vt/bin/vtctld /vt/bin/ -COPY --from=builder /vt/bin/vtctlclient /vt/bin/ -COPY --from=builder /vt/bin/vtgate /vt/bin/ -COPY --from=builder /vt/bin/vttablet /vt/bin/ -COPY --from=builder /vt/bin/vtworker /vt/bin/ -COPY --from=builder /vt/bin/vtbackup /vt/bin/ - -RUN chown -R vitess:vitess /vt - -FROM debian:stretch-slim - -# Install dependencies -RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ - gnupg dirmngr ca-certificates wget libdbd-mysql-perl rsync libaio1 libatomic1 libcurl3 libev4 \ - && for i in $(seq 1 10); do apt-key adv --no-tty --recv-keys --keyserver keyserver.ubuntu.com 8C718D3B5072E1F5 && break; done \ - && echo 'deb http://repo.mysql.com/apt/debian/ stretch mysql-5.7' > /etc/apt/sources.list.d/mysql.list \ - && for i in $(seq 1 10); do apt-key adv --no-tty --keyserver keys.gnupg.net --recv-keys 9334A25F8507EFA5 && break; done \ - && echo 'deb http://repo.percona.com/apt stretch main' > /etc/apt/sources.list.d/percona.list && \ - { \ - echo debconf debconf/frontend select Noninteractive; \ - echo percona-server-server-5.7 percona-server-server/root_password password 'unused'; \ - echo percona-server-server-5.7 percona-server-server/root_password_again password 'unused'; \ - } | debconf-set-selections \ - && apt-get update \ - && DEBIAN_FRONTEND=noninteractive \ - apt-get install -y --no-install-recommends \ - bzip2 \ - libmysqlclient20 \ - mysql-client \ - mysql-server \ - libjemalloc1 \ - libtcmalloc-minimal4 \ - percona-xtrabackup-24 \ - && rm -rf /var/lib/apt/lists/* \ - && groupadd -r vitess && useradd -r -g vitess vitess - -# Set up Vitess environment (just enough to run pre-built Go binaries) -ENV VTTOP /vt/src/vitess.io/vitess -ENV VTROOT /vt -ENV GOTOP $VTTOP/go -ENV VTDATAROOT $VTROOT/vtdataroot -ENV GOBIN $VTROOT/bin -ENV GOPATH $VTROOT -ENV PATH $VTROOT/bin:$PATH -ENV VT_MYSQL_ROOT /usr -ENV PKG_CONFIG_PATH $VTROOT/lib -ENV MYSQL_FLAVOR MySQL56 - -# Copy binaries (placed by build.sh) -COPY --from=staging /vt/ /vt/ - -# Create mount point for actual data (e.g. MySQL data dir) -VOLUME /vt/vtdataroot -USER vitess diff --git a/docker/lite/Dockerfile b/docker/lite/Dockerfile new file mode 120000 index 00000000000..c0929ac9ed2 --- /dev/null +++ b/docker/lite/Dockerfile @@ -0,0 +1 @@ +Dockerfile.mysql57 \ No newline at end of file diff --git a/docker/lite/Dockerfile.alpine b/docker/lite/Dockerfile.alpine index f3d282163a9..4082bb04b67 100644 --- a/docker/lite/Dockerfile.alpine +++ b/docker/lite/Dockerfile.alpine @@ -1,39 +1,54 @@ -# This image is only meant to be built from within the build.sh script. -FROM vitess/base AS builder -FROM alpine:3.8 AS staging - -RUN mkdir -p /vt/vtdataroot/ && mkdir -p /vt/bin && mkdir -p /vt/src/vitess.io/vitess/web/vtctld2 - -COPY --from=builder /vt/src/vitess.io/vitess/web/vtctld /vt/src/vitess.io/vitess/web/vtctld -COPY --from=builder /vt/src/vitess.io/vitess/web/vtctld2/app /vt/src/vitess.io/vitess/web/vtctld2/app -COPY --from=builder /vt/src/vitess.io/vitess/config /vt/config -COPY --from=builder /vt/bin/mysqlctld /vt/bin/ -COPY --from=builder /vt/bin/vtctld /vt/bin/ -COPY --from=builder /vt/bin/vtctlclient /vt/bin/ -COPY --from=builder /vt/bin/vtgate /vt/bin/ -COPY --from=builder /vt/bin/vttablet /vt/bin/ -COPY --from=builder /vt/bin/vtworker /vt/bin/ -COPY --from=builder /vt/bin/vtbackup /vt/bin/ +# Copyright 2019 The Vitess Authors. +# +# 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. +# NOTE: We have to build the Vitess binaries from scratch instead of sharing +# a base image because Docker Hub dropped the feature we relied upon to +# ensure images contain the right binaries. + +# Use a temporary layer for the build stage. +FROM vitess/bootstrap:mariadb103 AS builder + +# Allows some docker builds to disable CGO +ARG CGO_ENABLED=0 + +# Re-copy sources from working tree. +COPY --chown=vitess:vitess . /vt/src/vitess.io/vitess + +# Build and install Vitess in a temporary output directory. +USER vitess +RUN make install PREFIX=/vt/install + +# Start over and build the final image. FROM alpine:3.8 # Install dependencies RUN echo '@edge http://nl.alpinelinux.org/alpine/edge/main' >> /etc/apk/repositories && \ apk add --no-cache mariadb@edge mariadb-client@edge bzip2 bash +# Set up Vitess user and directory tree. +RUN addgroup -S vitess && adduser -S -G vitess vitess +RUN mkdir -p /vt/vtdataroot && chown -R vitess:vitess /vt + # Set up Vitess environment (just enough to run pre-built Go binaries) -ENV VTTOP /vt/src/vitess.io/vitess -ENV VTROOT /vt -ENV GOTOP $VTTOP/go -ENV VTDATAROOT $VTROOT/vtdataroot -ENV GOBIN $VTROOT/bin -ENV GOPATH $VTROOT +ENV VTROOT /vt/src/vitess.io/vitess +ENV VTDATAROOT /vt/vtdataroot ENV PATH $VTROOT/bin:$PATH -ENV VT_MYSQL_ROOT /usr -ENV PKG_CONFIG_PATH $VTROOT/lib ENV MYSQL_FLAVOR MariaDB103 -# Create vitess user -RUN addgroup -S vitess && adduser -S -G vitess vitess && mkdir -p /vt -COPY --from=staging /vt/ /vt/ +# Copy artifacts from builder layer. +COPY --from=builder --chown=vitess:vitess /vt/install /vt + +# Create mount point for actual data (e.g. MySQL data dir) +VOLUME /vt/vtdataroot USER vitess diff --git a/docker/lite/Dockerfile.mariadb b/docker/lite/Dockerfile.mariadb index cea94d615e5..ce9c8cf4b4f 100644 --- a/docker/lite/Dockerfile.mariadb +++ b/docker/lite/Dockerfile.mariadb @@ -1,51 +1,53 @@ -FROM vitess/base AS builder -FROM debian:stretch-slim AS staging - -RUN mkdir -p /vt/vtdataroot/ \ - && mkdir -p /vt/bin \ - && mkdir -p /vt/src/vitess.io/vitess/web/vtctld2 \ - && groupadd -r vitess && useradd -r -g vitess vitess - -COPY --from=builder /vt/src/vitess.io/vitess/web/vtctld /vt/src/vitess.io/vitess/web/vtctld -COPY --from=builder /vt/src/vitess.io/vitess/web/vtctld2/app /vt/src/vitess.io/vitess/web/vtctld2/app -COPY --from=builder /vt/src/vitess.io/vitess/config /vt/config -COPY --from=builder /vt/bin/mysqlctld /vt/bin/ -COPY --from=builder /vt/bin/vtctld /vt/bin/ -COPY --from=builder /vt/bin/vtctlclient /vt/bin/ -COPY --from=builder /vt/bin/vtgate /vt/bin/ -COPY --from=builder /vt/bin/vttablet /vt/bin/ -COPY --from=builder /vt/bin/vtworker /vt/bin/ -COPY --from=builder /vt/bin/vtbackup /vt/bin/ - -RUN chown -R vitess:vitess /vt +# Copyright 2019 The Vitess Authors. +# +# 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. + +# NOTE: We have to build the Vitess binaries from scratch instead of sharing +# a base image because Docker Hub dropped the feature we relied upon to +# ensure images contain the right binaries. + +# Use a temporary layer for the build stage. +FROM vitess/bootstrap:mariadb AS builder + +# Allows some docker builds to disable CGO +ARG CGO_ENABLED=0 + +# Re-copy sources from working tree. +COPY --chown=vitess:vitess . /vt/src/vitess.io/vitess + +# Build and install Vitess in a temporary output directory. +USER vitess +RUN make install PREFIX=/vt/install +# Start over and build the final image. FROM debian:stretch-slim # Install dependencies -RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends gnupg dirmngr ca-certificates \ - && for i in $(seq 1 10); do apt-key adv --no-tty --recv-keys --keyserver keyserver.ubuntu.com 0xF1656F24C74CD1D8 && break; done \ - && echo 'deb http://sfo1.mirrors.digitalocean.com/mariadb/repo/10.2/debian stretch main' > /etc/apt/sources.list.d/mariadb.list \ - && apt-get update \ - && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ - bzip2 \ - mariadb-server \ - && rm -rf /var/lib/apt/lists/* \ - && groupadd -r vitess && useradd -r -g vitess vitess +COPY docker/lite/install_dependencies.sh /vt/dist/install_dependencies.sh +RUN /vt/dist/install_dependencies.sh mariadb + +# Set up Vitess user and directory tree. +RUN groupadd -r vitess && useradd -r -g vitess vitess +RUN mkdir -p /vt/vtdataroot && chown -R vitess:vitess /vt # Set up Vitess environment (just enough to run pre-built Go binaries) -ENV VTTOP /vt/src/vitess.io/vitess -ENV VTROOT /vt -ENV GOTOP $VTTOP/go -ENV VTDATAROOT $VTROOT/vtdataroot -ENV GOBIN $VTROOT/bin -ENV GOPATH $VTROOT +ENV VTROOT /vt/src/vitess.io/vitess +ENV VTDATAROOT /vt/vtdataroot ENV PATH $VTROOT/bin:$PATH -ENV VT_MYSQL_ROOT /usr -ENV PKG_CONFIG_PATH $VTROOT/lib ENV MYSQL_FLAVOR MariaDB -# Copy binaries (placed by build.sh) -COPY --from=staging /vt/ /vt/ +# Copy artifacts from builder layer. +COPY --from=builder --chown=vitess:vitess /vt/install /vt # Create mount point for actual data (e.g. MySQL data dir) VOLUME /vt/vtdataroot diff --git a/docker/lite/Dockerfile.mariadb103 b/docker/lite/Dockerfile.mariadb103 index 4ff440d3d86..f0833f81f51 100644 --- a/docker/lite/Dockerfile.mariadb103 +++ b/docker/lite/Dockerfile.mariadb103 @@ -1,50 +1,53 @@ -FROM vitess/base AS builder -FROM debian:stretch-slim AS staging - -RUN mkdir -p /vt/vtdataroot/ \ - && mkdir -p /vt/bin \ - && mkdir -p /vt/src/vitess.io/vitess/web/vtctld2 \ - && groupadd -r vitess && useradd -r -g vitess vitess - -COPY --from=builder /vt/src/vitess.io/vitess/web/vtctld /vt/src/vitess.io/vitess/web/vtctld -COPY --from=builder /vt/src/vitess.io/vitess/web/vtctld2/app /vt/src/vitess.io/vitess/web/vtctld2/app -COPY --from=builder /vt/src/vitess.io/vitess/config /vt/config -COPY --from=builder /vt/bin/mysqlctld /vt/bin/ -COPY --from=builder /vt/bin/vtctld /vt/bin/ -COPY --from=builder /vt/bin/vtctlclient /vt/bin/ -COPY --from=builder /vt/bin/vtgate /vt/bin/ -COPY --from=builder /vt/bin/vttablet /vt/bin/ -COPY --from=builder /vt/bin/vtworker /vt/bin/ -COPY --from=builder /vt/bin/vtbackup /vt/bin/ -RUN chown -R vitess:vitess /vt +# Copyright 2019 The Vitess Authors. +# +# 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. +# NOTE: We have to build the Vitess binaries from scratch instead of sharing +# a base image because Docker Hub dropped the feature we relied upon to +# ensure images contain the right binaries. + +# Use a temporary layer for the build stage. +FROM vitess/bootstrap:mariadb103 AS builder + +# Allows some docker builds to disable CGO +ARG CGO_ENABLED=0 + +# Re-copy sources from working tree. +COPY --chown=vitess:vitess . /vt/src/vitess.io/vitess + +# Build and install Vitess in a temporary output directory. +USER vitess +RUN make install PREFIX=/vt/install + +# Start over and build the final image. FROM debian:stretch-slim # Install dependencies -RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends gnupg dirmngr ca-certificates \ - && for i in $(seq 1 10); do apt-key adv --no-tty --recv-keys --keyserver keyserver.ubuntu.com 0xF1656F24C74CD1D8 && break; done \ - && echo 'deb http://sfo1.mirrors.digitalocean.com/mariadb/repo/10.3/debian stretch main' > /etc/apt/sources.list.d/mariadb.list \ - && apt-get update \ - && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ - bzip2 \ - mariadb-server \ - && rm -rf /var/lib/apt/lists/* \ - && groupadd -r vitess && useradd -r -g vitess vitess +COPY docker/lite/install_dependencies.sh /vt/dist/install_dependencies.sh +RUN /vt/dist/install_dependencies.sh mariadb103 + +# Set up Vitess user and directory tree. +RUN groupadd -r vitess && useradd -r -g vitess vitess +RUN mkdir -p /vt/vtdataroot && chown -R vitess:vitess /vt # Set up Vitess environment (just enough to run pre-built Go binaries) -ENV VTTOP /vt/src/vitess.io/vitess -ENV VTROOT /vt -ENV GOTOP $VTTOP/go -ENV VTDATAROOT $VTROOT/vtdataroot -ENV GOBIN $VTROOT/bin -ENV GOPATH $VTROOT +ENV VTROOT /vt/src/vitess.io/vitess +ENV VTDATAROOT /vt/vtdataroot ENV PATH $VTROOT/bin:$PATH -ENV VT_MYSQL_ROOT /usr -ENV PKG_CONFIG_PATH $VTROOT/lib ENV MYSQL_FLAVOR MariaDB103 -# Copy binaries (placed by build.sh) -COPY --from=staging /vt/ /vt/ +# Copy artifacts from builder layer. +COPY --from=builder --chown=vitess:vitess /vt/install /vt # Create mount point for actual data (e.g. MySQL data dir) VOLUME /vt/vtdataroot diff --git a/docker/lite/Dockerfile.mysql56 b/docker/lite/Dockerfile.mysql56 index f3d6b3dcb7a..7b78af0aa89 100644 --- a/docker/lite/Dockerfile.mysql56 +++ b/docker/lite/Dockerfile.mysql56 @@ -1,54 +1,52 @@ -FROM vitess/base AS builder -FROM debian:stretch-slim AS staging - -RUN mkdir -p /vt/vtdataroot/ \ - && mkdir -p /vt/bin \ - && mkdir -p /vt/src/vitess.io/vitess/web/vtctld2 \ - && groupadd -r vitess && useradd -r -g vitess vitess - -COPY --from=builder /vt/src/vitess.io/vitess/web/vtctld /vt/src/vitess.io/vitess/web/vtctld -COPY --from=builder /vt/src/vitess.io/vitess/web/vtctld2/app /vt/src/vitess.io/vitess/web/vtctld2/app -COPY --from=builder /vt/src/vitess.io/vitess/config /vt/config -COPY --from=builder /vt/bin/mysqlctld /vt/bin/ -COPY --from=builder /vt/bin/vtctld /vt/bin/ -COPY --from=builder /vt/bin/vtctlclient /vt/bin/ -COPY --from=builder /vt/bin/vtgate /vt/bin/ -COPY --from=builder /vt/bin/vttablet /vt/bin/ -COPY --from=builder /vt/bin/vtworker /vt/bin/ -COPY --from=builder /vt/bin/vtbackup /vt/bin/ - -RUN chown -R vitess:vitess /vt +# Copyright 2019 The Vitess Authors. +# +# 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. + +# NOTE: We have to build the Vitess binaries from scratch instead of sharing +# a base image because Docker Hub dropped the feature we relied upon to +# ensure images contain the right binaries. + +# Use a temporary layer for the build stage. +FROM vitess/bootstrap:mysql56 AS builder + +# Allows some docker builds to disable CGO +ARG CGO_ENABLED=0 + +# Re-copy sources from working tree. +COPY --chown=vitess:vitess . /vt/src/vitess.io/vitess + +# Build and install Vitess in a temporary output directory. +USER vitess +RUN make install PREFIX=/vt/install +# Start over and build the final image. FROM debian:stretch-slim # Install dependencies -RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends gnupg dirmngr ca-certificates \ - && for i in $(seq 1 10); do apt-key adv --no-tty --recv-keys --keyserver keyserver.ubuntu.com 8C718D3B5072E1F5 && break; done \ - && echo 'deb http://repo.mysql.com/apt/debian/ stretch mysql-5.6' > /etc/apt/sources.list.d/mysql.list \ - && apt-get update \ - && DEBIAN_FRONTEND=noninteractive \ - apt-get install -y --no-install-recommends \ - bzip2 \ - libmysqlclient18 \ - mysql-client \ - mysql-server \ - && rm -rf /var/lib/apt/lists/* \ - && groupadd -r vitess && useradd -r -g vitess vitess +COPY docker/lite/install_dependencies.sh /vt/dist/install_dependencies.sh +RUN /vt/dist/install_dependencies.sh mysql56 + +# Set up Vitess user and directory tree. +RUN groupadd -r vitess && useradd -r -g vitess vitess +RUN mkdir -p /vt/vtdataroot && chown -R vitess:vitess /vt # Set up Vitess environment (just enough to run pre-built Go binaries) -ENV VTTOP /vt/src/vitess.io/vitess -ENV VTROOT /vt -ENV GOTOP $VTTOP/go -ENV VTDATAROOT $VTROOT/vtdataroot -ENV GOBIN $VTROOT/bin -ENV GOPATH $VTROOT +ENV VTROOT /vt/src/vitess.io/vitess +ENV VTDATAROOT /vt/vtdataroot ENV PATH $VTROOT/bin:$PATH -ENV VT_MYSQL_ROOT /usr -ENV PKG_CONFIG_PATH $VTROOT/lib -ENV MYSQL_FLAVOR MySQL56 -# Copy binaries (placed by build.sh) -COPY --from=staging /vt/ /vt/ +# Copy artifacts from builder layer. +COPY --from=builder --chown=vitess:vitess /vt/install /vt # Create mount point for actual data (e.g. MySQL data dir) VOLUME /vt/vtdataroot diff --git a/docker/lite/Dockerfile.mysql57 b/docker/lite/Dockerfile.mysql57 index 78318e5c652..25535464af8 100644 --- a/docker/lite/Dockerfile.mysql57 +++ b/docker/lite/Dockerfile.mysql57 @@ -1,54 +1,52 @@ -FROM vitess/base AS builder -FROM debian:stretch-slim AS staging - -RUN mkdir -p /vt/vtdataroot/ \ - && mkdir -p /vt/bin \ - && mkdir -p /vt/src/vitess.io/vitess/web/vtctld2 \ - && groupadd -r vitess && useradd -r -g vitess vitess - -COPY --from=builder /vt/src/vitess.io/vitess/web/vtctld /vt/src/vitess.io/vitess/web/vtctld -COPY --from=builder /vt/src/vitess.io/vitess/web/vtctld2/app /vt/src/vitess.io/vitess/web/vtctld2/app -COPY --from=builder /vt/src/vitess.io/vitess/config /vt/config -COPY --from=builder /vt/bin/mysqlctld /vt/bin/ -COPY --from=builder /vt/bin/vtctld /vt/bin/ -COPY --from=builder /vt/bin/vtctlclient /vt/bin/ -COPY --from=builder /vt/bin/vtgate /vt/bin/ -COPY --from=builder /vt/bin/vttablet /vt/bin/ -COPY --from=builder /vt/bin/vtworker /vt/bin/ -COPY --from=builder /vt/bin/vtbackup /vt/bin/ - -RUN chown -R vitess:vitess /vt +# Copyright 2019 The Vitess Authors. +# +# 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. + +# NOTE: We have to build the Vitess binaries from scratch instead of sharing +# a base image because Docker Hub dropped the feature we relied upon to +# ensure images contain the right binaries. + +# Use a temporary layer for the build stage. +FROM vitess/bootstrap:mysql57 AS builder + +# Allows some docker builds to disable CGO +ARG CGO_ENABLED=0 + +# Re-copy sources from working tree. +COPY --chown=vitess:vitess . /vt/src/vitess.io/vitess + +# Build and install Vitess in a temporary output directory. +USER vitess +RUN make install PREFIX=/vt/install +# Start over and build the final image. FROM debian:stretch-slim # Install dependencies -RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends gnupg dirmngr ca-certificates \ - && for i in $(seq 1 10); do apt-key adv --no-tty --recv-keys --keyserver keyserver.ubuntu.com 8C718D3B5072E1F5 && break; done \ - && echo 'deb http://repo.mysql.com/apt/debian/ stretch mysql-5.7' > /etc/apt/sources.list.d/mysql.list \ - && apt-get update \ - && DEBIAN_FRONTEND=noninteractive \ - apt-get install -y --no-install-recommends \ - bzip2 \ - libmysqlclient20 \ - mysql-client \ - mysql-server \ - && rm -rf /var/lib/apt/lists/* \ - && groupadd -r vitess && useradd -r -g vitess vitess +COPY docker/lite/install_dependencies.sh /vt/dist/install_dependencies.sh +RUN /vt/dist/install_dependencies.sh mysql57 + +# Set up Vitess user and directory tree. +RUN groupadd -r vitess && useradd -r -g vitess vitess +RUN mkdir -p /vt/vtdataroot && chown -R vitess:vitess /vt # Set up Vitess environment (just enough to run pre-built Go binaries) -ENV VTTOP /vt/src/vitess.io/vitess -ENV VTROOT /vt -ENV GOTOP $VTTOP/go -ENV VTDATAROOT $VTROOT/vtdataroot -ENV GOBIN $VTROOT/bin -ENV GOPATH $VTROOT +ENV VTROOT /vt/src/vitess.io/vitess +ENV VTDATAROOT /vt/vtdataroot ENV PATH $VTROOT/bin:$PATH -ENV VT_MYSQL_ROOT /usr -ENV PKG_CONFIG_PATH $VTROOT/lib -ENV MYSQL_FLAVOR MySQL56 -# Copy binaries (placed by build.sh) -COPY --from=staging /vt/ /vt/ +# Copy artifacts from builder layer. +COPY --from=builder --chown=vitess:vitess /vt/install /vt # Create mount point for actual data (e.g. MySQL data dir) VOLUME /vt/vtdataroot diff --git a/docker/lite/Dockerfile.mysql80 b/docker/lite/Dockerfile.mysql80 index fb71b6f6b56..4d0ad6d6ec8 100644 --- a/docker/lite/Dockerfile.mysql80 +++ b/docker/lite/Dockerfile.mysql80 @@ -1,54 +1,53 @@ -FROM vitess/base AS builder -FROM debian:stretch-slim AS staging - -RUN mkdir -p /vt/vtdataroot/ \ - && mkdir -p /vt/bin \ - && mkdir -p /vt/src/vitess.io/vitess/web/vtctld2 \ - && groupadd -r vitess && useradd -r -g vitess vitess - -COPY --from=builder /vt/src/vitess.io/vitess/web/vtctld /vt/src/vitess.io/vitess/web/vtctld -COPY --from=builder /vt/src/vitess.io/vitess/web/vtctld2/app /vt/src/vitess.io/vitess/web/vtctld2/app -COPY --from=builder /vt/src/vitess.io/vitess/config /vt/config -COPY --from=builder /vt/bin/mysqlctld /vt/bin/ -COPY --from=builder /vt/bin/vtctld /vt/bin/ -COPY --from=builder /vt/bin/vtctlclient /vt/bin/ -COPY --from=builder /vt/bin/vtgate /vt/bin/ -COPY --from=builder /vt/bin/vttablet /vt/bin/ -COPY --from=builder /vt/bin/vtworker /vt/bin/ -COPY --from=builder /vt/bin/vtbackup /vt/bin/ - -RUN chown -R vitess:vitess /vt +# Copyright 2019 The Vitess Authors. +# +# 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. + +# NOTE: We have to build the Vitess binaries from scratch instead of sharing +# a base image because Docker Hub dropped the feature we relied upon to +# ensure images contain the right binaries. + +# Use a temporary layer for the build stage. +FROM vitess/bootstrap:mysql80 AS builder + +# Allows some docker builds to disable CGO +ARG CGO_ENABLED=0 + +# Re-copy sources from working tree. +COPY --chown=vitess:vitess . /vt/src/vitess.io/vitess + +# Build and install Vitess in a temporary output directory. +USER vitess +RUN make install PREFIX=/vt/install +# Start over and build the final image. FROM debian:stretch-slim # Install dependencies -RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends gnupg dirmngr ca-certificates \ - && for i in $(seq 1 10); do apt-key adv --no-tty --recv-keys --keyserver keyserver.ubuntu.com 8C718D3B5072E1F5 && break; done \ - && echo 'deb http://repo.mysql.com/apt/debian/ stretch mysql-8.0' > /etc/apt/sources.list.d/mysql.list \ - && apt-get update \ - && DEBIAN_FRONTEND=noninteractive \ - apt-get install -y --no-install-recommends \ - bzip2 \ - libmysqlclient21 \ - mysql-client \ - mysql-server \ - && rm -rf /var/lib/apt/lists/* \ - && groupadd -r vitess && useradd -r -g vitess vitess +COPY docker/lite/install_dependencies.sh /vt/dist/install_dependencies.sh +RUN /vt/dist/install_dependencies.sh mysql80 + +# Set up Vitess user and directory tree. +RUN groupadd -r vitess && useradd -r -g vitess vitess +RUN mkdir -p /vt/vtdataroot && chown -R vitess:vitess /vt # Set up Vitess environment (just enough to run pre-built Go binaries) -ENV VTTOP /vt/src/vitess.io/vitess -ENV VTROOT /vt -ENV GOTOP $VTTOP/go -ENV VTDATAROOT $VTROOT/vtdataroot -ENV GOBIN $VTROOT/bin -ENV GOPATH $VTROOT +ENV VTROOT /vt/src/vitess.io/vitess +ENV VTDATAROOT /vt/vtdataroot ENV PATH $VTROOT/bin:$PATH -ENV VT_MYSQL_ROOT /usr -ENV PKG_CONFIG_PATH $VTROOT/lib -ENV MYSQL_FLAVOR MySQL56 +ENV MYSQL_FLAVOR MySQL80 -# Copy binaries (placed by build.sh) -COPY --from=staging /vt/ /vt/ +# Copy artifacts from builder layer. +COPY --from=builder --chown=vitess:vitess /vt/install /vt # Create mount point for actual data (e.g. MySQL data dir) VOLUME /vt/vtdataroot diff --git a/docker/lite/Dockerfile.percona b/docker/lite/Dockerfile.percona index e8d127dc56f..a3e77350672 100644 --- a/docker/lite/Dockerfile.percona +++ b/docker/lite/Dockerfile.percona @@ -1,56 +1,52 @@ -FROM vitess/base AS builder -FROM debian:stretch-slim AS staging - -RUN mkdir -p /vt/vtdataroot/ \ - && mkdir -p /vt/bin \ - && mkdir -p /vt/src/vitess.io/vitess/web/vtctld2 \ - && groupadd -r vitess && useradd -r -g vitess vitess - -COPY --from=builder /vt/src/vitess.io/vitess/web/vtctld /vt/src/vitess.io/vitess/web/vtctld -COPY --from=builder /vt/src/vitess.io/vitess/web/vtctld2/app /vt/src/vitess.io/vitess/web/vtctld2/app -COPY --from=builder /vt/src/vitess.io/vitess/config /vt/config -COPY --from=builder /vt/bin/mysqlctld /vt/bin/ -COPY --from=builder /vt/bin/vtctld /vt/bin/ -COPY --from=builder /vt/bin/vtctlclient /vt/bin/ -COPY --from=builder /vt/bin/vtgate /vt/bin/ -COPY --from=builder /vt/bin/vttablet /vt/bin/ -COPY --from=builder /vt/bin/vtworker /vt/bin/ -COPY --from=builder /vt/bin/vtbackup /vt/bin/ - -RUN chown -R vitess:vitess /vt +# Copyright 2019 The Vitess Authors. +# +# 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. + +# NOTE: We have to build the Vitess binaries from scratch instead of sharing +# a base image because Docker Hub dropped the feature we relied upon to +# ensure images contain the right binaries. + +# Use a temporary layer for the build stage. +FROM vitess/bootstrap:percona AS builder + +# Allows some docker builds to disable CGO +ARG CGO_ENABLED=0 + +# Re-copy sources from working tree. +COPY --chown=vitess:vitess . /vt/src/vitess.io/vitess + +# Build and install Vitess in a temporary output directory. +USER vitess +RUN make install PREFIX=/vt/install +# Start over and build the final image. FROM debian:stretch-slim # Install dependencies -RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends gnupg dirmngr ca-certificates \ - && for i in $(seq 1 10); do apt-key adv --no-tty --recv-keys --keyserver keys.gnupg.net 9334A25F8507EFA5 && break; done \ - && echo 'deb http://repo.percona.com/apt stretch main' > /etc/apt/sources.list.d/percona.list && \ - { \ - echo debconf debconf/frontend select Noninteractive; \ - echo percona-server-server-5.6 percona-server-server/root_password password 'unused'; \ - echo percona-server-server-5.6 percona-server-server/root_password_again password 'unused'; \ - } | debconf-set-selections \ - && apt-get update \ - && apt-get install -y --no-install-recommends \ - percona-server-server-5.6 \ - bzip2 \ - && rm -rf /var/lib/apt/lists/* \ - && groupadd -r vitess && useradd -r -g vitess vitess +COPY docker/lite/install_dependencies.sh /vt/dist/install_dependencies.sh +RUN /vt/dist/install_dependencies.sh percona + +# Set up Vitess user and directory tree. +RUN groupadd -r vitess && useradd -r -g vitess vitess +RUN mkdir -p /vt/vtdataroot && chown -R vitess:vitess /vt # Set up Vitess environment (just enough to run pre-built Go binaries) -ENV VTTOP /vt/src/vitess.io/vitess -ENV VTROOT /vt -ENV GOTOP $VTTOP/go -ENV VTDATAROOT $VTROOT/vtdataroot -ENV GOBIN $VTROOT/bin -ENV GOPATH $VTROOT +ENV VTROOT /vt/src/vitess.io/vitess +ENV VTDATAROOT /vt/vtdataroot ENV PATH $VTROOT/bin:$PATH -ENV VT_MYSQL_ROOT /usr -ENV PKG_CONFIG_PATH $VTROOT/lib -ENV MYSQL_FLAVOR MySQL56 -# Copy binaries (placed by build.sh) -COPY --from=staging /vt/ /vt/ +# Copy artifacts from builder layer. +COPY --from=builder --chown=vitess:vitess /vt/install /vt # Create mount point for actual data (e.g. MySQL data dir) VOLUME /vt/vtdataroot diff --git a/docker/lite/Dockerfile.percona57 b/docker/lite/Dockerfile.percona57 index 30472af2a60..3ac6d264f8b 100644 --- a/docker/lite/Dockerfile.percona57 +++ b/docker/lite/Dockerfile.percona57 @@ -1,57 +1,52 @@ -FROM vitess/base AS builder -FROM debian:stretch-slim AS staging - -RUN mkdir -p /vt/vtdataroot/ \ - && mkdir -p /vt/bin \ - && mkdir -p /vt/src/vitess.io/vitess/web/vtctld2 \ - && groupadd -r vitess && useradd -r -g vitess vitess - -COPY --from=builder /vt/src/vitess.io/vitess/web/vtctld /vt/src/vitess.io/vitess/web/vtctld -COPY --from=builder /vt/src/vitess.io/vitess/web/vtctld2/app /vt/src/vitess.io/vitess/web/vtctld2/app -COPY --from=builder /vt/src/vitess.io/vitess/config /vt/config -COPY --from=builder /vt/bin/mysqlctld /vt/bin/ -COPY --from=builder /vt/bin/vtctld /vt/bin/ -COPY --from=builder /vt/bin/vtctlclient /vt/bin/ -COPY --from=builder /vt/bin/vtgate /vt/bin/ -COPY --from=builder /vt/bin/vttablet /vt/bin/ -COPY --from=builder /vt/bin/vtworker /vt/bin/ -COPY --from=builder /vt/bin/vtbackup /vt/bin/ - -RUN chown -R vitess:vitess /vt +# Copyright 2019 The Vitess Authors. +# +# 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. + +# NOTE: We have to build the Vitess binaries from scratch instead of sharing +# a base image because Docker Hub dropped the feature we relied upon to +# ensure images contain the right binaries. + +# Use a temporary layer for the build stage. +FROM vitess/bootstrap:percona57 AS builder + +# Allows some docker builds to disable CGO +ARG CGO_ENABLED=0 + +# Re-copy sources from working tree. +COPY --chown=vitess:vitess . /vt/src/vitess.io/vitess + +# Build and install Vitess in a temporary output directory. +USER vitess +RUN make install PREFIX=/vt/install +# Start over and build the final image. FROM debian:stretch-slim # Install dependencies -RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends gnupg dirmngr ca-certificates \ - && for i in $(seq 1 10); do apt-key adv --no-tty --recv-keys --keyserver keys.gnupg.net 9334A25F8507EFA5 && break; done \ - && echo 'deb http://repo.percona.com/apt stretch main' > /etc/apt/sources.list.d/percona.list && \ - { \ - echo debconf debconf/frontend select Noninteractive; \ - echo percona-server-server-5.7 percona-server-server/root_password password 'unused'; \ - echo percona-server-server-5.7 percona-server-server/root_password_again password 'unused'; \ - } | debconf-set-selections \ - && apt-get update \ - && apt-get install -y --no-install-recommends \ - percona-server-server-5.7 \ - libperconaserverclient20 \ - bzip2 \ - && rm -rf /var/lib/apt/lists/* \ - && groupadd -r vitess && useradd -r -g vitess vitess +COPY docker/lite/install_dependencies.sh /vt/dist/install_dependencies.sh +RUN /vt/dist/install_dependencies.sh percona57 + +# Set up Vitess user and directory tree. +RUN groupadd -r vitess && useradd -r -g vitess vitess +RUN mkdir -p /vt/vtdataroot && chown -R vitess:vitess /vt # Set up Vitess environment (just enough to run pre-built Go binaries) -ENV VTTOP /vt/src/vitess.io/vitess -ENV VTROOT /vt -ENV GOTOP $VTTOP/go -ENV VTDATAROOT $VTROOT/vtdataroot -ENV GOBIN $VTROOT/bin -ENV GOPATH $VTROOT +ENV VTROOT /vt/src/vitess.io/vitess +ENV VTDATAROOT /vt/vtdataroot ENV PATH $VTROOT/bin:$PATH -ENV VT_MYSQL_ROOT /usr -ENV PKG_CONFIG_PATH $VTROOT/lib -ENV MYSQL_FLAVOR MySQL56 -# Copy binaries (placed by build.sh) -COPY --from=staging /vt/ /vt/ +# Copy artifacts from builder layer. +COPY --from=builder --chown=vitess:vitess /vt/install /vt # Create mount point for actual data (e.g. MySQL data dir) VOLUME /vt/vtdataroot diff --git a/docker/lite/Dockerfile.percona80 b/docker/lite/Dockerfile.percona80 index 31182d277d6..71f258d7e03 100644 --- a/docker/lite/Dockerfile.percona80 +++ b/docker/lite/Dockerfile.percona80 @@ -1,59 +1,53 @@ -FROM vitess/base AS builder -FROM debian:stretch-slim AS staging - -RUN mkdir -p /vt/vtdataroot/ \ - && mkdir -p /vt/bin \ - && mkdir -p /vt/src/vitess.io/vitess/web/vtctld2 \ - && groupadd -r vitess && useradd -r -g vitess vitess - -COPY --from=builder /vt/src/vitess.io/vitess/web/vtctld /vt/src/vitess.io/vitess/web/vtctld -COPY --from=builder /vt/src/vitess.io/vitess/web/vtctld2/app /vt/src/vitess.io/vitess/web/vtctld2/app -COPY --from=builder /vt/src/vitess.io/vitess/config /vt/config -COPY --from=builder /vt/bin/mysqlctld /vt/bin/ -COPY --from=builder /vt/bin/vtctld /vt/bin/ -COPY --from=builder /vt/bin/vtctlclient /vt/bin/ -COPY --from=builder /vt/bin/vtgate /vt/bin/ -COPY --from=builder /vt/bin/vttablet /vt/bin/ -COPY --from=builder /vt/bin/vtworker /vt/bin/ -COPY --from=builder /vt/bin/vtbackup /vt/bin/ - -RUN chown -R vitess:vitess /vt +# Copyright 2019 The Vitess Authors. +# +# 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. + +# NOTE: We have to build the Vitess binaries from scratch instead of sharing +# a base image because Docker Hub dropped the feature we relied upon to +# ensure images contain the right binaries. + +# Use a temporary layer for the build stage. +FROM vitess/bootstrap:percona80 AS builder + +# Allows some docker builds to disable CGO +ARG CGO_ENABLED=0 + +# Re-copy sources from working tree. +COPY --chown=vitess:vitess . /vt/src/vitess.io/vitess + +# Build and install Vitess in a temporary output directory. +USER vitess +RUN make install PREFIX=/vt/install +# Start over and build the final image. FROM debian:stretch-slim # Install dependencies -RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends gnupg dirmngr ca-certificates \ - && for i in $(seq 1 10); do apt-key adv --no-tty --recv-keys --keyserver keys.gnupg.net 9334A25F8507EFA5 && break; done \ - && echo 'deb http://repo.percona.com/ps-80/apt stretch main' > /etc/apt/sources.list.d/percona.list && \ - { \ - echo debconf debconf/frontend select Noninteractive; \ - echo percona-server-server-8.0 percona-server-server/root_password password 'unused'; \ - echo percona-server-server-8.0 percona-server-server/root_password_again password 'unused'; \ - } | debconf-set-selections \ - && apt-get update \ - && apt-get install -y --no-install-recommends \ - percona-server-server \ - libperconaserverclient21 \ - percona-server-tokudb \ - percona-server-rocksdb \ - bzip2 \ - && rm -rf /var/lib/apt/lists/* \ - && groupadd -r vitess && useradd -r -g vitess vitess +COPY docker/lite/install_dependencies.sh /vt/dist/install_dependencies.sh +RUN /vt/dist/install_dependencies.sh percona80 + +# Set up Vitess user and directory tree. +RUN groupadd -r vitess && useradd -r -g vitess vitess +RUN mkdir -p /vt/vtdataroot && chown -R vitess:vitess /vt # Set up Vitess environment (just enough to run pre-built Go binaries) -ENV VTTOP /vt/src/vitess.io/vitess -ENV VTROOT /vt -ENV GOTOP $VTTOP/go -ENV VTDATAROOT $VTROOT/vtdataroot -ENV GOBIN $VTROOT/bin -ENV GOPATH $VTROOT +ENV VTROOT /vt/src/vitess.io/vitess +ENV VTDATAROOT /vt/vtdataroot ENV PATH $VTROOT/bin:$PATH -ENV VT_MYSQL_ROOT /usr -ENV PKG_CONFIG_PATH $VTROOT/lib -ENV MYSQL_FLAVOR MySQL56 +ENV MYSQL_FLAVOR MySQL80 -# Copy binaries (placed by build.sh) -COPY --from=staging /vt/ /vt/ +# Copy artifacts from builder layer. +COPY --from=builder --chown=vitess:vitess /vt/install /vt # Create mount point for actual data (e.g. MySQL data dir) VOLUME /vt/vtdataroot diff --git a/docker/lite/build.sh b/docker/lite/build.sh deleted file mode 100755 index 9524ddb6b98..00000000000 --- a/docker/lite/build.sh +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is the script to build the vitess/lite Docker image by extracting -# the pre-built binaries from a vitess/base image. - -set -ex - -# Parse command line arguments. -prompt_notice=true -if [[ "$1" == "--prompt"* ]]; then - if [[ "$1" == "--prompt=false" ]]; then - prompt_notice=false - fi - shift -fi - -flavor=$1 -base_image=vitess/base -lite_image=vitess/lite -dockerfile=Dockerfile -tag=latest - -if [[ -n "$flavor" ]]; then - lite_image=vitess/lite:$flavor - dockerfile=Dockerfile.$flavor - tag=$flavor -else - echo "Flavor not specified as first argument. Building default image." -fi - -# Abort if base image does not exist. -if ! docker inspect $base_image &>/dev/null; then - echo "ERROR: Dependent image $base_image does not exist. Run 'make $make_target' to build it locally or 'docker pull $base_image' to fetch it from Docker Hub (if it is published)." - exit 1 -fi - -# Educate the user that they have to build or pull vitess/base themselves. -if [[ "$prompt_notice" = true ]]; then - cat < + +set -euo pipefail + +FLAVOR="$1" +export DEBIAN_FRONTEND=noninteractive + +retry() { + for i in $(seq 1 10); do + if "$@"; then return; fi + done +} + +# Install base packages that are common to all flavors. +BASE_PACKAGES=( + bzip2 + ca-certificates + dirmngr + gnupg + libaio1 + libatomic1 + libcurl3 + libdbd-mysql-perl + libev4 + libjemalloc1 + libtcmalloc-minimal4 + procps + rsync + strace + sysstat + wget +) + +apt-get update +apt-get install -y --no-install-recommends "${BASE_PACKAGES[@]}" + +# Packages specific to certain flavors. +case "${FLAVOR}" in +mysql56) + PACKAGES=( + libmysqlclient18 + mysql-client + mysql-server + percona-xtrabackup-24 + ) + ;; +mysql57) + PACKAGES=( + libmysqlclient20 + mysql-client + mysql-server + percona-xtrabackup-24 + ) + ;; +mysql80) + PACKAGES=( + libmysqlclient21 + mysql-client + mysql-server + percona-xtrabackup-80 + ) + ;; +percona) + PACKAGES=( + percona-server-server-5.6 + percona-xtrabackup-24 + ) + ;; +percona57) + PACKAGES=( + libperconaserverclient20 + percona-server-server-5.7 + percona-xtrabackup-24 + ) + ;; +percona80) + PACKAGES=( + libperconaserverclient21 + percona-server-rocksdb + percona-server-server + percona-server-tokudb + percona-xtrabackup-80 + ) + ;; +mariadb|mariadb103) + PACKAGES=( + mariadb-server + ) + ;; +*) + echo "Unknown flavor ${FLAVOR}" + exit 1 + ;; +esac + +# Get GPG keys for extra apt repositories. +case "${FLAVOR}" in +mysql56|mysql57|mysql80) + # repo.mysql.com + retry apt-key adv --no-tty --keyserver keyserver.ubuntu.com --recv-keys 8C718D3B5072E1F5 + ;; +mariadb|mariadb103) + # digitalocean.com + retry apt-key adv --no-tty --keyserver keyserver.ubuntu.com --recv-keys F1656F24C74CD1D8 + ;; +esac + +# All flavors (except mariadb*) include Percona XtraBackup (from repo.percona.com). +retry apt-key adv --no-tty --keyserver keys.gnupg.net --recv-keys 9334A25F8507EFA5 + +# Add extra apt repositories for MySQL. +case "${FLAVOR}" in +mysql56) + echo 'deb http://repo.mysql.com/apt/debian/ stretch mysql-5.6' > /etc/apt/sources.list.d/mysql.list + ;; +mysql57) + echo 'deb http://repo.mysql.com/apt/debian/ stretch mysql-5.7' > /etc/apt/sources.list.d/mysql.list + ;; +mysql80) + echo 'deb http://repo.mysql.com/apt/debian/ stretch mysql-8.0' > /etc/apt/sources.list.d/mysql.list + ;; +mariadb) + echo 'deb http://sfo1.mirrors.digitalocean.com/mariadb/repo/10.2/debian stretch main' > /etc/apt/sources.list.d/mariadb.list + ;; +mariadb103) + echo 'deb http://sfo1.mirrors.digitalocean.com/mariadb/repo/10.3/debian stretch main' > /etc/apt/sources.list.d/mariadb.list + ;; +esac + +# Add extra apt repositories for Percona Server and/or Percona XtraBackup. +case "${FLAVOR}" in +mysql56|mysql57|mysql80|percona|percona57) + echo 'deb http://repo.percona.com/apt stretch main' > /etc/apt/sources.list.d/percona.list + ;; +percona80) + echo 'deb http://repo.percona.com/apt stretch main' > /etc/apt/sources.list.d/percona.list + echo 'deb http://repo.percona.com/ps-80/apt stretch main' > /etc/apt/sources.list.d/percona80.list + ;; +esac + +# Pre-fill values for installation prompts that are normally interactive. +case "${FLAVOR}" in +percona) + debconf-set-selections < /etc/apt/sources.list.d/mysql.list && \ apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ diff --git a/docker/packaging/Dockerfile b/docker/packaging/Dockerfile deleted file mode 100644 index 576b8ef0e63..00000000000 --- a/docker/packaging/Dockerfile +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2019 The Vitess Authors. -# -# 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. - -FROM vitess/base - -USER root - -# Install gem and use gem to install fpm -RUN apt-get update \ - && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ - build-essential \ - ruby-dev \ - rubygems \ - rpm \ - && rm -rf /var/lib/apt/lists/* \ - && gem install --no-ri --no-rdoc fpm - -RUN mkdir /vt/packaging - -COPY docker/packaging/* /vt/packaging/ - -RUN chown -R vitess:vitess /vt/packaging - -USER vitess - -ENTRYPOINT ["/bin/bash", "/vt/packaging/package_vitess.sh"] diff --git a/docker/packaging/package_vitess.sh b/docker/packaging/package_vitess.sh deleted file mode 100755 index 609fd1447d5..00000000000 --- a/docker/packaging/package_vitess.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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. - -if [ -z "${VERSION}" ]; then - echo "Set the env var VERSION with the release version" - exit 1 -fi - -set -eu - -PREFIX=${PREFIX:-/usr} - -inputs_file="/vt/packaging/inputs" -cat <> "${inputs_file}" -/vt/bin/mysqlctld=${PREFIX}/bin/mysqlctld -/vt/bin/vtbackup=${PREFIX}/bin/vtbackup -/vt/bin/vtctl=${PREFIX}/bin/vtctl -/vt/bin/vtctlclient=${PREFIX}/bin/vtctlclient -/vt/bin/vtctld=${PREFIX}/bin/vtctld -/vt/bin/vtgate=${PREFIX}/bin/vtgate -/vt/bin/vttablet=${PREFIX}/bin/vttablet -/vt/bin/vtworker=${PREFIX}/bin/vtworker -/vt/src/vitess.io/vitess/config/=/etc/vitess -/vt/src/vitess.io/vitess/web/vtctld2/app=${PREFIX}/lib/vitess/web/vtcld2 -/vt/src/vitess.io/vitess/web/vtctld=${PREFIX}/lib/vitess/web -/vt/src/vitess.io/vitess/examples/local/=${PREFIX}/share/vitess/examples -EOF - -description='A database clustering system for horizontal scaling of MySQL - -Vitess is a database solution for deploying, scaling and managing large -clusters of MySQL instances. It’s architected to run as effectively in a public -or private cloud architecture as it does on dedicated hardware. It combines and -extends many important MySQL features with the scalability of a NoSQL database.' - -exec /usr/local/bin/fpm \ - --force \ - --input-type dir \ - --name vitess \ - --version "${VERSION}" \ - --url "https://vitess.io/" \ - --description "${description}" \ - --license "Apache License - Version 2.0, January 2004" \ - --inputs "${inputs_file}" \ - --config-files "/etc/vitess" \ - --directories "${PREFIX}/lib/vitess" \ - --before-install "/vt/packaging/preinstall.sh" \ - "${@}" diff --git a/docker/packaging/preinstall.sh b/docker/packaging/preinstall.sh deleted file mode 100755 index e6bfaf537a2..00000000000 --- a/docker/packaging/preinstall.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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. - -if ! /usr/bin/getent group vitess >/dev/null ; then - groupadd -r vitess -fi - -if ! /usr/bin/getent passwd vitess >/dev/null ; then - useradd -r -g vitess vitess -fi diff --git a/docker/publish-site/Dockerfile b/docker/publish-site/Dockerfile deleted file mode 100644 index e0a1946996f..00000000000 --- a/docker/publish-site/Dockerfile +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2019 The Vitess Authors. -# -# 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 image should be built with $VTTOP as the context dir. -# For example: -# vitess$ docker build -f docker/publish-site/Dockerfile -t vitess/publish-site . -FROM ruby:2.3 - -# Install apt dependencies. -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - nodejs && \ - rm -rf /var/lib/apt/lists/* - -# Install ruby dependencies. -COPY vitess.io/Gemfile /vitess.io/Gemfile -RUN cd /vitess.io && \ - gem install bundler && \ - bundle install - -# Expose port for preview-site.sh. -EXPOSE 4000 - diff --git a/docker/test/run.sh b/docker/test/run.sh index 147663d028b..df0c6a20f82 100755 --- a/docker/test/run.sh +++ b/docker/test/run.sh @@ -160,37 +160,32 @@ case "$mode" in "create_cache") echo "Creating cache image $cache_image ..." ;; esac -# Construct "cp" command to copy the source code. -# -# Copy the full source tree except: -# - vendor -# That's because these directories are already part of the image. -# -# Note that we're using the Bash extended Glob support "!(vendor)" on -# purpose here to minimize the size of the cache image: With this trick, -# we do not move or overwrite the existing files while copying the other -# directories. Therefore, the existing files do not count as changed and will -# not be part of the new Docker layer of the cache image. -copy_src_cmd="cp -R /tmp/src/!(vendor|bootstrap.sh) ." -# Copy the .git directory because travis/check_make_proto.sh needs a working -# Git repository. -copy_src_cmd=$(append_cmd "$copy_src_cmd" "cp -R /tmp/src/.git .") - -# Enable gomodules -run_bootstrap_cmd="export GO111MODULE=on" -# Copy bootstrap.sh if it changed -run_bootstrap_cmd=$(append_cmd "$run_bootstrap_cmd" "if [[ \$(diff -w bootstrap.sh /tmp/src/bootstrap.sh) ]]; then cp -f /tmp/src/bootstrap.sh .; bootstrap=1; fi") -# run bootstrap.sh if necessary -run_bootstrap_cmd=$(append_cmd "$run_bootstrap_cmd" "if [[ -n \$bootstrap ]]; then ./bootstrap.sh; fi") -copy_src_cmd=$(append_cmd "$copy_src_cmd" "$run_bootstrap_cmd") - -# Construct the command we will actually run. -# -# Uncomment the next line if you need to debug "bashcmd". -#bashcmd="set -x" +bashcmd="" + if [[ -z "$existing_cache_image" ]]; then - bashcmd=$(append_cmd "$bashcmd" "$copy_src_cmd") + + # Construct "cp" command to copy the source code. + bashcmd=$(append_cmd "$bashcmd" "cp -R /tmp/src/!(vtdataroot|dist|bin|lib|vthook|py-vtdb) . && cp -R /tmp/src/.git .") + fi + +# Reset the environment if this was an old bootstrap. We can detect this from VTTOP presence. +bashcmd=$(append_cmd "$bashcmd" "export VTROOT=/vt/src/vitess.io/vitess") +bashcmd=$(append_cmd "$bashcmd" "export VTDATAROOT=/vt/vtdataroot") +bashcmd=$(append_cmd "$bashcmd" "export PYTHONPATH=/vt/src/vitess.io/vitess/dist/grpc/usr/local/lib/python2.7/site-packages:/vt/src/vitess.io/vitess/dist/py-mock-1.0.1/lib/python2.7/site-packages:/vt/src/vitess.io/vitess/py-vtdb:/vt/src/vitess.io/vitess/dist/selenium/lib/python2.7/site-packages") + +bashcmd=$(append_cmd "$bashcmd" "mkdir -p dist; mkdir -p bin; mkdir -p lib; mkdir -p vthook") +bashcmd=$(append_cmd "$bashcmd" "rm -rf /vt/dist; ln -s /vt/src/vitess.io/vitess/dist /vt/dist") +bashcmd=$(append_cmd "$bashcmd" "rm -rf /vt/bin; ln -s /vt/src/vitess.io/vitess/bin /vt/bin") +bashcmd=$(append_cmd "$bashcmd" "rm -rf /vt/lib; ln -s /vt/src/vitess.io/vitess/lib /vt/lib") +bashcmd=$(append_cmd "$bashcmd" "rm -rf /vt/vthook; ln -s /vt/src/vitess.io/vitess/vthook /vt/vthook") + +# Maven was setup in /vt/dist, may need to reinstall it. +bashcmd=$(append_cmd "$bashcmd" "echo 'Checking if mvn needs installing...'; if [[ ! \$(command -v mvn) ]]; then echo 'install maven'; curl -sL --connect-timeout 10 --retry 3 http://www-us.apache.org/dist/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz | tar -xz && mv apache-maven-3.3.9 /vt/dist/maven; fi; echo 'mvn check done'") + +# Run bootstrap every time now +bashcmd=$(append_cmd "$bashcmd" "./bootstrap.sh") + # At last, append the user's command. bashcmd=$(append_cmd "$bashcmd" "$cmd") diff --git a/examples/are-you-alive/.gitignore b/examples/are-you-alive/.gitignore new file mode 100644 index 00000000000..a0ba6e25a73 --- /dev/null +++ b/examples/are-you-alive/.gitignore @@ -0,0 +1,2 @@ +vendor +are-you-alive diff --git a/examples/are-you-alive/Makefile b/examples/are-you-alive/Makefile new file mode 100644 index 00000000000..d6cc94e5f39 --- /dev/null +++ b/examples/are-you-alive/Makefile @@ -0,0 +1,15 @@ +# We are using the public "planetscale-vitess" registry for this +NAME := "us.gcr.io/planetscale-vitess/are-you-alive" +TAG := $$(git log -1 --pretty=%H) +IMG := ${NAME}:${TAG} +LATEST := ${NAME}:latest + +.PHONY: build push + +build: + @docker build -f build/release/Dockerfile -t ${IMG} . + @docker tag ${IMG} ${LATEST} + +push: + @docker push ${IMG} + @docker push ${LATEST} diff --git a/examples/are-you-alive/README.md b/examples/are-you-alive/README.md new file mode 100644 index 00000000000..65bff90cad6 --- /dev/null +++ b/examples/are-you-alive/README.md @@ -0,0 +1,85 @@ +# Are You Alive? + +What does it mean to be alive? + +Well we don't know what it means for you, but we know what it means for a Vitess +Cluster! + +This project contains a simulated client application that can be used to measure +the health of a Vitess cluster over time. + +## Design + +For now, there is a specific database schema and vschema that you must apply to +the database that you are using for this test. + +This client application: + +1. Hammers the database with random data (not a load test though). +1. Measures all the important things: + - Client connection errors + - Write latency + - Read latency from masters + - Read latency from replicas + - Write errors + - Read errors on masters + - Write errors on replicas + - Errors in other operations on masters and replicas (e.g. COUNT) + - Latency on other operations on masters and replicas (e.g. COUNT) + - Data loss (by writing predictable data and testing for that) +1. Reports all these metrics to Prometheus. + +That's it! + +## Usage + +First, [initialize your database with the correct schemas](schemas/README.md). + +Run `are-you-alive --help` for usage. You can us the command line flags to +control the dataset size, whether to target reads at masters and replicas, your +mysql connection string, and the rate at which to send requests. + +Example: + +``` +./are-you-alive --mysql_connection_string +``` + +Where `` points to the database you are trying to test, +and everything else will be set to defaults. + +## Building + +``` +go build vitess.io/vitess/examples/are-you-alive/cmd/are-you-alive +``` + +## Testing + +First, [install docker compose](https://docs.docker.com/compose/install/) and +make sure it's working. Then run: + +``` +docker-compose build +docker-compose up +``` + +This will create a local mysqld and a local prometheus to scrape the app. It +will also start the app with the `--initialize` flag which tells it to +automatically create the test database. You might have to run this twice to +give mysql a chance to do its first initialization. + +After you run docker compose, navigate to `http://localhost:9090` to see +Prometheus and `http://localhost:8080/metrics` to see the raw metrics being +exported. + +## Push to Registry + +If you have push access to the [planetscale public +registry](https://us.gcr.io/planetscale-vitess), you can use the following +commands to build and push the image: + +``` +make build +make push +``` diff --git a/examples/are-you-alive/build/dev/Dockerfile b/examples/are-you-alive/build/dev/Dockerfile new file mode 100644 index 00000000000..3b079cfcf8a --- /dev/null +++ b/examples/are-you-alive/build/dev/Dockerfile @@ -0,0 +1,13 @@ +# Use a [multi stage +# build](https://docs.docker.com/develop/develop-images/multistage-build/) to +# build [reflex](https://github.com/cespare/reflex), a tool that will allow us +# to automatically rerun the project when any files change. +FROM golang:1.12.5 AS build +# Build reflex as a static binary (CGO_ENABLED=0) so we can run it in our final +# container. +RUN CGO_ENABLED=0 go get -v github.com/cespare/reflex + +FROM golang:1.12.5-alpine AS runtime +COPY --from=build /go/bin/reflex /go/bin/reflex +COPY reflex.conf / +ENTRYPOINT ["/go/bin/reflex", "-c", "/reflex.conf"] diff --git a/examples/are-you-alive/build/dev/reflex.conf b/examples/are-you-alive/build/dev/reflex.conf new file mode 100644 index 00000000000..9e92ab1a7ca --- /dev/null +++ b/examples/are-you-alive/build/dev/reflex.conf @@ -0,0 +1,2 @@ +# Rerun "go run" every time a ".go" file changes. +-r '(\.go$)' -s -- go run vitess.io/vitess/examples/are-you-alive/cmd/are-you-alive --initialize diff --git a/examples/are-you-alive/build/release/Dockerfile b/examples/are-you-alive/build/release/Dockerfile new file mode 100644 index 00000000000..67310da895a --- /dev/null +++ b/examples/are-you-alive/build/release/Dockerfile @@ -0,0 +1,7 @@ +FROM golang:1.12.5 AS build +COPY . /go/src/vitess.io/vitess/examples/are-you-alive +RUN CGO_ENABLED=0 go install vitess.io/vitess/examples/are-you-alive/cmd/are-you-alive + +FROM debian:stretch-slim AS runtime +COPY --from=build /go/bin/are-you-alive /go/bin/are-you-alive +ENTRYPOINT ["/go/bin/are-you-alive"] diff --git a/examples/are-you-alive/cmd/are-you-alive/main.go b/examples/are-you-alive/cmd/are-you-alive/main.go new file mode 100644 index 00000000000..fd747468558 --- /dev/null +++ b/examples/are-you-alive/cmd/are-you-alive/main.go @@ -0,0 +1,352 @@ +package main + +import ( + "database/sql" + "flag" + "fmt" + "github.com/go-sql-driver/mysql" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/sirupsen/logrus" + "math/rand" + "net/http" + "os" + "os/signal" + "sync" + "time" + "vitess.io/vitess/examples/are-you-alive/pkg/client" +) + +/* +* To measure data loss, we need predictable writes. We do this with "minPage" +* and "maxPage". Once the difference between them is our desired dataset size, +* we can start deleting old records, but we expect to find one record for every +* "page" number between "minPage" and "maxPage". +* +* We don't measure "update loss" with this client right now. + */ + +var ( + maxPage = 0 + minPage = 0 + dataLossEvents = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "are_you_alive_data_loss_events", + Help: "Data loss events", + }, + []string{"database_name"}, + ) +) + +func writeNextRecord(environmentName string, connectionString string) error { + + // 1. Call monitored client + err := client.Write(environmentName, connectionString, maxPage) + if err != nil { + // Check to see if this is a duplicate key error. We've seen this + // sometimes happen, and when it does this client app gets stuck in an + // infinite loop of failure to write a duplicate key. It's possible + // that happens because a write is succesful but something goes wrong + // before the client recieves a response, so the client thinks the write + // failed and does not increment the count. + // + // So when we specifically see a duplicate key error, assume that's what + // happened, bump the count, and move on. + // + // See https://github.com/planetscale/planetscale-operator/issues/1776 + if me, ok := err.(*mysql.MySQLError); ok && me.Number == 1062 { + logrus.WithError(err).Warnf( + "Key '%d' already found, incrementing count", maxPage) + maxPage = maxPage + 1 + return nil + } + + logrus.WithError(err).Error("Error writing record") + return err + } + + // 2. Increment "maxPage" + maxPage = maxPage + 1 + return nil +} + +func readRandomRecord(environmentName string, connectionString string) error { + + // 1. Pick Random Number Between "minPage" and "maxPage" + if minPage == maxPage { + logrus.Warn("Nothing has been inserted yet!") + return nil + } + page := (rand.Int() % (maxPage - minPage)) + minPage + + // 2. Read Record + readID, readMsg, err := client.Read(environmentName, connectionString, page) + if err != nil { + if err == sql.ErrNoRows { + // This races with deletion, but if our page is greater than minPage + // we know that it should be in there. If it's less than minPage + // assume we are just racing the deletion goroutine and ignore the + // error. + if page <= minPage { + return nil + } + // For replicas, there is a chance we are suffering from replication + // lag, so ignore the missing row if we are a replica. + // TODO: Should we attempt to roughly figure out replication lag in + // this client, at least to catch major failures? We could probably + // multiply delay by the difference betwen maxCount and the page we + // are trying to read to figure out how long ago the row we were + // trying to write was written. + if client.ParseTabletType(connectionString) == "replica" || + client.ParseTabletType(connectionString) == "rdonly" { + return nil + } + logrus.WithError(err).WithFields(logrus.Fields{ + "page": page, + "minPage": minPage, + "maxPage": maxPage, + }).Error("Query succeeded but record not found, may mean data loss") + dataLossEvents.With( + prometheus.Labels{"database_name": client.ParseDBName(connectionString)}).Inc() + return err + } + logrus.WithError(err).Error("Error reading record") + return err + } + // Add zero here just so the metric exists for this database, even if it's + // zero. + dataLossEvents.With( + prometheus.Labels{"database_name": client.ParseDBName(connectionString)}).Add(0) + logrus.WithFields(logrus.Fields{ + "readID": readID, + "readMsg": readMsg, + }).Debug("Read row!") + + return nil +} + +func runCount(environmentName string, connectionString string) error { + + // 1. Run Count + count, err := client.Count(environmentName, connectionString) + if err != nil { + logrus.WithError(err).Error("Error counting records") + return err + } + logrus.WithFields(logrus.Fields{ + "count": count, + }).Debug("Counted rows!") + + // 2. Log if COUNT != "minPage" - "maxPage" + return nil +} + +func deleteLastRecordIfNecessary(environmentName string, connectionString string) error { + + // 1. Compare "maxPage" - "minPage" to Desired Dataset Size + if (maxPage - minPage) < *datasetSize { + return nil + } + logrus.WithFields(logrus.Fields{ + "current": maxPage - minPage, + "desired": *datasetSize, + }).Debug("Deleting last record") + + // 2. Delete Record If We Are Above Desired Size + err := client.Delete(environmentName, connectionString, minPage) + if err != nil { + logrus.WithError(err).Error("Error deleting record") + return err + } + + // 3. Increment "minPage" + minPage = minPage + 1 + return nil +} + +var ( + mysqlConnectionString = flag.String( + "mysql_connection_string", "", "Connection string for db to test") + prometheusMetricsAddress = flag.String( + "prometheus_metrics_address", ":8080", "Address on which to serve prometheus metrics") + debug = flag.Bool("debug", false, "Enable debug logging") + useVtgate = flag.Bool("vtgate", false, "Using vtgate (for @master and @replica)") + readFromReplica = flag.Bool("replica", false, "Read from replica") + readFromReadOnly = flag.Bool("rdonly", false, "Read from rdonly") + initialize = flag.Bool("initialize", false, "Initialize database (for testing)") + sleepTime = flag.Int("delay", 1*1000*1000*1000, "Delay in nanoseconds between ops") + datasetSize = flag.Int("dataset_size", 10, "Number of total records in database") + environmentName = flag.String("environment_name", "prod", + "Environment the database is deployed in that this client is pointing at") +) + +type runner struct { + connString string + envName string + fn func(string, string) error + errMessage string + sleepTime time.Duration +} + +func (r *runner) run() { + for { + time.Sleep(r.sleepTime) + err := r.fn(r.envName, r.connString) + if err != nil { + logrus.WithError(err).Error(r.errMessage) + } + } +} + +func waitForCtrlC() { + var endWaiter sync.WaitGroup + endWaiter.Add(1) + var signalChannel chan os.Signal + signalChannel = make(chan os.Signal, 1) + signal.Notify(signalChannel, os.Interrupt) + go func() { + <-signalChannel + endWaiter.Done() + }() + endWaiter.Wait() +} + +func runPrometheus() { + http.Handle("/metrics", promhttp.Handler()) + logrus.Fatal(http.ListenAndServe(*prometheusMetricsAddress, nil)) +} + +func main() { + + // 0. Handle Arguments + flag.Parse() + if *debug { + logrus.SetLevel(logrus.DebugLevel) + } + logrus.WithFields(logrus.Fields{ + "mysqlConnectionString": *mysqlConnectionString, + "prometheusMetricsAddress": *prometheusMetricsAddress, + "debug": *debug, + }).Debug("Command line arguments") + + connectionString := "" + if *mysqlConnectionString != "" { + connectionString = *mysqlConnectionString + } else if os.Getenv("MYSQL_CONN_STRING") != "" { + connectionString = os.Getenv("MYSQL_CONN_STRING") + } + masterConnectionString := connectionString + replicaConnectionString := connectionString + rdonlyConnectionString := connectionString + // When using vtgate, we want to append @master and @replica to the DSN, but + // this will fail against normal mysql which we're using for testing. See: + // https://vitess.io/docs/user-guides/faq/#how-do-i-choose-between-master-vs-replica-for-queries + if *useVtgate { + // We need to pass interpolateParams when using a vtgate because + // prepare is not supported. + // + // See: + // - https://github.com/go-sql-driver/mysql/blob/master/README.md#interpolateparams + // - https://github.com/src-d/go-mysql-server/issues/428 + // - https://github.com/vitessio/vitess/pull/3862 + masterConnectionString = fmt.Sprintf("%s@master?interpolateParams=true", connectionString) + replicaConnectionString = fmt.Sprintf("%s@replica?interpolateParams=true", connectionString) + rdonlyConnectionString = fmt.Sprintf("%s@rdonly?interpolateParams=true", connectionString) + } + fmt.Println("masterConnectionString:", masterConnectionString) + fmt.Println("replicaConnectionString:", replicaConnectionString) + fmt.Println("rdonlyConnectionString:", rdonlyConnectionString) + + // 1. Set Up Prometheus Metrics + logrus.Info("Prometheus Go") + go runPrometheus() + + // 2. Initialize Database + logrus.Info("Initializing database") + // For local testing, does not initialize vschema + if *initialize { + client.InitializeDatabase(*environmentName, masterConnectionString, "are_you_alive_messages") + } + client.WipeTestTable(*environmentName, masterConnectionString, "are_you_alive_messages") + + // 3. Start goroutines to do various things + logrus.Info("Starting client goroutines") + deleter := runner{ + connString: masterConnectionString, + envName: *environmentName, + fn: deleteLastRecordIfNecessary, + errMessage: "Recieved error deleting last record", + sleepTime: time.Duration(*sleepTime), + } + go deleter.run() + writer := runner{ + connString: masterConnectionString, + envName: *environmentName, + fn: writeNextRecord, + errMessage: "Recieved error writing next record", + sleepTime: time.Duration(*sleepTime), + } + go writer.run() + reader := runner{ + connString: masterConnectionString, + envName: *environmentName, + fn: readRandomRecord, + errMessage: "Recieved error reading record", + sleepTime: time.Duration(*sleepTime), + } + go reader.run() + counter := runner{ + connString: masterConnectionString, + envName: *environmentName, + fn: runCount, + errMessage: "Recieved error running count", + sleepTime: time.Duration(*sleepTime), + } + go counter.run() + + // Only bother starting a replica reader/counter if we are using a vtgate + // and actually are asking to do replica reads + if *useVtgate && *readFromReplica { + replicaReader := runner{ + connString: replicaConnectionString, + envName: *environmentName, + fn: readRandomRecord, + errMessage: "Recieved error reading record from replica", + sleepTime: time.Duration(*sleepTime), + } + go replicaReader.run() + replicaRowCounter := runner{ + connString: replicaConnectionString, + envName: *environmentName, + fn: runCount, + errMessage: "Recieved error running count on replica", + sleepTime: time.Duration(*sleepTime), + } + go replicaRowCounter.run() + } + + // Only bother starting a rdonly reader/counter if we are using a vtgate and + // actually are asking to do rdonly reads + if *useVtgate && *readFromReadOnly { + replicaReader := runner{ + connString: rdonlyConnectionString, + envName: *environmentName, + fn: readRandomRecord, + errMessage: "Recieved error reading record from rdonly", + sleepTime: time.Duration(*sleepTime), + } + go replicaReader.run() + replicaRowCounter := runner{ + connString: rdonlyConnectionString, + envName: *environmentName, + fn: runCount, + errMessage: "Recieved error running count on rdonly", + sleepTime: time.Duration(*sleepTime), + } + go replicaRowCounter.run() + } + + logrus.Info("Press Ctrl+C to end\n") + waitForCtrlC() + logrus.Info("\n") +} diff --git a/examples/are-you-alive/docker-compose.yml b/examples/are-you-alive/docker-compose.yml new file mode 100644 index 00000000000..603353dcb89 --- /dev/null +++ b/examples/are-you-alive/docker-compose.yml @@ -0,0 +1,29 @@ +# https://www.firehydrant.io/blog/developer-a-go-app-with-docker-compose/ +version: '3' +services: + app: + build: build/dev + image: are-you-alive-dev + volumes: + - .:/go/src/vitess.io/vitess/examples/are-you-alive + working_dir: /go/src/vitess.io/vitess/examples/are-you-alive + environment: + MYSQL_CONN_STRING: root:mysql@tcp(mysql)/testfixture + depends_on: + - mysql + ports: + - 8080:8080 + prom: + image: quay.io/prometheus/prometheus:v2.0.0 + volumes: + - ./prometheus.yml:/etc/prometheus/prometheus.yml + command: "--config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/prometheus" + ports: + - 9090:9090 + depends_on: + - app + mysql: + image: mysql:5.7 + environment: + MYSQL_DATABASE: testfixture + MYSQL_ROOT_PASSWORD: mysql diff --git a/examples/are-you-alive/go.mod b/examples/are-you-alive/go.mod new file mode 100644 index 00000000000..5f3d04ddccd --- /dev/null +++ b/examples/are-you-alive/go.mod @@ -0,0 +1,11 @@ +module vitess.io/vitess/examples/are-you-alive + +go 1.12 + +require ( + github.com/go-sql-driver/mysql v1.5.0 + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/prometheus/client_golang v1.4.1 + github.com/sirupsen/logrus v1.4.2 +) diff --git a/examples/are-you-alive/go.sum b/examples/are-you-alive/go.sum new file mode 100644 index 00000000000..7c05c83b99b --- /dev/null +++ b/examples/are-you-alive/go.sum @@ -0,0 +1,92 @@ +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.1 h1:FFSuS004yOQEtDdTq+TAOLP5xUq63KqAFYyOi8zA+Y8= +github.com/prometheus/client_golang v1.4.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82 h1:ywK/j/KkyTHcdyYSZNXGjMwgmDSfjglYZ3vStQ/gSCU= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +vitess.io/vitess v2.1.1+incompatible h1:nuuGHiWYWpudD3gOCLeGzol2EJ25e/u5Wer2wV1O130= diff --git a/examples/are-you-alive/pkg/client/client.go b/examples/are-you-alive/pkg/client/client.go new file mode 100644 index 00000000000..e4f35d3e882 --- /dev/null +++ b/examples/are-you-alive/pkg/client/client.go @@ -0,0 +1,347 @@ +package client + +import ( + "database/sql" + "fmt" + mysql "github.com/go-sql-driver/mysql" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + "github.com/sirupsen/logrus" + "strings" +) + +/* + * This package is meant to provide a client that includes prometheus metrics + * for common database issues. + */ + +var ( + defaultBuckets = []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10} + countErrorLatency = promauto.NewHistogramVec(prometheus.HistogramOpts{ + Name: "are_you_alive_count_error_latency_seconds", + Help: "Latency to recieve a count error", + Buckets: defaultBuckets, + }, + []string{"environment_name", "database_name", "tablet_type"}, + ) + readErrorLatency = promauto.NewHistogramVec(prometheus.HistogramOpts{ + Name: "are_you_alive_read_error_latency_seconds", + Help: "Latency to recieve a read error", + Buckets: defaultBuckets, + }, + []string{"environment_name", "database_name", "tablet_type"}, + ) + deleteErrorLatency = promauto.NewHistogramVec(prometheus.HistogramOpts{ + Name: "are_you_alive_delete_error_latency_seconds", + Help: "Latency to recieve a delete error", + Buckets: defaultBuckets, + }, + []string{"environment_name", "database_name"}, + ) + writeErrorLatency = promauto.NewHistogramVec(prometheus.HistogramOpts{ + Name: "are_you_alive_write_error_latency_seconds", + Help: "Latency to recieve a write error", + Buckets: defaultBuckets, + }, + []string{"environment_name", "database_name"}, + ) + connectErrorLatency = promauto.NewHistogramVec(prometheus.HistogramOpts{ + Name: "are_you_alive_connect_error_latency_seconds", + Help: "Latency to recieve a connect error", + Buckets: defaultBuckets, + }, + []string{"environment_name", "database_name", "tablet_type"}, + ) + countLatency = promauto.NewHistogramVec(prometheus.HistogramOpts{ + Name: "are_you_alive_count_latency_seconds", + Help: "Time it takes to count to the database", + Buckets: defaultBuckets, + }, + []string{"environment_name", "database_name", "tablet_type"}, + ) + readLatency = promauto.NewHistogramVec(prometheus.HistogramOpts{ + Name: "are_you_alive_read_latency_seconds", + Help: "Time it takes to read to the database", + Buckets: defaultBuckets, + }, + []string{"environment_name", "database_name", "tablet_type"}, + ) + deleteLatency = promauto.NewHistogramVec(prometheus.HistogramOpts{ + Name: "are_you_alive_delete_latency_seconds", + Help: "Time it takes to delete to the database", + Buckets: defaultBuckets, + }, + []string{"environment_name", "database_name"}, + ) + writeLatency = promauto.NewHistogramVec(prometheus.HistogramOpts{ + Name: "are_you_alive_write_latency_seconds", + Help: "Time it takes to write to the database", + Buckets: defaultBuckets, + }, + []string{"environment_name", "database_name"}, + ) + connectLatency = promauto.NewHistogramVec(prometheus.HistogramOpts{ + Name: "are_you_alive_connect_latency_seconds", + Help: "Time it takes to connect to the database", + Buckets: defaultBuckets, + }, + []string{"environment_name", "database_name", "tablet_type"}, + ) +) + +// ParseDBName extracts the database name from a mysql connection string. +func ParseDBName(connectionString string) string { + mysqlConfig, err := mysql.ParseDSN(connectionString) + if err != nil { + logrus.WithError(err).Fatal("Error parsing DSN!") + } + return mysqlConfig.DBName +} + +// ParseTabletType extracts the tablet type from a vitess specific mysql +// connection string. +// +// See https://vitess.io/docs/faq/queries/ for where these come from. +func ParseTabletType(connectionString string) string { + databaseName := ParseDBName(connectionString) + if strings.HasSuffix(databaseName, "@master") { + return "master" + } else if strings.HasSuffix(databaseName, "@replica") { + return "replica" + } else if strings.HasSuffix(databaseName, "@rdonly") { + return "rdonly" + } else { + return "default" + } +} + +func openDatabase(environmentName string, connectionString string) (*sql.DB, error) { + databaseName := ParseDBName(connectionString) + tabletType := ParseTabletType(connectionString) + // NOTE: This is probably not measuring open connections. I think they + // connections are created/fetched from the pool when an operation is + // actually performed. We could force this with a ping probably, but for + // now this is here just as a sanity check that this is actually all + // happening locally. We should just see everything complete within + // milliseconds. + labels := prometheus.Labels{ + "environment_name": environmentName, + "database_name": databaseName, + "tablet_type": tabletType} + connectTimer := prometheus.NewTimer(connectLatency.With(labels)) + connectErrorTimer := prometheus.NewTimer(connectErrorLatency.With(labels)) + db, err := sql.Open("mysql", connectionString) + if err != nil { + logrus.WithError(err).Error("Error connecting to database") + connectErrorTimer.ObserveDuration() + return nil, err + } + connectTimer.ObserveDuration() + return db, nil +} + +// InitializeDatabase will connect to the given connectionString, drop the +// given tableName, and recreate it with the schema that the rest of the client +// expects. This is not something any normal client would do but is convenient +// here because we are just using this client for monitoring. +func InitializeDatabase(environmentName string, connectionString string, tableName string) error { + + // 0. Create logger + log := logrus.WithField("connection_string", connectionString) + + // 1. Open client to database + db, err := openDatabase(environmentName, connectionString) + if err != nil { + log.WithError(err).Error("Error opening database") + return err + } + defer db.Close() + + // 2. Delete test table, but continue if it's not there + if _, err := db.Exec(fmt.Sprintf("DROP TABLE %s", tableName)); err != nil { + log.WithError(err).Warn("Error deleting database") + } + + // 3. Create table + createSQL := fmt.Sprintf( + "CREATE TABLE IF NOT EXISTS %s(page INT, message VARCHAR(255) NOT NULL, PRIMARY KEY (page))", tableName) + if _, err := db.Exec(createSQL); err != nil { + log.WithError(err).Error("Error creating database") + return err + } + return nil +} + +// WipeTestTable connects to the database given by connectionString and deletes +// everything in the table given by tableName because this client expects the +// table to be empty. No client would normally do this, but it's convenient for +// testing. +func WipeTestTable(environmentName string, connectionString string, tableName string) error { + + // 0. Create logger + log := logrus.WithField("connection_string", connectionString) + + // 1. Open client to database + db, err := openDatabase(environmentName, connectionString) + if err != nil { + log.WithError(err).Error("Error opening database") + return err + } + defer db.Close() + + // 2. Clear database + if _, err := db.Exec(fmt.Sprintf("DELETE FROM %s", tableName)); err != nil { + log.WithError(err).Warn("Error clearing table") + } + return nil +} + +// Write will write the record given by page to the test table in the database +// referenced by connectionString. +func Write(environmentName string, connectionString string, page int) error { + + // 0. Create logger + log := logrus.WithField("connection_string", connectionString) + + // 1. Open client to database + databaseName := ParseDBName(connectionString) + db, err := openDatabase(environmentName, connectionString) + if err != nil { + log.WithError(err).Error("Error opening database") + return err + } + defer db.Close() + + // 2. Write record + labels := prometheus.Labels{ + "environment_name": environmentName, + "database_name": databaseName} + writeTimer := prometheus.NewTimer(writeLatency.With(labels)) + writeErrorTimer := prometheus.NewTimer(writeErrorLatency.With(labels)) + if _, err := db.Exec("INSERT INTO are_you_alive_messages (page, message) VALUES (?, ?)", page, "foo"); err != nil { + log.WithError(err).Error("Error inserting into database") + writeErrorTimer.ObserveDuration() + return err + } + writeTimer.ObserveDuration() + return nil +} + +// Read will read the record given by page from the test table in the database +// referenced by connectionString. +func Read(environmentName string, connectionString string, page int) (int, string, error) { + + // 0. Create logger + log := logrus.WithField("connection_string", connectionString) + + // 1. Open client to database + databaseName := ParseDBName(connectionString) + db, err := openDatabase(environmentName, connectionString) + if err != nil { + log.WithError(err).Error("Error opening database") + return 0, "", err + } + defer db.Close() + + // 2. Read record + tabletType := ParseTabletType(connectionString) + labels := prometheus.Labels{ + "environment_name": environmentName, + "database_name": databaseName, + "tablet_type": tabletType} + readTimer := prometheus.NewTimer(readLatency.With(labels)) + readErrorTimer := prometheus.NewTimer(readErrorLatency.With(labels)) + row := db.QueryRow("SELECT * FROM are_you_alive_messages WHERE page=?", page) + var readID int + var readMsg string + if err := row.Scan(&readID, &readMsg); err != nil { + if err == sql.ErrNoRows { + // If our error is just that we didn't find anything, don't treat + // this as an error or a success. Just return and let the caller + // deal with it so we don't mess up our metrics. + return 0, "", err + } + log.WithError(err).Error("Error connecting to database") + readErrorTimer.ObserveDuration() + return 0, "", err + } + logrus.WithFields(logrus.Fields{ + "readId": readID, + "readMsg": readMsg, + }).Debug("Successfully read row") + readTimer.ObserveDuration() + return readID, readMsg, nil +} + +// Count will count all the documents in the test table in the database +// referenced by connectionString. +func Count(environmentName string, connectionString string) (int, error) { + + // 0. Create logger + log := logrus.WithField("connection_string", connectionString) + + // 1. Open client to database + databaseName := ParseDBName(connectionString) + db, err := openDatabase(environmentName, connectionString) + if err != nil { + log.WithError(err).Error("Error opening database") + return 0, err + } + defer db.Close() + + // 2. Run Count + tabletType := ParseTabletType(connectionString) + labels := prometheus.Labels{ + "environment_name": environmentName, + "database_name": databaseName, + "tablet_type": tabletType} + countTimer := prometheus.NewTimer(countLatency.With(labels)) + countErrorTimer := prometheus.NewTimer(countErrorLatency.With(labels)) + row := db.QueryRow("SELECT COUNT(*) FROM are_you_alive_messages") + var count int + if err := row.Scan(&count); err != nil { + log.WithError(err).Error("Error running count") + countErrorTimer.ObserveDuration() + return 0, err + } + logrus.WithFields(logrus.Fields{ + "count": count, + }).Debug("Successfully ran count") + countTimer.ObserveDuration() + return count, nil +} + +// Delete will delete the record given by page from the test table in the +// database referenced by connectionString. +func Delete(environmentName string, connectionString string, page int) error { + + // 0. Create logger + log := logrus.WithFields(logrus.Fields{ + "connection_string": connectionString, + "page": page, + }) + + // 1. Open client to database + databaseName := ParseDBName(connectionString) + labels := prometheus.Labels{ + "environment_name": environmentName, + "database_name": databaseName} + deleteTimer := prometheus.NewTimer(deleteLatency.With(labels)) + deleteErrorTimer := prometheus.NewTimer(deleteErrorLatency.With(labels)) + db, err := openDatabase(environmentName, connectionString) + if err != nil { + log.WithError(err).Error("Error opening database") + deleteErrorTimer.ObserveDuration() + return err + } + defer db.Close() + + // 2. Delete record + if _, err := db.Exec("DELETE FROM are_you_alive_messages WHERE page=?", page); err != nil { + log.WithError(err).Error("Error deleting record") + deleteErrorTimer.ObserveDuration() + return err + } + deleteTimer.ObserveDuration() + return nil +} diff --git a/examples/are-you-alive/prometheus.yml b/examples/are-you-alive/prometheus.yml new file mode 100644 index 00000000000..d968a28136d --- /dev/null +++ b/examples/are-you-alive/prometheus.yml @@ -0,0 +1,34 @@ +# my global config +global: + scrape_interval: 5s # By default, scrape targets every 5 seconds. + evaluation_interval: 5s # By default, scrape targets every 5 seconds. + # scrape_timeout is set to the global default (10s). + + # Attach these labels to any time series or alerts when communicating with + # external systems (federation, remote storage, Alertmanager). + external_labels: + monitor: 'local-integration-test' + +# Load rules once and periodically evaluate them according to the global 'evaluation_interval'. +rule_files: + # - "first.rules" + # - "second.rules" + +# A scrape configuration containing exactly one endpoint to scrape: +# Here it's Prometheus itself. +scrape_configs: + # The job name is added as a label `job=` to any timeseries scraped from this config. + - job_name: 'prometheus' + + # Override the global default and scrape targets from this job every 5 seconds. + scrape_interval: 5s + + # metrics_path defaults to '/metrics' + # scheme defaults to 'http'. + + static_configs: + - targets: ['localhost:9090'] + - job_name: "app" + scrape_interval: "5s" + static_configs: + - targets: ['app:8080'] diff --git a/examples/are-you-alive/schemas/README.md b/examples/are-you-alive/schemas/README.md new file mode 100644 index 00000000000..e119ab33506 --- /dev/null +++ b/examples/are-you-alive/schemas/README.md @@ -0,0 +1,9 @@ +# Test Schemas + +MySQL schemas and Vitess schemas that must be applied to your cluster to use +this test helper. They should be applied using `vtctlclient` like this: + +``` +vtctlclient -server "" ApplySchema -sql "$(cat create_test_table.sql)" +vtctlclient -server "" ApplyVSchema -vschema "$(cat vschema.json)" +``` diff --git a/examples/are-you-alive/schemas/create_test_table.sql b/examples/are-you-alive/schemas/create_test_table.sql new file mode 100644 index 00000000000..c382d343529 --- /dev/null +++ b/examples/are-you-alive/schemas/create_test_table.sql @@ -0,0 +1,6 @@ +CREATE TABLE IF NOT EXISTS are_you_alive_messages ( + page INT, + message VARCHAR(255) NOT NULL, + PRIMARY KEY (page) +) + diff --git a/examples/kubernetes/vschema.json b/examples/are-you-alive/schemas/vschema.json similarity index 87% rename from examples/kubernetes/vschema.json rename to examples/are-you-alive/schemas/vschema.json index 17e5dedf0c8..bf8df1b6e64 100644 --- a/examples/kubernetes/vschema.json +++ b/examples/are-you-alive/schemas/vschema.json @@ -6,7 +6,7 @@ } }, "tables": { - "messages": { + "are_you_alive_messages": { "column_vindexes": [ { "column": "page", diff --git a/examples/compose/README.md b/examples/compose/README.md index 12f81422d64..e637b60652c 100644 --- a/examples/compose/README.md +++ b/examples/compose/README.md @@ -51,7 +51,7 @@ Flags available: go run vtcompose/vtcompose.go -keyspaceData="test_keyspace:2:1:create_messages.sql,create_tokens.sql:lookup_keyspace;lookup_keyspace:1:1:create_tokens_token_lookup.sql,create_messages_message_lookup.sql" ``` * **externalDbData** - Specifies which databases/keyspaces are external and provides data along with it to connect to the external db. - List of `,,,,,` seperated by ';'. + List of `,,,,,` separated by ';'. When using this, make sure to have the external_db_name/keyspace in the `keyspaceData` flag with no schema_file_names specified. ``` go run vtcompose/vtcompose.go -keyspaces="test:0:2::" -externalDbData="test:192.68.99.101:3306:admin:pass:CHARACTER SET utf8 COLLATE utf8_general_ci" @@ -155,11 +155,6 @@ DB_CHARSET=CHARACTER SET utf8 COLLATE utf8_general_ci ``` Ensure you have log bin enabled on your external database. -You may add the following configs to your conf.d directory and reload mysqld on your server -``` -vitess/config/mycnf/master_mysql56.cnf -vitess/config/mycnf/rbr.cnf -``` ### Start the cluster ``` @@ -263,4 +258,4 @@ vitess/examples/compose$ ./lvtctl.sh ApplyVschema -vschema '{"sharded":false, "t ``` This has since been fixed by -https://github.com/vitessio/vitess/pull/4868 & https://github.com/vitessio/vitess/pull/5010 \ No newline at end of file +https://github.com/vitessio/vitess/pull/4868 & https://github.com/vitessio/vitess/pull/5010 diff --git a/examples/compose/docker-compose.beginners.yml b/examples/compose/docker-compose.beginners.yml index 4f23b688f1a..4555cc397c8 100644 --- a/examples/compose/docker-compose.beginners.yml +++ b/examples/compose/docker-compose.beginners.yml @@ -37,8 +37,6 @@ services: command: ["sh", "-c", " $$VTROOT/bin/vtctld \ $TOPOLOGY_FLAGS \ -cell $CELL \ - -web_dir $$VTTOP/web/vtctld \ - -web_dir2 $$VTTOP/web/vtctld2/app \ -workflow_manager_init \ -workflow_manager_use_election \ -service_map 'grpc-vtctl' \ diff --git a/examples/compose/external_db/docker-compose.yml b/examples/compose/external_db/docker-compose.yml index 5b3b28f1f9e..b0b1e58f9fd 100644 --- a/examples/compose/external_db/docker-compose.yml +++ b/examples/compose/external_db/docker-compose.yml @@ -17,7 +17,6 @@ services: volumes: - vol-db:/var/lib/mysql - ./mysql/:/docker-entrypoint-initdb.d/ - - ./mysql/master_mysql56.cnf:/etc/mysql/conf.d/master_mysql56.cnf - ./mysql/query.log:/var/log/mysql/query.log - ./mysql/slow.log:/var/log/mysql/slow.log healthcheck: diff --git a/examples/compose/vtcompose/vtcompose.go b/examples/compose/vtcompose/vtcompose.go index b88099f3a6c..912081b66e6 100644 --- a/examples/compose/vtcompose/vtcompose.go +++ b/examples/compose/vtcompose/vtcompose.go @@ -48,7 +48,7 @@ var ( mySqlPort = flag.String("mySqlPort", "15306", "mySql port to be used") cell = flag.String("cell", "test", "Vitess Cell name") keyspaceData = flag.String("keyspaceData", "test_keyspace:2:1:create_messages.sql,create_tokens.sql;unsharded_keyspace:0:0:create_dinosaurs.sql,create_eggs.sql", "List of keyspace_name/external_db_name:num_of_shards:num_of_replica_tablets:schema_files:lookup_keyspace_name separated by ';'") - externalDbData = flag.String("externalDbData", "", "List of Data corresponding to external DBs. List of ,,,,, seperated by ';'") + externalDbData = flag.String("externalDbData", "", "List of Data corresponding to external DBs. List of ,,,,, separated by ';'") ) type keyspaceInfo struct { @@ -466,8 +466,6 @@ func generateVtctld() string { command: ["sh", "-c", " $$VTROOT/bin/vtctld \ %[3]s \ -cell %[4]s \ - -web_dir $$VTTOP/web/vtctld \ - -web_dir2 $$VTTOP/web/vtctld2/app \ -workflow_manager_init \ -workflow_manager_use_election \ -service_map 'grpc-vtctl' \ diff --git a/examples/compose/vttablet-up.sh b/examples/compose/vttablet-up.sh index 00369ecdd22..7284fc37d7e 100755 --- a/examples/compose/vttablet-up.sh +++ b/examples/compose/vttablet-up.sh @@ -63,14 +63,10 @@ if [ $tablet_role != "master" ]; then echo "CREATE USER IF NOT EXISTS '$DB_USER'@'%' IDENTIFIED BY '$DB_PASS';" >> $init_db_sql_file echo "GRANT ALL ON *.* TO '$DB_USER'@'%';FLUSH PRIVILEGES;" >> $init_db_sql_file # Prevent replication failures in case external db server has multiple databases which have not been created here - echo "replicate-do-db=$keyspace" >> $VTROOT/config/mycnf/rbr.cnf else echo "CREATE DATABASE IF NOT EXISTS $db_name;" >> $init_db_sql_file fi fi -# Enforce Row Based Replication -export EXTRA_MY_CNF=$VTROOT/config/mycnf/default-fast.cnf:$VTROOT/config/mycnf/rbr.cnf -export EXTRA_MY_CNF=$EXTRA_MY_CNF:$VTROOT/config/mycnf/master_mysql56.cnf mkdir -p $VTDATAROOT/backups @@ -182,4 +178,4 @@ exec $VTROOT/bin/vttablet \ -backup_storage_implementation file \ -file_backup_storage_root $VTDATAROOT/backups \ -queryserver-config-schema-reload-time 60 \ - $external_db_args \ No newline at end of file + $external_db_args diff --git a/examples/demo/run.py b/examples/demo/run.py index 45eb8267ce2..a5dae3a4e26 100755 --- a/examples/demo/run.py +++ b/examples/demo/run.py @@ -51,13 +51,13 @@ def start_vitess(): keyspace = topology.keyspaces.add(name='lookup') keyspace.shards.add(name='0') - vttop = os.environ['VTTOP'] - args = [os.path.join(vttop, 'py/vttest/run_local_database.py'), + vtroot = os.environ['VTROOT'] + args = [os.path.join(vtroot, 'py/vttest/run_local_database.py'), '--port', '12345', '--proto_topo', text_format.MessageToString(topology, as_one_line=True), - '--web_dir', os.path.join(vttop, 'web/vtctld'), - '--schema_dir', os.path.join(vttop, 'examples/demo/schema')] + '--schema_dir', os.path.join(vttop, 'examples/demo/schema'), + '--mysql_server_bind_address', '0.0.0.0'] sp = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE) # This load will make us wait for vitess to come up. diff --git a/examples/helm/101_initial_cluster.yaml b/examples/helm/101_initial_cluster.yaml index 79d9bb972ea..aab85cee688 100644 --- a/examples/helm/101_initial_cluster.yaml +++ b/examples/helm/101_initial_cluster.yaml @@ -64,7 +64,7 @@ vtgate: resources: vttablet: - mysqlSize: "test" + mysqlSize: "prod" resources: mysqlResources: diff --git a/examples/helm/201_customer_keyspace.yaml b/examples/helm/201_customer_keyspace.yaml index 3490ac2e106..c343abb8d97 100644 --- a/examples/helm/201_customer_keyspace.yaml +++ b/examples/helm/201_customer_keyspace.yaml @@ -40,7 +40,7 @@ vtgate: resources: vttablet: - mysqlSize: "test" + mysqlSize: "prod" resources: mysqlResources: diff --git a/examples/helm/202_customer_tablets.yaml b/examples/helm/202_customer_tablets.yaml index f24c929e4e1..2a13c3940f2 100644 --- a/examples/helm/202_customer_tablets.yaml +++ b/examples/helm/202_customer_tablets.yaml @@ -65,7 +65,7 @@ vtgate: resources: vttablet: - mysqlSize: "test" + mysqlSize: "prod" resources: mysqlResources: diff --git a/examples/helm/203_vertical_split.yaml b/examples/helm/203_vertical_split.yaml index 677f2bbd9d5..2480f39a2d2 100644 --- a/examples/helm/203_vertical_split.yaml +++ b/examples/helm/203_vertical_split.yaml @@ -36,7 +36,7 @@ jobs: - name: "vertical-split" kind: "vtworker" cell: "zone1" - command: "VerticalSplitClone -min_healthy_rdonly_tablets=1 -tables=customer,corder customer/0" + command: "VerticalSplitClone -min_healthy_tablets=1 -tables=customer,corder customer/0" etcd: replicas: 1 @@ -51,7 +51,7 @@ vtgate: resources: vttablet: - mysqlSize: "test" + mysqlSize: "prod" resources: mysqlResources: diff --git a/examples/helm/204_vertical_migrate_replicas.yaml b/examples/helm/204_vertical_migrate_replicas.yaml index 360c30020e9..aad9a9b155c 100644 --- a/examples/helm/204_vertical_migrate_replicas.yaml +++ b/examples/helm/204_vertical_migrate_replicas.yaml @@ -53,7 +53,7 @@ vtgate: resources: vttablet: - mysqlSize: "test" + mysqlSize: "prod" resources: mysqlResources: diff --git a/examples/helm/205_vertical_migrate_master.yaml b/examples/helm/205_vertical_migrate_master.yaml index 3476c6709be..21ecc757762 100644 --- a/examples/helm/205_vertical_migrate_master.yaml +++ b/examples/helm/205_vertical_migrate_master.yaml @@ -50,7 +50,7 @@ vtgate: resources: vttablet: - mysqlSize: "test" + mysqlSize: "prod" resources: mysqlResources: diff --git a/examples/helm/206_clean_commerce.yaml b/examples/helm/206_clean_commerce.yaml index 57304dea4f8..11883808f52 100644 --- a/examples/helm/206_clean_commerce.yaml +++ b/examples/helm/206_clean_commerce.yaml @@ -60,7 +60,7 @@ vtgate: resources: vttablet: - mysqlSize: "test" + mysqlSize: "prod" resources: mysqlResources: diff --git a/examples/helm/301_customer_sharded.yaml b/examples/helm/301_customer_sharded.yaml index 34ef10ca90f..d20497d6b93 100644 --- a/examples/helm/301_customer_sharded.yaml +++ b/examples/helm/301_customer_sharded.yaml @@ -104,7 +104,7 @@ vtgate: resources: vttablet: - mysqlSize: "test" + mysqlSize: "prod" resources: mysqlResources: diff --git a/examples/helm/302_new_shards.yaml b/examples/helm/302_new_shards.yaml index 9ed6098cd72..658281899ad 100644 --- a/examples/helm/302_new_shards.yaml +++ b/examples/helm/302_new_shards.yaml @@ -65,7 +65,7 @@ vtgate: resources: vttablet: - mysqlSize: "test" + mysqlSize: "prod" resources: mysqlResources: diff --git a/examples/helm/303_horizontal_split.yaml b/examples/helm/303_horizontal_split.yaml index de6b2c527b4..7415384db45 100644 --- a/examples/helm/303_horizontal_split.yaml +++ b/examples/helm/303_horizontal_split.yaml @@ -67,7 +67,7 @@ vtgate: resources: vttablet: - mysqlSize: "test" + mysqlSize: "prod" resources: mysqlResources: diff --git a/examples/helm/304_migrate_replicas.yaml b/examples/helm/304_migrate_replicas.yaml index bb5b35efa7a..950b1e8ce38 100644 --- a/examples/helm/304_migrate_replicas.yaml +++ b/examples/helm/304_migrate_replicas.yaml @@ -69,7 +69,7 @@ vtgate: resources: vttablet: - mysqlSize: "test" + mysqlSize: "prod" resources: mysqlResources: diff --git a/examples/helm/305_migrate_master.yaml b/examples/helm/305_migrate_master.yaml index 8b325b2bc05..ae3dd170105 100644 --- a/examples/helm/305_migrate_master.yaml +++ b/examples/helm/305_migrate_master.yaml @@ -66,7 +66,7 @@ vtgate: resources: vttablet: - mysqlSize: "test" + mysqlSize: "prod" resources: mysqlResources: diff --git a/examples/helm/306_down_shard_0.yaml b/examples/helm/306_down_shard_0.yaml index 6b3fb1b3a01..d34ac318f65 100644 --- a/examples/helm/306_down_shard_0.yaml +++ b/examples/helm/306_down_shard_0.yaml @@ -53,7 +53,7 @@ vtgate: resources: vttablet: - mysqlSize: "test" + mysqlSize: "prod" resources: mysqlResources: diff --git a/examples/helm/307_delete_shard_0.yaml b/examples/helm/307_delete_shard_0.yaml index f24e3410619..ccfad668d30 100644 --- a/examples/helm/307_delete_shard_0.yaml +++ b/examples/helm/307_delete_shard_0.yaml @@ -58,7 +58,7 @@ vtgate: resources: vttablet: - mysqlSize: "test" + mysqlSize: "prod" resources: mysqlResources: diff --git a/examples/helm/308_final.yaml b/examples/helm/308_final.yaml index f24e3410619..ccfad668d30 100644 --- a/examples/helm/308_final.yaml +++ b/examples/helm/308_final.yaml @@ -58,7 +58,7 @@ vtgate: resources: vttablet: - mysqlSize: "test" + mysqlSize: "prod" resources: mysqlResources: diff --git a/examples/helm/kvtctld.sh b/examples/helm/kvtctld.sh index 45f9c796299..2499e706301 100755 --- a/examples/helm/kvtctld.sh +++ b/examples/helm/kvtctld.sh @@ -1,13 +1,13 @@ #!/bin/bash # Copyright 2019 The Vitess Authors. -# +# # 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. diff --git a/examples/kubernetes/README.md b/examples/kubernetes/README.md deleted file mode 100644 index a4ea12366cd..00000000000 --- a/examples/kubernetes/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Vitess on Kubernetes - -This directory contains an example configuration for running Vitess on -[Kubernetes](https://kubernetes.io/). - -See the [Vitess on Kubernetes](https://vitess.io/docs/tutorials/kubernetes/) \ No newline at end of file diff --git a/examples/kubernetes/advanced.md b/examples/kubernetes/advanced.md deleted file mode 100644 index 1b4e4f260f3..00000000000 --- a/examples/kubernetes/advanced.md +++ /dev/null @@ -1,61 +0,0 @@ -# Advanced Vitess on Kubernetes - -## Automatically run Vitess on Container Engine - -The following commands will create a Google Container Engine cluster and bring -up Vitess with two shards and three tablets per shard: (Note that it does not -bring up the Guestbook example) - -``` - -vitess/examples/kubernetes$ export SHARDS=-80,80- -vitess/examples/kubernetes$ export GKE_ZONE=us-central1-b -vitess/examples/kubernetes$ export GKE_NUM_NODES=10 -vitess/examples/kubernetes$ export GKE_MACHINE_TYPE=n1-standard-8 -vitess/examples/kubernetes$ ./cluster-up.sh -vitess/examples/kubernetes$ ./vitess-up.sh -``` - -Run the following to tear down the entire Vitess + container engine cluster: - -``` -vitess/examples/kubernetes$ ./vitess-down.sh -vitess/examples/kubernetes$ ./cluster-down.sh -``` - -## Parameterizing configs - -The vitess and cluster scripts both support parameterization via exporting -environment variables. - -### Parameterizing cluster scripts - -Common environment variables: - -* GKE_ZONE - Zone to use for Container Engine (default us-central1-b) -* GKE_CLUSTER_NAME - Name to use when creating a cluster (default example). -* SHARDS - Comma delimited keyranges for shards (default -80,80- for 2 shards). -Use 0 for an unsharded keyspace. - -The cluster-up.sh script supports the following environment variables: - -* GKE_MACHINE_TYPE - Container Engine machine type (default n1-standard-1) -* GKE_NUM_NODES - Number of nodes to use for the cluster (required). -* GKE_SSD_SIZE_GB - SSD size (in GB) to use (default 0 for no SSD). - -The vitess-up.sh script supports the following environment variables: - -* TABLETS_PER_SHARD - Number of tablets per shard (default 3). -* RDONLY_COUNT - Number of tablets per shard that are rdonly (default 0). -* VTGATE_COUNT - Number of vtgates (default 25% of total vttablet count, -with a minimum of 3). - -For example, to create an unsharded keyspace with 5 tablets, use the following: - -``` -export SHARDS=0 -export TABLETS_PER_SHARD=5 -vitess/examples/kubernetes$ ./cluster-up.sh -vitess/examples/kubernetes$ ./vitess-up.sh -``` - diff --git a/examples/kubernetes/cluster-down.sh b/examples/kubernetes/cluster-down.sh deleted file mode 100755 index 33ea5891ae5..00000000000 --- a/examples/kubernetes/cluster-down.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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. - -# Tears down the container engine cluster, removes rules/pools - -GKE_ZONE=${GKE_ZONE:-'us-central1-b'} -GKE_CLUSTER_NAME=${GKE_CLUSTER_NAME:-'example'} - -base_ssd_name="$GKE_CLUSTER_NAME-vt-ssd-" - -gcloud container clusters delete $GKE_CLUSTER_NAME -z $GKE_ZONE -q - -num_ssds=`gcloud compute disks list | awk -v name="$base_ssd_name" -v zone=$GKE_ZONE '$1~name && $2==zone' | wc -l` -for i in `seq 1 $num_ssds`; do - gcloud compute disks delete $base_ssd_name$i --zone $GKE_ZONE -q -done - diff --git a/examples/kubernetes/cluster-up.sh b/examples/kubernetes/cluster-up.sh deleted file mode 100755 index 7e4da58946c..00000000000 --- a/examples/kubernetes/cluster-up.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is an example script that creates a fully functional vitess cluster. -# It performs the following steps: -# 1. Create a container engine cluster -# 2. Create etcd clusters -# 3. Create vtctld clusters -# 4. Forward vtctld port -# 5. Create vttablet clusters -# 6. Perform vtctl initialization: -# SetKeyspaceShardingInfo, Rebuild Keyspace, Reparent Shard, Apply Schema -# 7. Create vtgate clusters -# 8. Forward vtgate port - -# Customizable parameters -GKE_ZONE=${GKE_ZONE:-'us-central1-b'} -GKE_MACHINE_TYPE=${GKE_MACHINE_TYPE:-'n1-standard-4'} -GKE_CLUSTER_NAME=${GKE_CLUSTER_NAME:-'example'} -GKE_SSD_SIZE_GB=${GKE_SSD_SIZE_GB:-0} -GKE_NUM_NODES=${GKE_NUM_NODES:-0} -VTDATAROOT_VOLUME=${VTDATAROOT_VOLUME:-'/ssd'} - -# Get region from zone (everything to last dash) -gke_region=`echo $GKE_ZONE | sed "s/-[^-]*$//"` - -export KUBECTL='kubectl' -gcloud config set compute/zone $GKE_ZONE -project_id=`gcloud config list project | sed -n 2p | cut -d " " -f 3` - -echo "****************************" -echo "*Creating cluster:" -echo "* Zone: $GKE_ZONE" -echo "* Machine type: $GKE_MACHINE_TYPE" -echo "* Num nodes: $GKE_NUM_NODES" -echo "* SSD Size: $GKE_SSD_SIZE_GB" -echo "* Cluster name: $GKE_CLUSTER_NAME" -echo "* Project ID: $project_id" -echo "****************************" -gcloud container clusters create $GKE_CLUSTER_NAME --machine-type $GKE_MACHINE_TYPE --num-nodes $GKE_NUM_NODES --scopes storage-rw -gcloud config set container/cluster $GKE_CLUSTER_NAME - -if [ $GKE_SSD_SIZE_GB -gt 0 ] -then - echo Creating SSDs and attaching to container engine nodes - i=1 - for nodename in `$KUBECTL get nodes --no-headers | awk '{print $1}'`; do - diskname=$GKE_CLUSTER_NAME-vt-ssd-$i - gcloud compute disks create $diskname --type=pd-ssd --size=${GKE_SSD_SIZE_GB}GB - gcloud compute instances attach-disk $nodename --disk $diskname - gcloud compute ssh $nodename --zone=$GKE_ZONE --command "sudo mkdir ${VTDATAROOT_VOLUME}; sudo /usr/share/google/safe_format_and_mount -m \"mkfs.ext4 -o noatime -F\" /dev/disk/by-id/google-persistent-disk-1 ${VTDATAROOT_VOLUME} &" - gcloud compute ssh $nodename --zone=$GKE_ZONE --command "echo '/dev/disk/by-id/google-persistent-disk-1 /ssd ext4 defaults,noatime 0 0' | sudo tee --append /etc/fstab > /dev/null" - let i=i+1 - done -fi - -if [ -n "$NEWRELIC_LICENSE_KEY" -a $GKE_SSD_SIZE_GB -gt 0 ]; then - i=1 - for nodename in `$KUBECTL get nodes --no-header | awk '{print $1}'`; do - gcloud compute copy-files newrelic.sh $nodename:~/ - gcloud compute copy-files newrelic_start_agent.sh $nodename:~/ - gcloud compute copy-files newrelic_start_mysql_plugin.sh $nodename:~/ - gcloud compute ssh $nodename --command "bash -c '~/newrelic.sh ${NEWRELIC_LICENSE_KEY}'" - let i=i+1 - done -fi - -echo "****************************" -echo "* Complete!" -echo "****************************" diff --git a/examples/kubernetes/configure.sh b/examples/kubernetes/configure.sh deleted file mode 100755 index 8ed12fd9587..00000000000 --- a/examples/kubernetes/configure.sh +++ /dev/null @@ -1,69 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 script generates config.sh, which is a site-local config file that is not -# checked into source control. - -# Erase any existing file since we append from here on. -> config.sh - -# Custom Docker image. -read -p "Vitess Docker image (leave empty for default) []: " -echo "vitess_image=\"$REPLY\"" >> config.sh - -# Select and configure Backup Storage Implementation. -storage=gcs -read -p "Backup Storage (file, gcs) [gcs]: " -if [ -n "$REPLY" ]; then storage="$REPLY"; fi - -case "$storage" in -gcs) - # Google Cloud Storage - read -p "Google Cloud Storage bucket for Vitess backups: " bucket - if [ -z "$bucket" ]; then - echo "ERROR: Bucket name must not be empty." - exit 1 - fi - echo - echo "NOTE: If you haven't already created this bucket, you can do so by running:" - echo " gsutil mb gs://$bucket" - echo - - backup_flags=$(echo -backup_storage_implementation gcs \ - -gcs_backup_storage_bucket "'$bucket'") - ;; -file) - # Mounted volume (e.g. NFS) - read -p "Root directory for backups (usually an NFS mount): " file_root - if [ -z "$file_root" ]; then - echo "ERROR: Root directory must not be empty." - exit 1 - fi - echo - echo "NOTE: You must add your NFS mount to the vtctld-controller-template" - echo " and vttablet-pod-template as described in the Kubernetes docs:" - echo " https://kubernetes.io/docs/concepts/storage/volumes#nfs" - echo - - backup_flags=$(echo -backup_storage_implementation file \ - -file_backup_storage_root "'$file_root'") - ;; -*) - echo "ERROR: Unsupported backup storage implementation: $storage" - exit 1 -esac -echo "backup_flags=\"$backup_flags\"" >> config.sh - diff --git a/examples/kubernetes/create_test_table.sql b/examples/kubernetes/create_test_table.sql deleted file mode 100644 index bfb24b766ad..00000000000 --- a/examples/kubernetes/create_test_table.sql +++ /dev/null @@ -1,7 +0,0 @@ -CREATE TABLE messages ( - page BIGINT(20) UNSIGNED, - time_created_ns BIGINT(20) UNSIGNED, - message VARCHAR(10000), - PRIMARY KEY (page, time_created_ns) -) ENGINE=InnoDB - diff --git a/examples/kubernetes/env.sh b/examples/kubernetes/env.sh deleted file mode 100644 index c644b4de8be..00000000000 --- a/examples/kubernetes/env.sh +++ /dev/null @@ -1,94 +0,0 @@ -#!/bin/bash -# Copyright 2019 The Vitess Authors. -# -# 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 is an include file used by the other scripts in this directory. - -# Most clusters will just be accessed with 'kubectl' on $PATH. -# However, some might require a different command. For example, GKE required -# KUBECTL='gcloud container kubectl' for a while. Now that most of our -# use cases just need KUBECTL=kubectl, we'll make that the default. -KUBECTL=${KUBECTL:-kubectl} - -# Kubernetes API address for $KUBECTL. When the Kubernetes API server is not -# local, We can easily access the API by editing KUBERNETES_API_SERVER's value -KUBERNETES_API_SERVER=${KUBERNETES_API_SERVER:-""} - -# Kubernetes namespace for Vitess and components. -VITESS_NAME=${VITESS_NAME:-'default'} - -# Kubernetes options config -KUBECTL_OPTIONS="--namespace=$VITESS_NAME" -if [[ -n "$KUBERNETES_API_SERVER" ]]; then - KUBECTL_OPTIONS+=" --server=$KUBERNETES_API_SERVER" -fi - -# CELLS should be a comma separated list of cells -# the first cell listed will become local to vtctld. -CELLS=${CELLS:-'test'} - -# This should match the nodePort in vtctld-service.yaml -VTCTLD_PORT=${VTCTLD_PORT:-30001} - -# Get the ExternalIP of any node. -get_node_ip() { - $KUBECTL $KUBECTL_OPTIONS get -o template --template '{{range (index .items 0).status.addresses}}{{if eq .type "ExternalIP" "LegacyHostIP"}}{{.address}}{{end}}{{end}}' nodes -} - -# Try to find vtctld address if not provided. -get_vtctld_addr() { - if [ -z "$VTCTLD_ADDR" ]; then - VTCTLD_HOST=$(get_node_ip) - if [ -n "$VTCTLD_HOST" ]; then - VTCTLD_ADDR="$VTCTLD_HOST:$VTCTLD_PORT" - fi - fi -} - -# Find the name of a vtctld pod. -get_vtctld_pod() { - $KUBECTL $KUBECTL_OPTIONS get -o template --template "{{if ge (len .items) 1 }}{{(index .items 0).metadata.name}}{{end}}" -l 'app=vitess,component=vtctld' pods -} - -start_vtctld_forward() { - pod=`get_vtctld_pod` - if [ -z "$pod" ]; then - >&2 echo "ERROR: Can't get vtctld pod name. Is vtctld running?" - return 1 - fi - - tmpfile=`mktemp` - $KUBECTL $KUBECTL_OPTIONS port-forward $pod 0:15999 &> $tmpfile & - vtctld_forward_pid=$! - - until [[ `cat $tmpfile` =~ :([0-9]+)\ -\> ]]; do :; done - vtctld_forward_port=${BASH_REMATCH[1]} - rm $tmpfile -} - -stop_vtctld_forward() { - kill $vtctld_forward_pid -} - -config_file=`dirname "${BASH_SOURCE}"`/config.sh -if [ ! -f $config_file ]; then - echo "Please run ./configure.sh first to generate config.sh file." - exit 1 -fi - -source $config_file - -# Fill in defaults for new variables, so old config.sh files still work. -vitess_image=${vitess_image:-vitess/lite} - diff --git a/examples/kubernetes/etcd-down.sh b/examples/kubernetes/etcd-down.sh deleted file mode 100755 index ecc912b63de..00000000000 --- a/examples/kubernetes/etcd-down.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is an example script that tears down the etcd servers started by -# etcd-up.sh. - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -replicas=${ETCD_REPLICAS:-3} -cells=`echo $CELLS | tr ',' ' '` - -# Delete etcd clusters -for cell in 'global' $cells; do - echo "Stopping etcd cluster for $cell cell..." - sed -e "s/{{cell}}/$cell/g" -e "s/{{replicas}}/$replicas/g" \ - etcd-service-template.yaml | \ - $KUBECTL $KUBECTL_OPTIONS delete -f - -done diff --git a/examples/kubernetes/etcd-service-template.yaml b/examples/kubernetes/etcd-service-template.yaml deleted file mode 100644 index 9aceaec4b33..00000000000 --- a/examples/kubernetes/etcd-service-template.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: "etcd.database.coreos.com/v1beta2" -kind: "EtcdCluster" -metadata: - name: "etcd-{{cell}}" -spec: - size: {{replicas}} - version: "3.1.8" - repository: "quay.io/coreos/etcd" - pod: - labels: - component: etcd - cell: {{cell}} - application: vitess - busyboxImage: "busybox:1.28.0-glibc" diff --git a/examples/kubernetes/etcd-up.sh b/examples/kubernetes/etcd-up.sh deleted file mode 100755 index f4d4d6118bc..00000000000 --- a/examples/kubernetes/etcd-up.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is an example script that creates etcd clusters. -# Vitess requires a global cluster, as well as one for each cell. -# -# For automatic discovery, an etcd cluster can be bootstrapped from an -# existing cluster. In this example, we use an externally-run discovery -# service, but you can use your own. See the etcd docs for more: -# https://github.com/coreos/etcd/blob/v2.0.13/Documentation/clustering.md - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -replicas=${ETCD_REPLICAS:-3} -cells=`echo $CELLS | tr ',' ' '` - -# Check the installation for etcd-operator has been done. -# To make sure the EtcdClusters CRD not only exists but is ready to serve, -# we try to list EtcdClusters. This will succeed even if the list is empty. -if ! kubectl get etcdclusters.etcd.database.coreos.com &> /dev/null ; then - # etcd-operator is a shared resource, and installing it on a secure - # cluster requires granting RBAC permissions. - # We therefore require the user to do this before running Vitess. - echo - echo "Please install etcd-operator in the same namespace as Vitess" - echo "before running etcd-up.sh. See the instructions here:" - echo - echo " https://github.com/coreos/etcd-operator/blob/master/doc/user/install_guide.md" - echo - echo "If you already installed etcd-operator and still get this prompt," - echo "check for any errors in etcd-operator logs:" - echo - echo " kubectl logs -l name=etcd-operator" - echo - exit 1 -fi - -for cell in 'global' $cells; do - # Create the etcd cluster using etcd-operator - echo "Creating etcd service for '$cell' cell..." - sed -e "s/{{cell}}/$cell/g" -e "s/{{replicas}}/$replicas/g" \ - etcd-service-template.yaml | \ - $KUBECTL $KUBECTL_OPTIONS create -f - -done - diff --git a/examples/kubernetes/guestbook-controller-template.yaml b/examples/kubernetes/guestbook-controller-template.yaml deleted file mode 100644 index 2897b3f5929..00000000000 --- a/examples/kubernetes/guestbook-controller-template.yaml +++ /dev/null @@ -1,29 +0,0 @@ -kind: ReplicationController -apiVersion: v1 -metadata: - name: guestbook -spec: - replicas: 3 - template: - metadata: - labels: - component: frontend - app: guestbook - spec: - containers: - - name: guestbook - image: vitess/guestbook - livenessProbe: - httpGet: - path: /env - port: 8080 - initialDelaySeconds: 30 - timeoutSeconds: 5 - ports: - - name: http-server - containerPort: 8080 - resources: - limits: - memory: "128Mi" - cpu: "100m" - args: ["--port", "{{port}}", "--cell", "{{cell}}", "--keyspace", "{{keyspace}}", "--vtgate_port", "{{vtgate_port}}"] diff --git a/examples/kubernetes/guestbook-down.sh b/examples/kubernetes/guestbook-down.sh deleted file mode 100755 index 35186041553..00000000000 --- a/examples/kubernetes/guestbook-down.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is an example script that stops guestbook. - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -echo "Stopping guestbook replicationcontroller..." -$KUBECTL $KUBECTL_OPTIONS delete replicationcontroller guestbook - -echo "Deleting guestbook service..." -$KUBECTL $KUBECTL_OPTIONS delete service guestbook diff --git a/examples/kubernetes/guestbook-service.yaml b/examples/kubernetes/guestbook-service.yaml deleted file mode 100644 index 341c3ee0314..00000000000 --- a/examples/kubernetes/guestbook-service.yaml +++ /dev/null @@ -1,16 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: guestbook - labels: - component: frontend - app: guestbook -spec: - ports: - - port: 80 - targetPort: http-server - selector: - component: frontend - app: guestbook - type: LoadBalancer - diff --git a/examples/kubernetes/guestbook-up.sh b/examples/kubernetes/guestbook-up.sh deleted file mode 100755 index f246a72e2ec..00000000000 --- a/examples/kubernetes/guestbook-up.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is an example script that starts a guestbook replicationcontroller. - -set -e - -port=${GUESTBOOK_PORT:-8080} -cell=${GUESTBOOK_CELL:-"test"} -keyspace=${GUESTBOOK_KEYSPACE:-"test_keyspace"} -vtgate_port=${VTGATE_PORT:-15991} - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -echo "Creating guestbook service..." -$KUBECTL $KUBECTL_OPTIONS create -f guestbook-service.yaml - -sed_script="" -for var in port cell keyspace vtgate_port; do - sed_script+="s,{{$var}},${!var},g;" -done - -echo "Creating guestbook replicationcontroller..." -sed -e "$sed_script" guestbook-controller-template.yaml | $KUBECTL $KUBECTL_OPTIONS create -f - diff --git a/examples/kubernetes/guestbook/Dockerfile b/examples/kubernetes/guestbook/Dockerfile deleted file mode 100644 index afdd85b4f2e..00000000000 --- a/examples/kubernetes/guestbook/Dockerfile +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright 2019 The Vitess Authors. -# -# 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 Dockerfile should be built from within the accompanying build.sh script. -FROM debian:jessie - -RUN apt-get update -y \ - && apt-get install --no-install-recommends -y -q \ - build-essential \ - python2.7 \ - python2.7-dev \ - python-pip \ - git \ - && pip install -U pip \ - && pip install virtualenv - -WORKDIR /app -RUN virtualenv /env -ADD requirements.txt /app/requirements.txt -RUN /env/bin/pip install -r /app/requirements.txt -ADD main.py requirements.txt /app/ -ADD static /app/static - -EXPOSE 8080 -CMD [] -ENTRYPOINT ["/env/bin/python", "main.py"] - -ADD tmp/pkg /app/pkg -ADD tmp/lib /app/lib -ENV LD_LIBRARY_PATH /app/lib -ENV PYTHONPATH /app/pkg/py-vtdb:/app/pkg/py-mock-1.0.1/lib/python2.7/site-packages:/app/pkg/dist-packages - diff --git a/examples/kubernetes/guestbook/README.md b/examples/kubernetes/guestbook/README.md deleted file mode 100644 index 2ff41a9217c..00000000000 --- a/examples/kubernetes/guestbook/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# vitess/guestbook - -This is a Docker image for a sample guestbook app that uses Vitess. - -It is essentially a port of the -[kubernetes/guestbook-go](https://github.com/kubernetes/examples/tree/master/guestbook-go) -example, but using Python instead of Go for the app server, -and Vitess instead of Redis for the storage engine. - -It has also been modified to support multiple Guestbook pages, -to better demonstrate sharding support in Vitess. - -Note that the Dockerfile should be built with the accompanying build.sh script. -See the comments in the script for more information. diff --git a/examples/kubernetes/guestbook/build.sh b/examples/kubernetes/guestbook/build.sh deleted file mode 100755 index 712bc8bf123..00000000000 --- a/examples/kubernetes/guestbook/build.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is a script to build the vitess/guestbook Docker image. -# It must be run from within a bootstrapped vitess tree, after dev.env. - -set -e - -mkdir tmp tmp/pkg tmp/lib -cp extract.sh tmp/ -chmod -R 777 tmp - -# We also need the grpc library. -docker run --rm -v $PWD/tmp:/out vitess/base bash /out/extract.sh - -# Build the Docker image. -docker build -t vitess/guestbook . - -# Clean up. -docker run --rm -v $PWD/tmp:/out vitess/base bash -c 'rm -rf /out/pkg/* /out/lib/*' -rm -rf tmp diff --git a/examples/kubernetes/guestbook/extract.sh b/examples/kubernetes/guestbook/extract.sh deleted file mode 100644 index e029df3fc77..00000000000 --- a/examples/kubernetes/guestbook/extract.sh +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2019 The Vitess Authors. -# -# 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. -# Don't run this. It is only used as part of build.sh. - -set -e - -# Collect all the local Python libs we need. -mkdir -p /out/pkg/py-vtdb -cp -R $VTTOP/py/* /out/pkg/py-vtdb/ -cp -R /usr/local/lib/python2.7/dist-packages /out/pkg/ -cp -R /vt/dist/py-* /out/pkg/ - diff --git a/examples/kubernetes/guestbook/main.py b/examples/kubernetes/guestbook/main.py deleted file mode 100644 index 9814990b915..00000000000 --- a/examples/kubernetes/guestbook/main.py +++ /dev/null @@ -1,115 +0,0 @@ -# Copyright 2019 The Vitess Authors. -# -# 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. - -"""Main python file.""" - -import argparse -import json -import os -import time - -from flask import Flask - -from vtdb import vtgate_client - -# Register gRPC protocol. -from vtdb import grpc_vtgate_client # pylint: disable=unused-import - -app = Flask(__name__) - -# conn is the connection to vtgate. -conn = None -keyspace = None - - -@app.route('/') -def index(): - return app.send_static_file('index.html') - - -@app.route('/page/') -def view(page): - _ = page - return app.send_static_file('index.html') - - -@app.route('/lrange/guestbook/') -def list_guestbook(page): - """Read the list from a replica.""" - cursor = conn.cursor(tablet_type='replica', keyspace=keyspace) - - cursor.execute( - 'SELECT message, time_created_ns FROM messages WHERE page=:page' - ' ORDER BY time_created_ns', - {'page': page}) - entries = [row[0] for row in cursor.fetchall()] - cursor.close() - - return json.dumps(entries) - - -@app.route('/rpush/guestbook//') -def add_entry(page, value): - """Insert a row on the master.""" - cursor = conn.cursor(tablet_type='master', keyspace=keyspace, writable=True) - - cursor.begin() - cursor.execute( - 'INSERT INTO messages (page, time_created_ns, message)' - ' VALUES (:page, :time_created_ns, :message)', - { - 'page': page, - 'time_created_ns': int(time.time() * 1e9), - 'message': value, - }) - cursor.commit() - - # Read the list back from master (critical read) because it's - # important that the user sees their own addition immediately. - cursor.execute( - 'SELECT message, time_created_ns FROM messages WHERE page=:page' - ' ORDER BY time_created_ns', - {'page': page}) - entries = [row[0] for row in cursor.fetchall()] - cursor.close() - - return json.dumps(entries) - - -@app.route('/env') -def env(): - return json.dumps(dict(os.environ)) - - -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Run guestbook app') - parser.add_argument('--port', help='Port', default=8080, type=int) - parser.add_argument('--cell', help='Cell', default='test', type=str) - parser.add_argument( - '--keyspace', help='Keyspace', default='test_keyspace', type=str) - parser.add_argument( - '--timeout', help='Connect timeout (s)', default=10, type=int) - parser.add_argument( - '--vtgate_port', help='Vtgate Port', default=15991, type=int) - guestbook_args = parser.parse_args() - - # Get vtgate service address from Kubernetes DNS. - addr = 'vtgate-%s:%d' % (guestbook_args.cell, guestbook_args.vtgate_port) - - # Connect to vtgate. - conn = vtgate_client.connect('grpc', addr, guestbook_args.timeout) - - keyspace = guestbook_args.keyspace - - app.run(host='0.0.0.0', port=guestbook_args.port, debug=True) diff --git a/examples/kubernetes/guestbook/requirements.txt b/examples/kubernetes/guestbook/requirements.txt deleted file mode 100644 index eb913c5c387..00000000000 --- a/examples/kubernetes/guestbook/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -Flask==1.0 -grpcio==1.12.0 -grpcio-tools==1.12.0 diff --git a/examples/kubernetes/guestbook/static/index.html b/examples/kubernetes/guestbook/static/index.html deleted file mode 100644 index 946a2b3d986..00000000000 --- a/examples/kubernetes/guestbook/static/index.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - Guestbook - - - - -
-

Waiting for database connection...

-
- -
-
- - Submit -
-
- -
-

-

/env -

- - - - diff --git a/examples/kubernetes/guestbook/static/script.js b/examples/kubernetes/guestbook/static/script.js deleted file mode 100644 index 0240307fcd9..00000000000 --- a/examples/kubernetes/guestbook/static/script.js +++ /dev/null @@ -1,60 +0,0 @@ -$(document).ready(function() { - var headerTitleElement = $("#header h1"); - var entriesElement = $("#guestbook-entries"); - var formElement = $("#guestbook-form"); - var submitElement = $("#guestbook-submit"); - var entryContentElement = $("#guestbook-entry-content"); - var hostAddressElement = $("#guestbook-host-address"); - - // Look for page number in the URL, if any. - var pageNum = -1; - var match = window.location.href.match(/\/page\/(\d+)$/); - if (match) { - pageNum = parseInt(match[1]); - headerTitleElement.text('Guestbook Page ' + pageNum); - } else { - // No page number provided. Link to a random one. - pageNum = Math.floor(Math.random() * 100); - entriesElement.html('

Pick a page to view by navigating to /page/### or go to a random page.

'); - formElement.remove(); - return; - } - - var appendGuestbookEntries = function(data) { - entriesElement.empty(); - $.each(data, function(key, val) { - entriesElement.append("

" + val + "

"); - }); - } - - var handleSubmission = function(e) { - e.preventDefault(); - var entryValue = entryContentElement.val() - if (entryValue.length > 0) { - entriesElement.append("

...

"); - $.getJSON("/rpush/guestbook/" + pageNum + "/" + entryValue, appendGuestbookEntries); - } - return false; - } - - // colors = purple, blue, red, green, yellow - var colors = ["#549", "#18d", "#d31", "#2a4", "#db1"]; - var randomColor = colors[Math.floor(5 * Math.random())]; - (function setElementsColor(color) { - headerTitleElement.css("color", color); - entryContentElement.css("box-shadow", "inset 0 0 0 2px " + color); - submitElement.css("background-color", color); - })(randomColor); - - submitElement.click(handleSubmission); - formElement.submit(handleSubmission); - hostAddressElement.append(document.URL); - - // Poll every second. - (function fetchGuestbook() { - $.getJSON("/lrange/guestbook/" + pageNum).done(appendGuestbookEntries).always( - function() { - setTimeout(fetchGuestbook, 1000); - }); - })(); -}); diff --git a/examples/kubernetes/guestbook/static/style.css b/examples/kubernetes/guestbook/static/style.css deleted file mode 100644 index fd1c393fb08..00000000000 --- a/examples/kubernetes/guestbook/static/style.css +++ /dev/null @@ -1,61 +0,0 @@ -body, input { - color: #123; - font-family: "Gill Sans", sans-serif; -} - -div { - overflow: hidden; - padding: 1em 0; - position: relative; - text-align: center; -} - -h1, h2, p, input, a { - font-weight: 300; - margin: 0; -} - -h1 { - color: #BDB76B; - font-size: 3.5em; -} - -h2 { - color: #999; -} - -form { - margin: 0 auto; - max-width: 50em; - text-align: center; -} - -input { - border: 0; - border-radius: 1000px; - box-shadow: inset 0 0 0 2px #BDB76B; - display: inline; - font-size: 1.5em; - margin-bottom: 1em; - outline: none; - padding: .5em 5%; - width: 55%; -} - -form a { - background: #BDB76B; - border: 0; - border-radius: 1000px; - color: #FFF; - font-size: 1.25em; - font-weight: 400; - padding: .75em 2em; - text-decoration: none; - text-transform: uppercase; - white-space: normal; -} - -p { - font-size: 1.5em; - line-height: 1.5; -} diff --git a/examples/kubernetes/kvtctl.sh b/examples/kubernetes/kvtctl.sh deleted file mode 100755 index 5dcb6dc3730..00000000000 --- a/examples/kubernetes/kvtctl.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is a script that uses kubectl to figure out the address for vtctld, -# and then runs vtctlclient with that address. - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -echo "Starting port forwarding to vtctld..." -start_vtctld_forward -trap stop_vtctld_forward EXIT - -vtctlclient -server 127.0.0.1:$vtctld_forward_port "$@" - diff --git a/examples/kubernetes/namespace-down.sh b/examples/kubernetes/namespace-down.sh deleted file mode 100755 index e5345f412e6..00000000000 --- a/examples/kubernetes/namespace-down.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is an example script that deletes a namespace. - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -namespace=${VITESS_NAME:-'vitess'} - -echo "Deleting namespace $namespace..." -$KUBECTL $KUBECTL_OPTIONS delete namespace $namespace diff --git a/examples/kubernetes/namespace-template.yaml b/examples/kubernetes/namespace-template.yaml deleted file mode 100644 index f0030d5d254..00000000000 --- a/examples/kubernetes/namespace-template.yaml +++ /dev/null @@ -1,4 +0,0 @@ -kind: Namespace -apiVersion: v1 -metadata: - name: {{namespace}} diff --git a/examples/kubernetes/newrelic.sh b/examples/kubernetes/newrelic.sh deleted file mode 100755 index 9cc2a2d0b96..00000000000 --- a/examples/kubernetes/newrelic.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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. - -NEWRELIC_LICENSE_KEY=$1 -VTDATAROOT=$2 - -./newrelic_start_agent.sh $NEWRELIC_LICENSE_KEY -if [ -n "$VTDATAROOT" ]; then - sudo cp newrelic_start*.sh $VTDATAROOT -fi - -mysql_docker_image=`sudo docker ps | awk '$NF~/^k8s_mysql/ {print $1}'` -vttablet_docker_image=`sudo docker ps | awk '$NF~/^k8s_vttablet/ {print $1}'` -vtgate_docker_image=`sudo docker ps | awk '$NF~/^k8s_vtgate/ {print $1}'` -for image in `echo -e "$mysql_docker_image\n$vttablet_docker_image\n$vtgate_docker_image"`; do - if [ -z "$VTDATAROOT" ]; then - vtdataroot=`sudo docker inspect -f '{{index .Volumes "/vt/vtdataroot"}}' $image` - sudo cp newrelic_start*.sh $vtdataroot - fi - sudo docker exec $image apt-get update - sudo docker exec $image apt-get install sudo -y - sudo docker exec $image apt-get install procps -y - sudo docker exec $image bash /vt/vtdataroot/newrelic_start_agent.sh $NEWRELIC_LICENSE_KEY -done diff --git a/examples/kubernetes/newrelic_start_agent.sh b/examples/kubernetes/newrelic_start_agent.sh deleted file mode 100755 index 99b28d1f77f..00000000000 --- a/examples/kubernetes/newrelic_start_agent.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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. - -NEWRELIC_LICENSE_KEY=$1 - -sudo sh -c 'echo deb http://apt.newrelic.com/debian/ newrelic non-free >> /etc/apt/sources.list.d/newrelic.list' -wget -O- https://download.newrelic.com/548C16BF.gpg | sudo apt-key add - -sudo apt-get update -sudo apt-get install newrelic-sysmond -sudo nrsysmond-config --set license_key=$NEWRELIC_LICENSE_KEY -sudo /etc/init.d/newrelic-sysmond start diff --git a/examples/kubernetes/newrelic_start_mysql_plugin.sh b/examples/kubernetes/newrelic_start_mysql_plugin.sh deleted file mode 100755 index 30ab0337401..00000000000 --- a/examples/kubernetes/newrelic_start_mysql_plugin.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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. - -NEWRELIC_LICENSE_KEY=$1 -AGENT_NAME=$2 - -export TERM=screen - -apt-get install openjdk-7-jdk -y - -yes | LICENSE_KEY=$NEWRELIC_LICENSE_KEY bash -c "$(curl -sSL https://download.newrelic.com/npi/release/install-npi-linux-debian-x64.sh)" - -vttablet_dir=`ls /vt/vtdataroot | grep -o vt_.* | tr '\r' ' ' | xargs` -mysql_sock=/vt/vtdataroot/${vttablet_dir}/mysql.sock -mysql -S $mysql_sock -u vt_dba -e "UPDATE mysql.user SET Password=PASSWORD('password') WHERE User='root'; FLUSH PRIVILEGES;" -mysql -S $mysql_sock -u vt_dba -e "create user newrelic@localhost identified by 'password'" -mysql -S $mysql_sock -u vt_dba -e "create user newrelic@127.0.0.1 identified by 'password'" -mysql -S $mysql_sock -u root --password=password -e "grant all on vt_test_keyspace.* to newrelic@localhost" -mysql -S $mysql_sock -u root --password=password -e "grant all on vt_test_keyspace.* to newrelic@127.0.0.1" -mysql -S $mysql_sock -u vt_dba -e "flush privileges;" - - -cd ~/newrelic-npi -./npi set user root -./npi config set license_key=$NEWRELIC_LICENSE_KEY -./npi fetch com.newrelic.plugins.mysql.instance -y -./npi prepare com.newrelic.plugins.mysql.instance -n - -echo "{ - \"agents\": [ - { - \"name\" : \"$AGENT_NAME\", - \"host\" : \"localhost\", - \"metrics\" : \"status,newrelic\", - \"user\" : \"root\", - \"passwd\" : \"password\", - \"properties\": \"mysql?socket=$mysql_sock\" - } - ] -}" > ~/newrelic-npi/plugins/com.newrelic.plugins.mysql.instance/newrelic_mysql_plugin-2.0.0/config/plugin.json - -sleep 10 -./npi add-service com.newrelic.plugins.mysql.instance --start -sleep 10 -./npi start com.newrelic.plugins.mysql.instance diff --git a/examples/kubernetes/orchestrator-down.sh b/examples/kubernetes/orchestrator-down.sh deleted file mode 100755 index 7648583d646..00000000000 --- a/examples/kubernetes/orchestrator-down.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is an example script that stops orchestrator. - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -echo "Stopping orchestrator replicationcontroller..." -$KUBECTL $KUBECTL_OPTIONS delete replicationcontroller orchestrator - -echo "Deleting orchestrator service..." -$KUBECTL $KUBECTL_OPTIONS delete service orchestrator - -echo "Deleting orchestrator configmap..." -$KUBECTL $KUBECTL_OPTIONS delete configmap orchestrator-conf diff --git a/examples/kubernetes/orchestrator-template.yaml b/examples/kubernetes/orchestrator-template.yaml deleted file mode 100644 index 918aaaafffe..00000000000 --- a/examples/kubernetes/orchestrator-template.yaml +++ /dev/null @@ -1,56 +0,0 @@ -# Orchestrator service -apiVersion: v1 -kind: Service -metadata: - name: orchestrator - labels: - component: orchestrator - app: vitess -spec: - ports: - - port: 80 - targetPort: 3000 - selector: - component: orchestrator - app: vitess ---- -# Orchestrator replication controller -apiVersion: v1 -kind: ReplicationController -metadata: - name: orchestrator -spec: - replicas: 1 - template: - metadata: - labels: - component: orchestrator - app: vitess - spec: - containers: - - name: orchestrator - image: vitess/orchestrator - livenessProbe: - httpGet: - path: / - port: 3000 - initialDelaySeconds: 300 - timeoutSeconds: 30 - resources: - limits: - memory: "512Mi" - cpu: "100m" - volumeMounts: - - mountPath: /orc/conf - name: config - - name: mysql - image: vitess/orchestrator - resources: - limits: - memory: "512Mi" - cpu: "100m" - command: ["mysqld"] - volumes: - - name: config - configMap: - name: orchestrator-conf diff --git a/examples/kubernetes/orchestrator-up.sh b/examples/kubernetes/orchestrator-up.sh deleted file mode 100755 index af9544bc12c..00000000000 --- a/examples/kubernetes/orchestrator-up.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is an example script that starts orchestrator. - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -echo "Creating orchestrator service, configmap, and replicationcontroller..." -sed_script="" -for var in service_type; do - sed_script+="s,{{$var}},${!var},g;" -done - -# Create configmap from orchestrator docker config file -$KUBECTL $KUBECTL_OPTIONS create configmap orchestrator-conf --from-file="${script_root}/../../docker/orchestrator/orchestrator.conf.json" - -cat orchestrator-template.yaml | sed -e "$sed_script" | $KUBECTL $KUBECTL_OPTIONS create -f - - -echo -echo "To access orchestrator web UI, start kubectl proxy in another terminal:" -echo " kubectl proxy --port=8001" -echo "Then visit http://localhost:8001/api/v1/proxy/namespaces/$VITESS_NAME/services/orchestrator/" diff --git a/examples/kubernetes/sharded-vtworker.sh b/examples/kubernetes/sharded-vtworker.sh deleted file mode 100755 index 782c8e1c0cb..00000000000 --- a/examples/kubernetes/sharded-vtworker.sh +++ /dev/null @@ -1,64 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is an example script that runs vtworker. - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -cell=test -port=15003 -vtworker_command="$*" - -# Expand template variables -sed_script="" -for var in vitess_image cell port vtworker_command; do - sed_script+="s,{{$var}},${!var},g;" -done - -# Instantiate template and send to kubectl. -echo "Creating vtworker pod in cell $cell..." -cat vtworker-pod-template.yaml | sed -e "$sed_script" | $KUBECTL $KUBECTL_OPTIONS create -f - - -set +e - -# Wait for vtworker pod to show up. -until [ $($KUBECTL $KUBECTL_OPTIONS get pod -o template --template '{{.status.phase}}' vtworker 2> /dev/null) = "Running" ]; do - echo "Waiting for vtworker pod to be created..." - sleep 1 -done - -echo "Following vtworker logs until termination..." -$KUBECTL $KUBECTL_OPTIONS logs -f vtworker - -# Get vtworker exit code. Wait for complete shutdown. -# (Although logs -f exited, the pod isn't fully shutdown yet and the exit code is not available yet.) -until [ $($KUBECTL $KUBECTL_OPTIONS get pod -o template --template '{{.status.phase}}' vtworker 2> /dev/null) != "Running" ]; do - echo "Waiting for vtworker pod to shutdown completely..." - sleep 1 -done -exit_code=$($KUBECTL $KUBECTL_OPTIONS get -o template --template '{{(index .status.containerStatuses 0).state.terminated.exitCode}}' pods vtworker) - -echo "Deleting vtworker pod..." -$KUBECTL $KUBECTL_OPTIONS delete pod vtworker - -if [ "$exit_code" != "0" ]; then - echo - echo "ERROR: vtworker did not run successfully (return value: $exit_code). Please check the error log above and try to run it again." - exit 1 -fi diff --git a/examples/kubernetes/vitess-up.sh b/examples/kubernetes/vitess-up.sh deleted file mode 100755 index 58db653fc8b..00000000000 --- a/examples/kubernetes/vitess-up.sh +++ /dev/null @@ -1,236 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is an example script that creates a fully functional vitess cluster. -# It performs the following steps: -# 1. Create etcd clusters -# 2. Create vtctld clusters -# 3. Forward vtctld port -# 4. Create vttablet clusters -# 5. Perform vtctl initialization: -# SetKeyspaceShardingInfo, Rebuild Keyspace, Reparent Shard, Apply Schema -# 6. Create vtgate clusters -# 7. Forward vtgate port - -# Customizable parameters -VITESS_NAME=${VITESS_NAME:-'vitess'} -SHARDS=${SHARDS:-'-80,80-'} -TABLETS_PER_SHARD=${TABLETS_PER_SHARD:-3} -RDONLY_COUNT=${RDONLY_COUNT:-0} -MAX_TASK_WAIT_RETRIES=${MAX_TASK_WAIT_RETRIES:-300} -MAX_VTTABLET_TOPO_WAIT_RETRIES=${MAX_VTTABLET_TOPO_WAIT_RETRIES:-180} -VTTABLET_TEMPLATE=${VTTABLET_TEMPLATE:-'vttablet-pod-benchmarking-template.yaml'} -VTGATE_TEMPLATE=${VTGATE_TEMPLATE:-'vtgate-controller-benchmarking-template.yaml'} -VTGATE_COUNT=${VTGATE_COUNT:-0} -VTDATAROOT_VOLUME=${VTDATAROOT_VOLUME:-''} -CELLS=${CELLS:-'test'} -KEYSPACE=${KEYSPACE:-'test_keyspace'} -TEST_MODE=${TEST_MODE:-'0'} - -cells=`echo $CELLS | tr ',' ' '` -num_cells=`echo $cells | wc -w` - -num_shards=`echo $SHARDS | tr "," " " | wc -w` -total_tablet_count=$(($num_shards*$TABLETS_PER_SHARD*$num_cells)) -vtgate_count=$VTGATE_COUNT -if [ $vtgate_count -eq 0 ]; then - vtgate_count=$(($total_tablet_count/$num_cells/4>3?$total_tablet_count/$num_cells/4:3)) -fi - -VTCTLD_SERVICE_TYPE=`[[ $TEST_MODE -gt 0 ]] && echo 'LoadBalancer' || echo 'ClusterIP'` - -# export for other scripts -export SHARDS=$SHARDS -export TABLETS_PER_SHARD=$TABLETS_PER_SHARD -export RDONLY_COUNT=$RDONLY_COUNT -export VTDATAROOT_VOLUME=$VTDATAROOT_VOLUME -export VTGATE_TEMPLATE=$VTGATE_TEMPLATE -export VTTABLET_TEMPLATE=$VTTABLET_TEMPLATE -export VTGATE_REPLICAS=$vtgate_count -export VTCTLD_SERVICE_TYPE=$VTCTLD_SERVICE_TYPE -export VITESS_NAME=$VITESS_NAME - -function update_spinner_value () { - spinner='-\|/' - cur_spinner=${spinner:$(($1%${#spinner})):1} -} - -function wait_for_running_tasks () { - # This function waits for pods to be in the "Running" state - # 1. task_name: Name that the desired task begins with - # 2. num_tasks: Number of tasks to wait for - # Returns: - # 0 if successful, -1 if timed out - task_name=$1 - num_tasks=$2 - counter=0 - - echo "Waiting for ${num_tasks}x $task_name to enter state Running" - - while [ $counter -lt $MAX_TASK_WAIT_RETRIES ]; do - # Get status column of pods with name starting with $task_name, - # count how many are in state Running - num_running=`$KUBECTL get pods --namespace=$VITESS_NAME | grep ^$task_name | grep Running | wc -l` - - echo -en "\r$task_name: $num_running out of $num_tasks in state Running..." - if [ $num_running -eq $num_tasks ] - then - echo Complete - return 0 - fi - update_spinner_value $counter - echo -n $cur_spinner - let counter=counter+1 - sleep 1 - done - echo Timed out - return -1 -} - -if [ -z "$GOPATH" ]; then - echo "ERROR: GOPATH undefined, can't obtain vtctlclient" - exit -1 -fi - -export KUBECTL='kubectl' -go get vitess.io/vitess/go/cmd/vtctlclient - -echo "****************************" -echo "*Creating vitess cluster: $VITESS_NAME" -echo "* Shards: $SHARDS" -echo "* Tablets per shard: $TABLETS_PER_SHARD" -echo "* Rdonly per shard: $RDONLY_COUNT" -echo "* VTGate count: $vtgate_count" -echo "* Cells: $cells" -echo "****************************" - -echo 'Running namespace-up.sh' && ./namespace-up.sh - -echo 'Running etcd-up.sh' && CELLS=$CELLS ./etcd-up.sh -wait_for_running_tasks etcd-global 3 -for cell in $cells; do - wait_for_running_tasks etcd-$cell 3 -done - -echo 'Running vtctld-up.sh' && TEST_MODE=$TEST_MODE ./vtctld-up.sh - -wait_for_running_tasks vtctld 1 -kvtctl="./kvtctl.sh" - -if [ $num_shards -gt 0 ] -then - echo Calling CreateKeyspace and SetKeyspaceShardingInfo - $kvtctl CreateKeyspace -force $KEYSPACE - $kvtctl SetKeyspaceShardingInfo -force $KEYSPACE keyspace_id uint64 -fi - -echo 'Running vttablet-up.sh' && CELLS=$CELLS ./vttablet-up.sh -echo 'Running vtgate-up.sh' && ./vtgate-up.sh -wait_for_running_tasks vttablet $total_tablet_count -wait_for_running_tasks vtgate $(($vtgate_count*$num_cells)) - - -echo Waiting for tablets to be visible in the topology -counter=0 -while [ $counter -lt $MAX_VTTABLET_TOPO_WAIT_RETRIES ]; do - num_tablets=0 - for cell in $cells; do - num_tablets=$(($num_tablets+`$kvtctl ListAllTablets $cell | grep $KEYSPACE | wc -l`)) - done - echo -en "\r$num_tablets out of $total_tablet_count in topology..." - if [ $num_tablets -eq $total_tablet_count ] - then - echo Complete - break - fi - update_spinner_value $counter - echo -n $cur_spinner - let counter=counter+1 - sleep 1 - if [ $counter -eq $MAX_VTTABLET_TOPO_WAIT_RETRIES ] - then - echo Timed out - fi -done - -echo -n Setting Keyspace Sharding Info... -$kvtctl SetKeyspaceShardingInfo -force $KEYSPACE keyspace_id uint64 -echo Done -echo -n Rebuilding Keyspace Graph... -$kvtctl RebuildKeyspaceGraph $KEYSPACE -echo Done -echo -n Reparenting... -shard_num=1 -master_cell=`echo $cells | awk '{print $1}'` -for shard in $(echo $SHARDS | tr "," " "); do - [[ $num_cells -gt 1 ]] && cell_id=01 || cell_id=00 - printf -v master_tablet_id '%s-%02d0000%02d00' $master_cell $cell_id $shard_num - $kvtctl InitShardMaster -force $KEYSPACE/$shard $master_tablet_id - let shard_num=shard_num+1 -done -echo Done -echo -n Applying Schema... -$kvtctl ApplySchema -sql "$(cat create_test_table.sql)" $KEYSPACE -echo Done - -if [ $TEST_MODE -gt 0 ]; then - echo Creating firewall rule for vtctld - vtctld_port=15000 - gcloud compute firewall-rules create ${VITESS_NAME}-vtctld --allow tcp:$vtctld_port - vtctld_ip='' - until [ $vtctld_ip ]; do - vtctld_ip=`$KUBECTL get -o template --template '{{if ge (len .status.loadBalancer) 1}}{{index (index .status.loadBalancer.ingress 0) "ip"}}{{end}}' service vtctld --namespace=$VITESS_NAME` - sleep 1 - done - vtctld_server="$vtctld_ip:$vtctld_port" -fi - -vtgate_servers='' -for cell in $cells; do - echo Creating firewall rule for vtgate in cell $cell - vtgate_port=15001 - gcloud compute firewall-rules create ${VITESS_NAME}-vtgate-$cell --allow tcp:$vtgate_port - vtgate_ip='' - until [ $vtgate_ip ]; do - vtgate_ip=`$KUBECTL get -o template --template '{{if ge (len .status.loadBalancer) 1}}{{index (index .status.loadBalancer.ingress 0) "ip"}}{{end}}' service vtgate-$cell --namespace=$VITESS_NAME` - sleep 1 - done - vtgate_servers+="vtgate-$cell: $vtgate_ip:$vtgate_port," -done - -if [ -n "$NEWRELIC_LICENSE_KEY" ]; then - echo Setting up Newrelic monitoring - i=1 - for nodename in `$KUBECTL get nodes --no-headers --namespace=$VITESS_NAME | awk '{print $1}'`; do - gcloud compute copy-files newrelic.sh $nodename:~/ - gcloud compute copy-files newrelic_start_agent.sh $nodename:~/ - gcloud compute copy-files newrelic_start_mysql_plugin.sh $nodename:~/ - gcloud compute ssh $nodename --command "bash -c '~/newrelic.sh ${NEWRELIC_LICENSE_KEY} ${VTDATAROOT}'" - let i=i+1 - done -fi - -echo "****************************" -echo "* Complete!" -if [ $TEST_MODE -gt 0 ]; then - echo "* vtctld: $vtctld_server" -else - echo "* Access the vtctld web UI by performing the following steps:" - echo "* $ kubectl proxy --port=8001" - echo "* Visit http://localhost:8001/api/v1/proxy/namespaces/default/services/vtctld:web/" -fi -echo $vtgate_servers | awk -F',' '{for(i=1;i- - mkdir -p $VTDATAROOT/tmp && - chown -R vitess /vt && - su -p -c "/vt/bin/vtctld - -cell {{cell}} - -web_dir $VTTOP/web/vtctld - -web_dir2 $VTTOP/web/vtctld2/app - -workflow_manager_init - -workflow_manager_use_election - -log_dir $VTDATAROOT/tmp - -alsologtostderr - -port 15000 - -grpc_port 15999 - -service_map 'grpc-vtctl' - -topo_implementation etcd2 - -topo_global_server_address http://etcd-global-client:2379 - -topo_global_root /global - {{backup_flags}} {{test_flags}}" vitess - volumes: - - name: syslog - hostPath: {path: /dev/log} - - name: vtdataroot - emptyDir: {} - - name: certs - # Uncomment one of the following lines to configure the location - # of the root certificates file on your host OS. We need this so - # we can import it into the container OS. - # If your host OS is Fedora/RHEL: - #hostPath: {path: /etc/pki/tls/certs/ca-bundle.crt} - # If your host OS is Debian/Ubuntu/Gentoo: - hostPath: {path: /etc/ssl/certs/ca-certificates.crt} diff --git a/examples/kubernetes/vtctld-down.sh b/examples/kubernetes/vtctld-down.sh deleted file mode 100755 index a48e803aaf2..00000000000 --- a/examples/kubernetes/vtctld-down.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is an example script that stops vtctld. - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -echo "Stopping vtctld replicationcontroller..." -$KUBECTL $KUBECTL_OPTIONS delete replicationcontroller vtctld - -echo "Deleting vtctld service..." -$KUBECTL $KUBECTL_OPTIONS delete service vtctld diff --git a/examples/kubernetes/vtctld-service-template.yaml b/examples/kubernetes/vtctld-service-template.yaml deleted file mode 100644 index 59327cb7d1a..00000000000 --- a/examples/kubernetes/vtctld-service-template.yaml +++ /dev/null @@ -1,17 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: vtctld - labels: - component: vtctld - app: vitess -spec: - ports: - - name: web - port: 15000 - - name: grpc - port: 15999 - selector: - component: vtctld - app: vitess - type: {{service_type}} diff --git a/examples/kubernetes/vtctld-up.sh b/examples/kubernetes/vtctld-up.sh deleted file mode 100755 index 1e65c6f587d..00000000000 --- a/examples/kubernetes/vtctld-up.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is an example script that starts vtctld. - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -service_type=${VTCTLD_SERVICE_TYPE:-'ClusterIP'} -cell=(`echo $CELLS | tr ',' ' '`) # ref to cell will get first element -TEST_MODE=${TEST_MODE:-'0'} - -test_flags=`[[ $TEST_MODE -gt 0 ]] && echo '-enable_queries' || echo ''` - -echo "Creating vtctld $service_type service..." -sed_script="" -for var in service_type; do - sed_script+="s,{{$var}},${!var},g;" -done -cat vtctld-service-template.yaml | sed -e "$sed_script" | $KUBECTL $KUBECTL_OPTIONS create -f - - -echo "Creating vtctld replicationcontroller..." -# Expand template variables -sed_script="" -for var in vitess_image backup_flags test_flags cell; do - sed_script+="s,{{$var}},${!var},g;" -done - -# Instantiate template and send to kubectl. -cat vtctld-controller-template.yaml | sed -e "$sed_script" | $KUBECTL $KUBECTL_OPTIONS create -f - - -echo -echo "To access vtctld web UI, start kubectl proxy in another terminal:" -echo " kubectl proxy --port=8001" -echo "Then visit http://localhost:8001/api/v1/namespaces/$VITESS_NAME/services/vtctld:web/proxy" \ No newline at end of file diff --git a/examples/kubernetes/vtgate-controller-benchmarking-template.yaml b/examples/kubernetes/vtgate-controller-benchmarking-template.yaml deleted file mode 100644 index a5db7c585e8..00000000000 --- a/examples/kubernetes/vtgate-controller-benchmarking-template.yaml +++ /dev/null @@ -1,58 +0,0 @@ -kind: ReplicationController -apiVersion: v1 -metadata: - name: vtgate-{{cell}} -spec: - replicas: {{replicas}} - template: - metadata: - labels: - component: vtgate - cell: {{cell}} - app: vitess - spec: - containers: - - name: vtgate - image: vitess/root - livenessProbe: - httpGet: - path: /debug/vars - port: 15001 - initialDelaySeconds: 30 - timeoutSeconds: 5 - volumeMounts: - - name: syslog - mountPath: /dev/log - - name: vtdataroot - mountPath: /vt/vtdataroot - resources: - limits: - memory: "4Gi" - cpu: "6" - command: - - sh - - "-c" - - >- - mkdir -p $VTDATAROOT/tmp && - chown -R vitess /vt && - su -p -c "/vt/bin/vtgate - -topo_implementation etcd2 - -topo_global_server_address http://etcd-global-client:2379 - -topo_global_root /global - -log_dir $VTDATAROOT/tmp - -alsologtostderr - -port 15001 - -grpc_port 15991 - -service_map 'grpc-vtgateservice' - -cells_to_watch {{cell}} - -tablet_types_to_wait MASTER,REPLICA - -gateway_implementation discoverygateway - -cell {{cell}}" vitess - env: - - name: GOMAXPROCS - value: "16" - volumes: - - name: syslog - hostPath: {path: /dev/log} - - name: vtdataroot - {{vtdataroot_volume}} diff --git a/examples/kubernetes/vtgate-controller-template.yaml b/examples/kubernetes/vtgate-controller-template.yaml deleted file mode 100644 index bbaac915b98..00000000000 --- a/examples/kubernetes/vtgate-controller-template.yaml +++ /dev/null @@ -1,58 +0,0 @@ -kind: ReplicationController -apiVersion: v1 -metadata: - name: vtgate-{{cell}} -spec: - replicas: {{replicas}} - template: - metadata: - labels: - component: vtgate - cell: {{cell}} - app: vitess - spec: - containers: - - name: vtgate - image: {{vitess_image}} - livenessProbe: - httpGet: - path: /debug/vars - port: 15001 - initialDelaySeconds: 30 - timeoutSeconds: 5 - volumeMounts: - - name: syslog - mountPath: /dev/log - - name: vtdataroot - mountPath: /vt/vtdataroot - resources: - limits: - memory: "512Mi" - cpu: "500m" - command: - - sh - - "-c" - - >- - mkdir -p $VTDATAROOT/tmp && - chown -R vitess /vt && - su -p -c "/vt/bin/vtgate - -topo_implementation etcd2 - -topo_global_server_address http://etcd-global-client:2379 - -topo_global_root /global - -log_dir $VTDATAROOT/tmp - -alsologtostderr - -port 15001 - -grpc_port 15991 - -mysql_server_port {{mysql_server_port}} - -mysql_auth_server_static_string '{\"mysql_user\":{\"Password\":\"mysql_password\"}}' - -service_map 'grpc-vtgateservice' - -cells_to_watch {{cell}} - -tablet_types_to_wait MASTER,REPLICA - -gateway_implementation discoverygateway - -cell {{cell}}" vitess - volumes: - - name: syslog - hostPath: {path: /dev/log} - - name: vtdataroot - emptyDir: {} - diff --git a/examples/kubernetes/vtgate-down.sh b/examples/kubernetes/vtgate-down.sh deleted file mode 100755 index 96c29c9c33b..00000000000 --- a/examples/kubernetes/vtgate-down.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is an example script that stops vtgate. - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -cells=`echo $CELLS | tr ',' ' '` - -for cell in $cells; do - echo "Stopping vtgate replicationcontroller in cell $cell..." - $KUBECTL $KUBECTL_OPTIONS delete replicationcontroller vtgate-$cell - - echo "Deleting vtgate service in cell $cell..." - $KUBECTL $KUBECTL_OPTIONS delete service vtgate-$cell -done - diff --git a/examples/kubernetes/vtgate-service-template.yaml b/examples/kubernetes/vtgate-service-template.yaml deleted file mode 100644 index 8a9f7450c99..00000000000 --- a/examples/kubernetes/vtgate-service-template.yaml +++ /dev/null @@ -1,21 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: vtgate-{{cell}} - labels: - component: vtgate - cell: {{cell}} - app: vitess -spec: - ports: - - name: web - port: 15001 - - name: grpc - port: 15991 - - name: mysql - port: {{mysql_server_port}} - selector: - component: vtgate - cell: {{cell}} - app: vitess - type: LoadBalancer diff --git a/examples/kubernetes/vtgate-up.sh b/examples/kubernetes/vtgate-up.sh deleted file mode 100755 index 66ef0667024..00000000000 --- a/examples/kubernetes/vtgate-up.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is an example script that starts a vtgate replicationcontroller. - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -# NOTE: mysql server support is currently in beta -mysql_server_port=${MYSQL_SERVER_PORT:-3306} - -VTGATE_REPLICAS=${VTGATE_REPLICAS:-3} -VTDATAROOT_VOLUME=${VTDATAROOT_VOLUME:-''} -VTGATE_TEMPLATE=${VTGATE_TEMPLATE:-'vtgate-controller-template.yaml'} - -vtdataroot_volume='emptyDir: {}' -if [ -n "$VTDATAROOT_VOLUME" ]; then - vtdataroot_volume="hostPath: {path: ${VTDATAROOT_VOLUME}}" -fi - -replicas=$VTGATE_REPLICAS - -cells=`echo $CELLS | tr ',' ' '` -for cell in $cells; do - sed_script="" - for var in cell; do - sed_script+="s,{{$var}},${!var},g;" - done - - sed_script+="s,{{mysql_server_port}},$mysql_server_port,g;" - - echo "Creating vtgate service in cell $cell..." - cat vtgate-service-template.yaml | sed -e "$sed_script" | $KUBECTL $KUBECTL_OPTIONS create -f - - - sed_script="" - for var in vitess_image replicas vtdataroot_volume cell mysql_server_port; do - sed_script+="s,{{$var}},${!var},g;" - done - - echo "Creating vtgate replicationcontroller in cell $cell..." - cat $VTGATE_TEMPLATE | sed -e "$sed_script" | $KUBECTL $KUBECTL_OPTIONS create -f - -done diff --git a/examples/kubernetes/vttablet-down.sh b/examples/kubernetes/vttablet-down.sh deleted file mode 100755 index e3fe9a67b03..00000000000 --- a/examples/kubernetes/vttablet-down.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is an example script that tears down the vttablet pods started by -# vttablet-up.sh. - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -echo "Starting port forwarding to vtctld..." -start_vtctld_forward -trap stop_vtctld_forward EXIT -VTCTLD_ADDR="localhost:$vtctld_forward_port" - -# Delete the pods for all shards -keyspace='test_keyspace' -SHARDS=${SHARDS:-'0'} -TABLETS_PER_SHARD=${TABLETS_PER_SHARD:-5} -UID_BASE=${UID_BASE:-100} - -num_shards=`echo $SHARDS | tr "," " " | wc -w` -uid_base=$UID_BASE -cells=`echo $CELLS | tr ',' ' '` -num_cells=`echo $cells | wc -w` - -for shard in `seq 1 $num_shards`; do - [[ $num_cells -gt 1 ]] && cell_index=100000000 || cell_index=0 - for cell in $cells; do - for uid_index in `seq 0 $(($TABLETS_PER_SHARD-1))`; do - uid=$[$uid_base + $uid_index + $cell_index] - printf -v alias '%s-%010d' $cell $uid - - echo "Deleting pod for tablet $alias..." - $KUBECTL $KUBECTL_OPTIONS delete pod vttablet-$uid - done - let cell_index=cell_index+100000000 - done - let uid_base=uid_base+100 -done diff --git a/examples/kubernetes/vttablet-pod-benchmarking-template.yaml b/examples/kubernetes/vttablet-pod-benchmarking-template.yaml deleted file mode 100644 index 8f24da64f54..00000000000 --- a/examples/kubernetes/vttablet-pod-benchmarking-template.yaml +++ /dev/null @@ -1,98 +0,0 @@ -kind: Pod -apiVersion: v1 -metadata: - name: vttablet-{{uid}} - labels: - component: vttablet - keyspace: "{{keyspace}}" - shard: "{{shard_label}}" - tablet: "{{alias}}" - app: vitess -spec: - containers: - - name: vttablet - image: vitess/root - resources: - limits: - memory: "4Gi" - cpu: "2" - volumeMounts: - - name: syslog - mountPath: /dev/log - - name: vtdataroot - mountPath: /vt/vtdataroot - command: - - bash - - "-c" - - >- - set -e - - mysql_socket="$VTDATAROOT/{{tablet_subdir}}/mysql.sock" - - mkdir -p $VTDATAROOT/tmp - - chown -R vitess /vt - - while [ ! -e $mysql_socket ]; do - echo "[$(date)] waiting for $mysql_socket" ; - sleep 1 ; - done - - su -p -s /bin/bash -c "mysql -u vt_dba -S $mysql_socket - -e 'CREATE DATABASE IF NOT EXISTS vt_{{keyspace}}'" vitess - - su -p -s /bin/bash -c "/vt/bin/vttablet - -topo_implementation etcd2 - -topo_global_server_address http://etcd-global-client:2379 - -topo_global_root /global - -log_dir $VTDATAROOT/tmp - -alsologtostderr - -port {{port}} - -grpc_port {{grpc_port}} - -service_map 'grpc-queryservice,grpc-tabletmanager,grpc-updatestream' - -tablet-path {{alias}} - -tablet_hostname $(hostname -i) - -init_keyspace {{keyspace}} - -init_shard {{shard}} - -init_tablet_type {{tablet_type}} - -mysqlctl_socket $VTDATAROOT/mysqlctl.sock - -queryserver-config-transaction-cap 300 - -queryserver-config-schema-reload-time 1 - -queryserver-config-pool-size 100 - -enable_replication_reporter" vitess - env: - - name: GOMAXPROCS - value: "16" - - name: mysql - image: vitess/root - resources: - limits: - memory: "4Gi" - cpu: "2" - volumeMounts: - - name: syslog - mountPath: /dev/log - - name: vtdataroot - mountPath: /vt/vtdataroot - command: - - sh - - "-c" - - >- - mkdir -p $VTDATAROOT/tmp && - chown -R vitess /vt - - su -p -c "/vt/bin/mysqlctld - -log_dir $VTDATAROOT/tmp - -alsologtostderr - -tablet_uid {{uid}} - -socket_file $VTDATAROOT/mysqlctl.sock - -init_db_sql_file $VTROOT/config/init_db.sql" vitess - env: - - name: EXTRA_MY_CNF - value: /vt/config/mycnf/benchmark.cnf:/vt/config/mycnf/master_mysql56.cnf - volumes: - - name: syslog - hostPath: {path: /dev/log} - - name: vtdataroot - {{vtdataroot_volume}} - diff --git a/examples/kubernetes/vttablet-pod-template.yaml b/examples/kubernetes/vttablet-pod-template.yaml deleted file mode 100644 index 52e19aad80f..00000000000 --- a/examples/kubernetes/vttablet-pod-template.yaml +++ /dev/null @@ -1,115 +0,0 @@ -kind: Pod -apiVersion: v1 -metadata: - name: vttablet-{{uid}} - labels: - component: vttablet - keyspace: "{{keyspace}}" - shard: "{{shard_label}}" - tablet: "{{alias}}" - app: vitess -spec: - containers: - - name: vttablet - image: {{vitess_image}} - livenessProbe: - httpGet: - path: /debug/vars - port: {{port}} - initialDelaySeconds: 60 - timeoutSeconds: 10 - volumeMounts: - - name: syslog - mountPath: /dev/log - - name: vtdataroot - mountPath: /vt/vtdataroot - - name: certs - readOnly: true - # Mount root certs from the host OS into the location - # expected for our container OS (Debian): - mountPath: /etc/ssl/certs/ca-certificates.crt - resources: - limits: - memory: "1Gi" - cpu: "500m" - ports: - - name: web - containerPort: {{port}} - - name: grpc - containerPort: {{grpc_port}} - command: - - bash - - "-c" - - >- - set -e - - mkdir -p $VTDATAROOT/tmp - - chown -R vitess /vt - - su -p -s /bin/bash -c "/vt/bin/vttablet - -binlog_use_v3_resharding_mode - -topo_implementation etcd2 - -topo_global_server_address http://etcd-global-client:2379 - -topo_global_root /global - -log_dir $VTDATAROOT/tmp - -alsologtostderr - -port {{port}} - -grpc_port {{grpc_port}} - -service_map 'grpc-queryservice,grpc-tabletmanager,grpc-updatestream' - -tablet-path {{alias}} - -tablet_hostname $(hostname -i) - -init_keyspace {{keyspace}} - -init_shard {{shard}} - -init_tablet_type {{tablet_type}} - -health_check_interval 5s - -mysqlctl_socket $VTDATAROOT/mysqlctl.sock - -enable_semi_sync - -enable_replication_reporter - -orc_api_url http://orchestrator/api - -orc_discover_interval 5m - -restore_from_backup {{backup_flags}}" vitess - env: - - name: EXTRA_MY_CNF - value: /vt/config/mycnf/master_mysql56.cnf - - name: mysql - image: {{vitess_image}} - volumeMounts: - - name: syslog - mountPath: /dev/log - - name: vtdataroot - mountPath: /vt/vtdataroot - resources: - limits: - memory: "1Gi" - cpu: "500m" - command: - - sh - - "-c" - - >- - mkdir -p $VTDATAROOT/tmp && - chown -R vitess /vt - - su -p -c "/vt/bin/mysqlctld - -log_dir $VTDATAROOT/tmp - -alsologtostderr - -tablet_uid {{uid}} - -socket_file $VTDATAROOT/mysqlctl.sock - -init_db_sql_file $VTROOT/config/init_db.sql" vitess - env: - - name: EXTRA_MY_CNF - value: /vt/config/mycnf/master_mysql56.cnf - volumes: - - name: syslog - hostPath: {path: /dev/log} - - name: vtdataroot - {{vtdataroot_volume}} - - name: certs - # Uncomment one of the following lines to configure the location - # of the root certificates file on your host OS. We need this so - # we can import it into the container OS. - # If your host OS is Fedora/RHEL: - #hostPath: {path: /etc/pki/tls/certs/ca-bundle.crt} - # If your host OS is Debian/Ubuntu/Gentoo: - hostPath: {path: /etc/ssl/certs/ca-certificates.crt} - diff --git a/examples/kubernetes/vttablet-up.sh b/examples/kubernetes/vttablet-up.sh deleted file mode 100755 index 8fbdcfc5ff3..00000000000 --- a/examples/kubernetes/vttablet-up.sh +++ /dev/null @@ -1,77 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is an example script that creates a vttablet deployment. - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -# Create the pods for shard-0 -keyspace=${KEYSPACE:-'test_keyspace'} -SHARDS=${SHARDS:-'0'} -TABLETS_PER_SHARD=${TABLETS_PER_SHARD:-5} -port=15002 -grpc_port=16002 -UID_BASE=${UID_BASE:-100} -VTTABLET_TEMPLATE=${VTTABLET_TEMPLATE:-'vttablet-pod-template.yaml'} -VTDATAROOT_VOLUME=${VTDATAROOT_VOLUME:-''} -RDONLY_COUNT=${RDONLY_COUNT:-2} - -vtdataroot_volume='emptyDir: {}' -if [ -n "$VTDATAROOT_VOLUME" ]; then - vtdataroot_volume="hostPath: {path: ${VTDATAROOT_VOLUME}}" -fi - -uid_base=$UID_BASE -indices=${TASKS:-`seq 0 $(($TABLETS_PER_SHARD-1))`} -cells=`echo $CELLS | tr ',' ' '` -num_cells=`echo $cells | wc -w` - -for shard in $(echo $SHARDS | tr "," " "); do - [[ $num_cells -gt 1 ]] && cell_index=100000000 || cell_index=0 - for cell in $cells; do - echo "Creating $keyspace.shard-$shard pods in cell $cell..." - for uid_index in $indices; do - uid=$[$uid_base + $uid_index + $cell_index] - printf -v alias '%s-%010d' $cell $uid - printf -v tablet_subdir 'vt_%010d' $uid - - echo "Creating pod for tablet $alias..." - - # Add xx to beginning or end if there is a dash. K8s does not allow for - # leading or trailing dashes for labels - shard_label=`echo $shard | sed s'/[-]$/-xx/' | sed s'/^-/xx-/'` - - tablet_type=replica - if [ $uid_index -gt $(($TABLETS_PER_SHARD-$RDONLY_COUNT-1)) ]; then - tablet_type=rdonly - fi - - # Expand template variables - sed_script="" - for var in vitess_image alias cell uid keyspace shard shard_label port grpc_port tablet_subdir vtdataroot_volume tablet_type backup_flags; do - sed_script+="s,{{$var}},${!var},g;" - done - - # Instantiate template and send to kubectl. - cat $VTTABLET_TEMPLATE | sed -e "$sed_script" | $KUBECTL $KUBECTL_OPTIONS create -f - - done - let cell_index=cell_index+100000000 - done - let uid_base=uid_base+100 -done diff --git a/examples/kubernetes/vtworker-controller-interactive-template.yaml b/examples/kubernetes/vtworker-controller-interactive-template.yaml deleted file mode 100644 index b3f86ae191e..00000000000 --- a/examples/kubernetes/vtworker-controller-interactive-template.yaml +++ /dev/null @@ -1,42 +0,0 @@ -kind: ReplicationController -apiVersion: v1 -metadata: - name: vtworker -spec: - replicas: 1 - template: - metadata: - labels: - component: vtworker - app: vitess - spec: - containers: - - name: vtworker - image: {{vitess_image}} - volumeMounts: - - name: syslog - mountPath: /dev/log - - name: vtdataroot - mountPath: /vt/vtdataroot - command: - - sh - - "-c" - - >- - mkdir -p $VTDATAROOT/tmp && - chown -R vitess /vt && - su -p -c "/vt/bin/vtworker - -log_dir $VTDATAROOT/tmp - -alsologtostderr - -port {{port}} - -grpc_port {{grpc_port}} - -service_map \"grpc-vtworker\" - -topo_implementation etcd2 - -topo_global_server_address http://etcd-global-client:2379 - -topo_global_root /global - -cell {{cell}} - -use_v3_resharding_mode" vitess - volumes: - - name: syslog - hostPath: {path: /dev/log} - - name: vtdataroot - emptyDir: {} diff --git a/examples/kubernetes/vtworker-down.sh b/examples/kubernetes/vtworker-down.sh deleted file mode 100755 index d1ab7330b49..00000000000 --- a/examples/kubernetes/vtworker-down.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is an example script that stops vtworker. - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -echo "Stopping vtworker replicationcontroller..." -$KUBECTL $KUBECTL_OPTIONS delete replicationcontroller vtworker - -echo "Deleting vtworker service..." -$KUBECTL $KUBECTL_OPTIONS delete service vtworker diff --git a/examples/kubernetes/vtworker-pod-template.yaml b/examples/kubernetes/vtworker-pod-template.yaml deleted file mode 100644 index 08ab4d68d36..00000000000 --- a/examples/kubernetes/vtworker-pod-template.yaml +++ /dev/null @@ -1,39 +0,0 @@ -kind: Pod -apiVersion: v1 -metadata: - name: vtworker - labels: - component: vtworker - app: vitess -spec: - containers: - - name: vtworker - image: {{vitess_image}} - volumeMounts: - - name: syslog - mountPath: /dev/log - - name: vtdataroot - mountPath: /vt/vtdataroot - command: - - sh - - "-c" - - >- - mkdir -p $VTDATAROOT/tmp && - chown -R vitess /vt && - su -p -c "/vt/bin/vtworker - -log_dir $VTDATAROOT/tmp - -alsologtostderr - -port {{port}} - -topo_implementation etcd2 - -topo_global_server_address http://etcd-global-client:2379 - -topo_global_root /global - -cell {{cell}} - -use_v3_resharding_mode - {{vtworker_command}}" vitess - restartPolicy: Never - volumes: - - name: syslog - hostPath: {path: /dev/log} - - name: vtdataroot - emptyDir: {} - diff --git a/examples/kubernetes/vtworker-service-template.yaml b/examples/kubernetes/vtworker-service-template.yaml deleted file mode 100644 index 1fbb7403c44..00000000000 --- a/examples/kubernetes/vtworker-service-template.yaml +++ /dev/null @@ -1,17 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: vtworker - labels: - component: vtworker - app: vitess -spec: - ports: - - name: web - port: {{port}} - - name: grpc - port: {{grpc_port}} - selector: - component: vtworker - app: vitess - type: {{service_type}} diff --git a/examples/kubernetes/vtworker-up.sh b/examples/kubernetes/vtworker-up.sh deleted file mode 100755 index d5cc3e32ccb..00000000000 --- a/examples/kubernetes/vtworker-up.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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. - -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -cell=(`echo $CELLS | tr ',' ' '`) # ref to cell will get first element -port=15032 -grpc_port=15033 - -sed_script="" -for var in vitess_image cell port grpc_port; do - sed_script+="s,{{$var}},${!var},g;" -done - -echo "Creating vtworker pod in cell $cell..." -cat vtworker-controller-interactive-template.yaml | sed -e "$sed_script" | $KUBECTL $KUBECTL_OPTIONS create -f - - -set +e - -service_type='LoadBalancer' -echo "Creating vtworker $service_type service..." -sed_script="" -for var in service_type port grpc_port; do - sed_script+="s,{{$var}},${!var},g;" -done -cat vtworker-service-template.yaml | sed -e "$sed_script" | $KUBECTL $KUBECTL_OPTIONS create -f - diff --git a/examples/local/101_initial_cluster.sh b/examples/local/101_initial_cluster.sh index 9f018da6b55..62e4542cc09 100755 --- a/examples/local/101_initial_cluster.sh +++ b/examples/local/101_initial_cluster.sh @@ -17,39 +17,32 @@ # this script brings up zookeeper and all the vitess components # required for a single shard deployment. -set -e - -# shellcheck disable=SC2128 -script_root=$(dirname "${BASH_SOURCE}") - -if [[ $EUID -eq 0 ]]; then - echo "This script refuses to be run as root. Please switch to a regular user." - exit 1 -fi +source ./env.sh # start topo server if [ "${TOPO}" = "zk2" ]; then - CELL=zone1 "$script_root/zk-up.sh" + CELL=zone1 ./scripts/zk-up.sh else - CELL=zone1 "$script_root/etcd-up.sh" + CELL=zone1 ./scripts/etcd-up.sh fi # start vtctld -CELL=zone1 "$script_root/vtctld-up.sh" +CELL=zone1 ./scripts/vtctld-up.sh # start vttablets for keyspace commerce -CELL=zone1 KEYSPACE=commerce UID_BASE=100 "$script_root/vttablet-up.sh" +for i in 100 101 102; do + CELL=zone1 TABLET_UID=$i ./scripts/mysqlctl-up.sh + CELL=zone1 KEYSPACE=commerce TABLET_UID=$i ./scripts/vttablet-up.sh +done # set one of the replicas to master -./lvtctl.sh InitShardMaster -force commerce/0 zone1-100 +vtctlclient -server localhost:15999 InitShardMaster -force commerce/0 zone1-100 # create the schema -./lvtctl.sh ApplySchema -sql-file create_commerce_schema.sql commerce +vtctlclient -server localhost:15999 ApplySchema -sql-file create_commerce_schema.sql commerce # create the vschema -./lvtctl.sh ApplyVSchema -vschema_file vschema_commerce_initial.json commerce +vtctlclient -server localhost:15999 ApplyVSchema -vschema_file vschema_commerce_initial.json commerce # start vtgate -CELL=zone1 "$script_root/vtgate-up.sh" - -disown -a +CELL=zone1 ./scripts/vtgate-up.sh diff --git a/examples/local/201_customer_keyspace.sh b/examples/local/201_customer_keyspace.sh index 72c415e6527..f948175195c 100755 --- a/examples/local/201_customer_keyspace.sh +++ b/examples/local/201_customer_keyspace.sh @@ -16,8 +16,5 @@ # this script creates a new keyspace in preparation for vertical resharding -set -e +vtctlclient -server localhost:15999 CreateKeyspace -served_from='master:commerce,replica:commerce,rdonly:commerce' customer -./lvtctl.sh CreateKeyspace -served_from='master:commerce,replica:commerce,rdonly:commerce' customer - -disown -a diff --git a/examples/local/202_customer_tablets.sh b/examples/local/202_customer_tablets.sh index 9420ba19713..ec77226342f 100755 --- a/examples/local/202_customer_tablets.sh +++ b/examples/local/202_customer_tablets.sh @@ -18,16 +18,15 @@ # resharding it also splits the vschema between the two keyspaces # old (commerce) and new (customer) -set -e +source ./env.sh -# shellcheck disable=SC2128 -script_root=$(dirname "${BASH_SOURCE}") +for i in 200 201 202; do + CELL=zone1 TABLET_UID=$i ./scripts/mysqlctl-up.sh + CELL=zone1 KEYSPACE=customer TABLET_UID=$i ./scripts/vttablet-up.sh +done -CELL=zone1 KEYSPACE=customer UID_BASE=200 "$script_root/vttablet-up.sh" +vtctlclient -server localhost:15999 InitShardMaster -force customer/0 zone1-200 +vtctlclient -server localhost:15999 CopySchemaShard -tables customer,corder commerce/0 customer/0 +vtctlclient -server localhost:15999 ApplyVSchema -vschema_file vschema_commerce_vsplit.json commerce +vtctlclient -server localhost:15999 ApplyVSchema -vschema_file vschema_customer_vsplit.json customer -./lvtctl.sh InitShardMaster -force customer/0 zone1-200 -./lvtctl.sh CopySchemaShard -tables customer,corder commerce/0 customer/0 -./lvtctl.sh ApplyVSchema -vschema_file vschema_commerce_vsplit.json commerce -./lvtctl.sh ApplyVSchema -vschema_file vschema_customer_vsplit.json customer - -disown -a diff --git a/examples/local/203_vertical_split.sh b/examples/local/203_vertical_split.sh index 99c927dd464..372c4817a90 100755 --- a/examples/local/203_vertical_split.sh +++ b/examples/local/203_vertical_split.sh @@ -17,17 +17,9 @@ # this script copies over all the data from commerce keyspace to # customer keyspace for the customer and corder tables -set -e +source ./env.sh -# shellcheck disable=SC2128 -script_root=$(dirname "${BASH_SOURCE}") - -# shellcheck source=./env.sh -# shellcheck disable=SC1091 -source "$script_root/env.sh" - -# shellcheck disable=SC2086 -"$VTROOT"/bin/vtworker \ +vtworker \ $TOPOLOGY_FLAGS \ -cell zone1 \ -log_dir "$VTDATAROOT"/tmp \ @@ -35,4 +27,3 @@ source "$script_root/env.sh" -use_v3_resharding_mode \ VerticalSplitClone -min_healthy_tablets=1 -tables=customer,corder customer/0 -disown -a diff --git a/examples/local/204_vertical_migrate_replicas.sh b/examples/local/204_vertical_migrate_replicas.sh index 1e13f62a4b3..45ada0aaf63 100755 --- a/examples/local/204_vertical_migrate_replicas.sh +++ b/examples/local/204_vertical_migrate_replicas.sh @@ -17,9 +17,6 @@ # this script migrates traffic for the new customer keyspace to the new # tablets of types rdonly and replica -set -e +vtctlclient -server localhost:15999 MigrateServedFrom customer/0 rdonly +vtctlclient -server localhost:15999 MigrateServedFrom customer/0 replica -./lvtctl.sh MigrateServedFrom customer/0 rdonly -./lvtctl.sh MigrateServedFrom customer/0 replica - -disown -a diff --git a/examples/local/205_vertical_migrate_master.sh b/examples/local/205_vertical_migrate_master.sh index 3aebc52a05c..211d27eb6a7 100755 --- a/examples/local/205_vertical_migrate_master.sh +++ b/examples/local/205_vertical_migrate_master.sh @@ -17,8 +17,4 @@ # this script migrates master traffic for the customer keyspace to the # new master tablet -set -e - -./lvtctl.sh MigrateServedFrom customer/0 master - -disown -a +vtctlclient -server localhost:15999 MigrateServedFrom customer/0 master diff --git a/examples/local/206_clean_commerce.sh b/examples/local/206_clean_commerce.sh index 6139558c385..7111a4a91fc 100755 --- a/examples/local/206_clean_commerce.sh +++ b/examples/local/206_clean_commerce.sh @@ -17,11 +17,7 @@ # this script removes the customer and corder tables from the commerce # keyspace -set -e - -./lvtctl.sh ApplySchema -sql-file drop_commerce_tables.sql commerce -./lvtctl.sh SetShardTabletControl -blacklisted_tables=customer,corder -remove commerce/0 rdonly -./lvtctl.sh SetShardTabletControl -blacklisted_tables=customer,corder -remove commerce/0 replica -./lvtctl.sh SetShardTabletControl -blacklisted_tables=customer,corder -remove commerce/0 master - -disown -a +vtctlclient -server localhost:15999 ApplySchema -sql-file drop_commerce_tables.sql commerce +vtctlclient -server localhost:15999 SetShardTabletControl -blacklisted_tables=customer,corder -remove commerce/0 rdonly +vtctlclient -server localhost:15999 SetShardTabletControl -blacklisted_tables=customer,corder -remove commerce/0 replica +vtctlclient -server localhost:15999 SetShardTabletControl -blacklisted_tables=customer,corder -remove commerce/0 master diff --git a/examples/local/301_customer_sharded.sh b/examples/local/301_customer_sharded.sh index 4d7bacf01d4..5335a0e7392 100755 --- a/examples/local/301_customer_sharded.sh +++ b/examples/local/301_customer_sharded.sh @@ -20,11 +20,7 @@ # it also changes the customer vschema from unsharded to sharded and # sets up the necessary vindexes -set -e - -./lvtctl.sh ApplySchema -sql-file create_commerce_seq.sql commerce -./lvtctl.sh ApplyVSchema -vschema_file vschema_commerce_seq.json commerce -./lvtctl.sh ApplySchema -sql-file create_customer_sharded.sql customer -./lvtctl.sh ApplyVSchema -vschema_file vschema_customer_sharded.json customer - -disown -a +vtctlclient -server localhost:15999 ApplySchema -sql-file create_commerce_seq.sql commerce +vtctlclient -server localhost:15999 ApplyVSchema -vschema_file vschema_commerce_seq.json commerce +vtctlclient -server localhost:15999 ApplySchema -sql-file create_customer_sharded.sql customer +vtctlclient -server localhost:15999 ApplyVSchema -vschema_file vschema_customer_sharded.json customer diff --git a/examples/local/302_new_shards.sh b/examples/local/302_new_shards.sh index 8475a83f1b2..c8830f97d0e 100755 --- a/examples/local/302_new_shards.sh +++ b/examples/local/302_new_shards.sh @@ -17,17 +17,19 @@ # this script brings up new tablets for the two new shards that we will # be creating in the customer keyspace and copies the schema -set -e +source ./env.sh -# shellcheck disable=SC2128 -script_root=$(dirname "${BASH_SOURCE}") +for i in 300 301 302; do + CELL=zone1 TABLET_UID=$i ./scripts/mysqlctl-up.sh + SHARD=-80 CELL=zone1 KEYSPACE=customer TABLET_UID=$i ./scripts/vttablet-up.sh +done -SHARD=-80 CELL=zone1 KEYSPACE=customer UID_BASE=300 "$script_root/vttablet-up.sh" -SHARD=80- CELL=zone1 KEYSPACE=customer UID_BASE=400 "$script_root/vttablet-up.sh" +for i in 400 401 402; do + CELL=zone1 TABLET_UID=$i ./scripts/mysqlctl-up.sh + SHARD=80- CELL=zone1 KEYSPACE=customer TABLET_UID=$i ./scripts/vttablet-up.sh +done -./lvtctl.sh InitShardMaster -force customer/-80 zone1-300 -./lvtctl.sh InitShardMaster -force customer/80- zone1-400 -./lvtctl.sh CopySchemaShard customer/0 customer/-80 -./lvtctl.sh CopySchemaShard customer/0 customer/80- - -disown -a +vtctlclient -server localhost:15999 InitShardMaster -force customer/-80 zone1-300 +vtctlclient -server localhost:15999 InitShardMaster -force customer/80- zone1-400 +vtctlclient -server localhost:15999 CopySchemaShard customer/0 customer/-80 +vtctlclient -server localhost:15999 CopySchemaShard customer/0 customer/80- diff --git a/examples/local/303_horizontal_split.sh b/examples/local/303_horizontal_split.sh index d53be175c98..aaa019559d4 100755 --- a/examples/local/303_horizontal_split.sh +++ b/examples/local/303_horizontal_split.sh @@ -17,22 +17,12 @@ # this script copies the data from customer/0 to customer/-80 and customer/80- # each row will be copied to exactly one shard based on the vindex value -set -e +source ./env.sh -# shellcheck disable=SC2128 -script_root=$(dirname "${BASH_SOURCE}") - -# shellcheck source=./env.sh -# shellcheck disable=SC1091 -source "${script_root}/env.sh" - -# shellcheck disable=SC2086 -"$VTROOT"/bin/vtworker \ - $TOPOLOGY_FLAGS \ - -cell zone1 \ - -log_dir "$VTDATAROOT"/tmp \ - -alsologtostderr \ - -use_v3_resharding_mode \ - SplitClone -min_healthy_rdonly_tablets=1 customer/0 - -disown -a +vtworker \ + $TOPOLOGY_FLAGS \ + -cell zone1 \ + -log_dir "$VTDATAROOT"/tmp \ + -alsologtostderr \ + -use_v3_resharding_mode \ + SplitClone -min_healthy_rdonly_tablets=1 customer/0 diff --git a/examples/local/304_migrate_replicas.sh b/examples/local/304_migrate_replicas.sh index 917d650fdb4..3aed031ebab 100755 --- a/examples/local/304_migrate_replicas.sh +++ b/examples/local/304_migrate_replicas.sh @@ -16,9 +16,5 @@ # this script migrates traffic for the rdonly and replica tablets -set -e - -./lvtctl.sh MigrateServedTypes customer/0 rdonly -./lvtctl.sh MigrateServedTypes customer/0 replica - -disown -a +vtctlclient -server localhost:15999 MigrateServedTypes customer/0 rdonly +vtctlclient -server localhost:15999 MigrateServedTypes customer/0 replica diff --git a/examples/local/305_migrate_master.sh b/examples/local/305_migrate_master.sh index e5ebed81e77..a9da079ea7c 100755 --- a/examples/local/305_migrate_master.sh +++ b/examples/local/305_migrate_master.sh @@ -16,9 +16,6 @@ # this script migrates traffic for the master tablet -set -e - -./lvtctl.sh MigrateServedTypes customer/0 master +vtctlclient -server localhost:15999 MigrateServedTypes customer/0 master # data has been copied over to shards, and databases for the new shards are now available -disown -a diff --git a/examples/local/306_down_shard_0.sh b/examples/local/306_down_shard_0.sh index 79bdd6f3318..25c23ab2111 100755 --- a/examples/local/306_down_shard_0.sh +++ b/examples/local/306_down_shard_0.sh @@ -15,11 +15,8 @@ # limitations under the License. # this script brings down the tablets for customer/0 keyspace -set -e +for i in 200 201 202; do + CELL=zone1 TABLET_UID=$i ./scripts/vttablet-down.sh + CELL=zone1 TABLET_UID=$i ./scripts/mysqlctl-down.sh +done -# shellcheck disable=SC2128 -script_root=$(dirname "${BASH_SOURCE}") - -CELL=zone1 UID_BASE=200 "$script_root/vttablet-down.sh" - -disown -a diff --git a/examples/local/307_delete_shard_0.sh b/examples/local/307_delete_shard_0.sh index 6076b0fabbe..662bb7cdfe9 100755 --- a/examples/local/307_delete_shard_0.sh +++ b/examples/local/307_delete_shard_0.sh @@ -16,8 +16,4 @@ # this script deletes the old shard 0 which has been replaced by 2 shards -set -e - -./lvtctl.sh DeleteShard -recursive customer/0 - -disown -a +vtctlclient -server localhost:15999 DeleteShard -recursive customer/0 diff --git a/examples/local/401_teardown.sh b/examples/local/401_teardown.sh index b0168ae133d..d044b568afd 100755 --- a/examples/local/401_teardown.sh +++ b/examples/local/401_teardown.sh @@ -17,23 +17,27 @@ # We should not assume that any of the steps have been executed. # This makes it possible for a user to cleanup at any point. -set -e - -# shellcheck disable=SC2128 -script_root=$(dirname "${BASH_SOURCE}") - -./vtgate-down.sh - -for TABLET in 100 200 300 400; do - ./lvtctl.sh GetTablet zone1-$TABLET >/dev/null 2>&1 && CELL=zone1 UID_BASE=$TABLET "$script_root/vttablet-down.sh" -done; +source ./env.sh + +./scripts/vtgate-down.sh + +for tablet in 100 200 300 400; do + if vtctlclient -server localhost:15999 GetTablet zone1-$tablet >/dev/null 2>&1 ; then + # The zero tablet is up. Try to shutdown 0-2 tablet + mysqlctl + for i in 0 1 2; do + uid=$[$tablet + $i] + CELL=zone1 TABLET_UID=$uid ./scripts/vttablet-down.sh + CELL=zone1 TABLET_UID=$uid ./scripts/mysqlctl-down.sh + done + fi +done -./vtctld-down.sh +./scripts/vtctld-down.sh if [ "${TOPO}" = "zk2" ]; then - CELL=zone1 "$script_root/zk-down.sh" + CELL=zone1 ./scripts/zk-down.sh else - CELL=zone1 "$script_root/etcd-down.sh" + CELL=zone1 ./scripts/etcd-down.sh fi # pedantic check: grep for any remaining processes diff --git a/examples/local/client.py b/examples/local/client.py deleted file mode 100644 index 1204ce309de..00000000000 --- a/examples/local/client.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2019 The Vitess Authors. -# -# 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. - - -"""Sample Vitess client in Python. - -This is a sample for using the Python Vitess client. -It's a script that inserts some random messages on random pages of the -guestbook sample app. - -Before running this, start up a local example cluster. - -Then run client.sh, which sets up PYTHONPATH before running client.py: -vitess/examples/local$ ./client.sh -""" - -import argparse -import random -import time - -from vtdb import vtgate_client - -# register the python gRPC client upon import -from vtdb import grpc_vtgate_client # pylint: disable=unused-import - -# Parse args -parser = argparse.ArgumentParser() -parser.add_argument('--server', dest='server', default='localhost:15991') -parser.add_argument('--timeout', dest='timeout', type=float, default='10.0') -args = parser.parse_args() - -# Connect -conn = vtgate_client.connect('grpc', args.server, args.timeout) - -try: - # Insert some messages on random pages. - print 'Inserting into master...' - cursor = conn.cursor(tablet_type='master', writable=True) - for i in range(3): - page = random.randint(1, 100) - - cursor.begin() - cursor.execute( - 'INSERT INTO messages (page, time_created_ns, message)' - ' VALUES (:page, :time_created_ns, :message)', - { - 'page': page, - 'time_created_ns': int(time.time() * 1e9), - 'message': 'V is for speed', - }) - cursor.commit() - - # Read it back from the master. - print 'Reading from master...' - cursor.execute('SELECT page, time_created_ns, message FROM messages', {}) - for row in cursor.fetchall(): - print row - - cursor.close() - - # Read from a replica. - # Note that this may be behind master due to replication lag. - print 'Reading from replica...' - cursor = conn.cursor(tablet_type='replica') - cursor.execute('SELECT page, time_created_ns, message FROM messages', {}) - for row in cursor.fetchall(): - print row - cursor.close() - -finally: - # Clean up - conn.close() diff --git a/examples/local/client.sh b/examples/local/client.sh deleted file mode 100755 index 8e1064bb770..00000000000 --- a/examples/local/client.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is a wrapper script that sets up the environment for client.py. - -set -e - -hostname=`hostname -f` - -# We expect to find zk-client-conf.json in the same folder as this script. -script_root=`dirname "${BASH_SOURCE}"` - -# Set up environment. -for pkg in `find $VTROOT/dist -name site-packages`; do - export PYTHONPATH=$pkg:$PYTHONPATH -done - -export PYTHONPATH=$VTROOT/py-vtdb:$PYTHONPATH - -exec env python $script_root/client.py $* diff --git a/examples/local/env.sh b/examples/local/env.sh index 9232c60b4ff..987dcc2f379 100644 --- a/examples/local/env.sh +++ b/examples/local/env.sh @@ -14,31 +14,32 @@ # See the License for the specific language governing permissions and # limitations under the License. +set -e + hostname=`hostname -f` vtctld_web_port=15000 +export VTDATAROOT="${VTDATAROOT:-${PWD}/vtdataroot}" -# Set up environment. -export VTTOP=${VTTOP-$VTROOT/src/vitess.io/vitess} +function fail() { + echo "ERROR: $1" + exit 1 +} -# Try to find mysqld on PATH. -if [ -z "$VT_MYSQL_ROOT" ]; then - mysql_path=`which mysqld` - if [ -z "$mysql_path" ]; then - echo "Can't guess location of mysqld. Please set VT_MYSQL_ROOT manually." - exit 1 - fi - export VT_MYSQL_ROOT=$(dirname `dirname $mysql_path`) +if [[ $EUID -eq 0 ]]; then + fail "This script refuses to be run as root. Please switch to a regular user." fi -# Previously the file specified MYSQL_FLAVOR -# it is now autodetected +# mysqld might be in /usr/sbin which will not be in the default PATH +PATH="/usr/sbin:$PATH" +for binary in mysqld etcd etcdctl curl vtctlclient vttablet vtgate vtctld mysqlctl; do + command -v "$binary" > /dev/null || fail "${binary} is not installed in PATH. See https://vitess.io/docs/get-started/local/ for install instructions." +done; if [ "${TOPO}" = "zk2" ]; then # Each ZooKeeper server needs a list of all servers in the quorum. # Since we're running them all locally, we need to give them unique ports. # In a real deployment, these should be on different machines, and their # respective hostnames should be given. - echo "enter zk2 env" zkcfg=(\ "1@$hostname:28881:38881:21811" \ "2@$hostname:28882:38882:21812" \ @@ -56,8 +57,6 @@ if [ "${TOPO}" = "zk2" ]; then mkdir -p $VTDATAROOT/tmp else - echo "enter etcd2 env" - ETCD_SERVER="localhost:2379" TOPOLOGY_FLAGS="-topo_implementation etcd2 -topo_global_server_address $ETCD_SERVER -topo_global_root /vitess/global" diff --git a/examples/local/lvtctl.sh b/examples/local/lvtctl.sh deleted file mode 100755 index 0197fb79b33..00000000000 --- a/examples/local/lvtctl.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is a convenience script to run vtctlclient against the local example. - -exec vtctlclient -server localhost:15999 "$@" diff --git a/examples/local/vtworker-down.sh b/examples/local/scripts/etcd-down.sh similarity index 79% rename from examples/local/vtworker-down.sh rename to examples/local/scripts/etcd-down.sh index 0ec047a5638..018af7432a3 100755 --- a/examples/local/vtworker-down.sh +++ b/examples/local/scripts/etcd-down.sh @@ -14,12 +14,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -set -e +# This is an example script that stops the etcd servers started by etcd-up.sh. -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -pid=`cat $VTDATAROOT/tmp/vtworker.pid` -echo "Stopping vtworker..." -kill $pid +source ./env.sh +echo "Stopping etcd..." +kill -9 `cat $VTDATAROOT/tmp/etcd.pid` diff --git a/examples/local/etcd-up.sh b/examples/local/scripts/etcd-up.sh similarity index 77% rename from examples/local/etcd-up.sh rename to examples/local/scripts/etcd-up.sh index 51a1ef10cd2..d8c0a869a7e 100755 --- a/examples/local/etcd-up.sh +++ b/examples/local/scripts/etcd-up.sh @@ -16,17 +16,15 @@ # This is an example script that creates a quorum of ZooKeeper servers. -set -e -cell=${CELL:-'test'} +source ./env.sh -script_root=$(dirname "${BASH_SOURCE[0]}") +cell=${CELL:-'test'} export ETCDCTL_API=2 -# shellcheck source=./env.sh -# shellcheck disable=SC1091 -source "${script_root}/env.sh" +# Check that etcd is not already running +curl "http://${ETCD_SERVER}" > /dev/null 2>&1 && fail "etcd is already running. Exiting." -etcd --data-dir "${VTDATAROOT}/etcd/" --listen-client-urls "http://${ETCD_SERVER}" --advertise-client-urls "http://${ETCD_SERVER}" > "${VTDATAROOT}"/tmp/etcd.out 2>&1 & +etcd --enable-v2=true --data-dir "${VTDATAROOT}/etcd/" --listen-client-urls "http://${ETCD_SERVER}" --advertise-client-urls "http://${ETCD_SERVER}" > "${VTDATAROOT}"/tmp/etcd.out 2>&1 & PID=$! echo $PID > "${VTDATAROOT}/tmp/etcd.pid" sleep 5 @@ -34,7 +32,6 @@ sleep 5 echo "add /vitess/global" etcdctl --endpoints "http://${ETCD_SERVER}" mkdir /vitess/global & - echo "add /vitess/$cell" etcdctl --endpoints "http://${ETCD_SERVER}" mkdir /vitess/$cell & @@ -43,7 +40,7 @@ etcdctl --endpoints "http://${ETCD_SERVER}" mkdir /vitess/$cell & echo "add $cell CellInfo" set +e # shellcheck disable=SC2086 -"${VTROOT}"/bin/vtctl $TOPOLOGY_FLAGS AddCellInfo \ +vtctl $TOPOLOGY_FLAGS AddCellInfo \ -root /vitess/$cell \ -server_address "${ETCD_SERVER}" \ $cell @@ -52,4 +49,3 @@ set -e echo "etcd start done..." - diff --git a/examples/kubernetes/sharded-vttablet-down.sh b/examples/local/scripts/mysqlctl-down.sh similarity index 78% rename from examples/kubernetes/sharded-vttablet-down.sh rename to examples/local/scripts/mysqlctl-down.sh index 9c921dfcb85..9e5491d1d4c 100755 --- a/examples/kubernetes/sharded-vttablet-down.sh +++ b/examples/local/scripts/mysqlctl-down.sh @@ -14,10 +14,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -# This is an example script that tears down the vttablet deployment -# created by sharded-vttablet-up.sh. +# This is an example script that stops the mysqld and vttablet instances +# created by vttablet-up.sh -SHARDS='-80,80-' -UID_BASE=200 +source ./env.sh + +mysqlctl -tablet_uid $TABLET_UID shutdown -source ./vttablet-down.sh diff --git a/examples/local/vtworker-up.sh b/examples/local/scripts/mysqlctl-up.sh similarity index 53% rename from examples/local/vtworker-up.sh rename to examples/local/scripts/mysqlctl-up.sh index 520ee89de78..e4c9f58f819 100755 --- a/examples/local/vtworker-up.sh +++ b/examples/local/scripts/mysqlctl-up.sh @@ -14,22 +14,29 @@ # See the License for the specific language governing permissions and # limitations under the License. -# This is an example script that runs vtworker. +# This is an example script that creates a single shard vttablet deployment. -set -e +source ./env.sh cell=${CELL:-'test'} -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -echo "Starting vtworker..." -exec $VTROOT/bin/vtworker \ - $TOPOLOGY_FLAGS \ - -cell $cell \ - -log_dir $VTDATAROOT/tmp \ - -alsologtostderr \ - -service_map=grpc-vtworker \ - -grpc_port 15033 \ - -port 15032 \ - -pid_file $VTDATAROOT/tmp/vtworker.pid \ - -use_v3_resharding_mode & +uid=$TABLET_UID +mysql_port=$[17000 + $uid] +printf -v alias '%s-%010d' $cell $uid +printf -v tablet_dir 'vt_%010d' $uid + +mkdir -p $VTDATAROOT/backups + +echo "Starting MySQL for tablet $alias..." +action="init" + +if [ -d $VTDATAROOT/$tablet_dir ]; then + echo "Resuming from existing vttablet dir:" + echo " $VTDATAROOT/$tablet_dir" + action='start' +fi + +mysqlctl \ + -log_dir $VTDATAROOT/tmp \ + -tablet_uid $uid \ + -mysql_port $mysql_port \ + $action diff --git a/examples/local/lmysql.sh b/examples/local/scripts/vtctld-down.sh similarity index 82% rename from examples/local/lmysql.sh rename to examples/local/scripts/vtctld-down.sh index b043ed69b15..d96fa3b927f 100755 --- a/examples/local/lmysql.sh +++ b/examples/local/scripts/vtctld-down.sh @@ -14,6 +14,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -# This is a convenience script to run mysql client against the local vtgate. +# This is an example script that stops vtctld. -mysql -h 127.0.0.1 -P 15306 -u mysql_user +source ./env.sh + +echo "Stopping vtctld..." +kill -9 `cat $VTDATAROOT/tmp/vtctld.pid` diff --git a/examples/local/vtctld-down.sh b/examples/local/scripts/vtctld-up.sh similarity index 57% rename from examples/local/vtctld-down.sh rename to examples/local/scripts/vtctld-up.sh index 398311ca043..662a234ae48 100755 --- a/examples/local/vtctld-down.sh +++ b/examples/local/scripts/vtctld-up.sh @@ -16,11 +16,23 @@ # This is an example script that starts vtctld. -set -e +source ./env.sh -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh +cell=${CELL:-'test'} +grpc_port=15999 -pid=`cat $VTDATAROOT/tmp/vtctld.pid` -echo "Stopping vtctld..." -kill -9 $pid +echo "Starting vtctld..." +# shellcheck disable=SC2086 +vtctld \ + $TOPOLOGY_FLAGS \ + -cell $cell \ + -workflow_manager_init \ + -workflow_manager_use_election \ + -service_map 'grpc-vtctl' \ + -backup_storage_implementation file \ + -file_backup_storage_root $VTDATAROOT/backups \ + -log_dir $VTDATAROOT/tmp \ + -port $vtctld_web_port \ + -grpc_port $grpc_port \ + -pid_file $VTDATAROOT/tmp/vtctld.pid \ + > $VTDATAROOT/tmp/vtctld.out 2>&1 & diff --git a/examples/local/vtgate-down.sh b/examples/local/scripts/vtgate-down.sh similarity index 85% rename from examples/local/vtgate-down.sh rename to examples/local/scripts/vtgate-down.sh index d396cceab51..9da0a7179df 100755 --- a/examples/local/vtgate-down.sh +++ b/examples/local/scripts/vtgate-down.sh @@ -16,13 +16,8 @@ # This is an example script that stops the instance started by vtgate-up.sh. -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh +source ./env.sh # Stop vtgate. -pid=`cat $VTDATAROOT/tmp/vtgate.pid` echo "Stopping vtgate..." -kill $pid - +kill `cat $VTDATAROOT/tmp/vtgate.pid` diff --git a/examples/local/scripts/vtgate-up.sh b/examples/local/scripts/vtgate-up.sh new file mode 100755 index 00000000000..e3fe2d17f82 --- /dev/null +++ b/examples/local/scripts/vtgate-up.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +# Copyright 2019 The Vitess Authors. +# +# 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 is an example script that starts a single vtgate. + +source ./env.sh + +cell=${CELL:-'test'} +web_port=15001 +grpc_port=15991 +mysql_server_port=15306 +mysql_server_socket_path="/tmp/mysql.sock" + +# Start vtgate. +# shellcheck disable=SC2086 +vtgate \ + $TOPOLOGY_FLAGS \ + -log_dir $VTDATAROOT/tmp \ + -log_queries_to_file $VTDATAROOT/tmp/vtgate_querylog.txt \ + -port $web_port \ + -grpc_port $grpc_port \ + -mysql_server_port $mysql_server_port \ + -mysql_server_socket_path $mysql_server_socket_path \ + -cell $cell \ + -cells_to_watch $cell \ + -tablet_types_to_wait MASTER,REPLICA \ + -gateway_implementation discoverygateway \ + -service_map 'grpc-vtgateservice' \ + -pid_file $VTDATAROOT/tmp/vtgate.pid \ + -mysql_auth_server_impl none \ + > $VTDATAROOT/tmp/vtgate.out 2>&1 & + +# Block waiting for vtgate to be listening +# Not the same as healthy + +echo "Waiting for vtgate to be up..." +while true; do + curl -I "http://$hostname:$web_port/debug/status" >/dev/null 2>&1 && break + sleep 0.1 +done; +echo "vtgate is up!" + +echo "Access vtgate at http://$hostname:$web_port/debug/status" + +disown -a diff --git a/examples/local/etcd-down.sh b/examples/local/scripts/vttablet-down.sh similarity index 67% rename from examples/local/etcd-down.sh rename to examples/local/scripts/vttablet-down.sh index cb2d5b1023f..47b881b9793 100755 --- a/examples/local/etcd-down.sh +++ b/examples/local/scripts/vttablet-down.sh @@ -14,16 +14,17 @@ # See the License for the specific language governing permissions and # limitations under the License. -# This is an example script that stops the etcd servers started by etcd-up.sh. +# This is an example script that stops the mysqld and vttablet instances +# created by vttablet-up.sh -set -e +source ./env.sh -script_root=$(dirname "${BASH_SOURCE[0]}") +printf -v tablet_dir 'vt_%010d' $TABLET_UID +pid=`cat $VTDATAROOT/$tablet_dir/vttablet.pid` + +kill $pid + +# Wait for vttablet to die. +while ps -p $pid > /dev/null; do sleep 1; done -# shellcheck source=./env.sh -# shellcheck disable=SC1091 -source "${script_root}/env.sh" -pid=`cat $VTDATAROOT/tmp/etcd.pid` -echo "Stopping etcd..." -kill -9 $pid diff --git a/examples/local/scripts/vttablet-up.sh b/examples/local/scripts/vttablet-up.sh new file mode 100755 index 00000000000..c3f66fa806d --- /dev/null +++ b/examples/local/scripts/vttablet-up.sh @@ -0,0 +1,69 @@ +#!/bin/bash + +# Copyright 2019 The Vitess Authors. +# +# 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. + +source ./env.sh + +cell=${CELL:-'test'} +keyspace=${KEYSPACE:-'test_keyspace'} +shard=${SHARD:-'0'} +uid=$TABLET_UID +mysql_port=$[17000 + $uid] +port=$[15000 + $uid] +grpc_port=$[16000 + $uid] +printf -v alias '%s-%010d' $cell $uid +printf -v tablet_dir 'vt_%010d' $uid +tablet_hostname='' +printf -v tablet_logfile 'vttablet_%010d_querylog.txt' $uid + +tablet_type=replica +if [[ "${uid: -1}" -gt 1 ]]; then + tablet_type=rdonly +fi + +echo "Starting vttablet for $alias..." +# shellcheck disable=SC2086 +vttablet \ + $TOPOLOGY_FLAGS \ + -log_dir $VTDATAROOT/tmp \ + -log_queries_to_file $VTDATAROOT/tmp/$tablet_logfile \ + -tablet-path $alias \ + -tablet_hostname "$tablet_hostname" \ + -init_keyspace $keyspace \ + -init_shard $shard \ + -init_tablet_type $tablet_type \ + -health_check_interval 5s \ + -enable_semi_sync \ + -enable_replication_reporter \ + -backup_storage_implementation file \ + -file_backup_storage_root $VTDATAROOT/backups \ + -restore_from_backup \ + -port $port \ + -grpc_port $grpc_port \ + -service_map 'grpc-queryservice,grpc-tabletmanager,grpc-updatestream' \ + -pid_file $VTDATAROOT/$tablet_dir/vttablet.pid \ + -vtctld_addr http://$hostname:$vtctld_web_port/ \ + > $VTDATAROOT/$tablet_dir/vttablet.out 2>&1 & + +# Block waiting for the tablet to be listening +# Not the same as healthy + +for i in $(seq 0 300); do + curl -I "http://$hostname:$port/debug/status" >/dev/null 2>&1 && break + sleep 0.1 +done + +# check one last time +curl -I "http://$hostname:$port/debug/status" || fail "tablet could not be started!" diff --git a/examples/local/zk-down.sh b/examples/local/scripts/zk-down.sh similarity index 82% rename from examples/local/zk-down.sh rename to examples/local/scripts/zk-down.sh index aa8e29dba4d..18dd7933bc9 100755 --- a/examples/local/zk-down.sh +++ b/examples/local/scripts/zk-down.sh @@ -16,14 +16,11 @@ # This is an example script that stops the ZooKeeper servers started by zk-up.sh. -set -e - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh +source ./env.sh # Stop ZooKeeper servers. echo "Stopping zk servers..." for zkid in $zkids; do - $VTROOT/bin/zkctl -zk.myid $zkid -zk.cfg $zkcfg -log_dir $VTDATAROOT/tmp shutdown + zkctl -zk.myid $zkid -zk.cfg $zkcfg -log_dir $VTDATAROOT/tmp shutdown done diff --git a/examples/local/zk-up.sh b/examples/local/scripts/zk-up.sh similarity index 89% rename from examples/local/zk-up.sh rename to examples/local/scripts/zk-up.sh index 76c134583c7..6671d1063a6 100755 --- a/examples/local/zk-up.sh +++ b/examples/local/scripts/zk-up.sh @@ -16,13 +16,10 @@ # This is an example script that creates a quorum of ZooKeeper servers. -set -e +source ./env.sh cell=${CELL:-'test'} -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - # Start ZooKeeper servers. # The "zkctl init" command won't return until the server is able to contact its # peers, so we need to start them all in the background and then wait for them. @@ -35,7 +32,7 @@ for zkid in $zkids; do echo " $VTDATAROOT/$zkdir" action='start' fi - $VTROOT/bin/zkctl -zk.myid $zkid -zk.cfg $zkcfg -log_dir $VTDATAROOT/tmp $action \ + zkctl -zk.myid $zkid -zk.cfg $zkcfg -log_dir $VTDATAROOT/tmp $action \ > $VTDATAROOT/tmp/zkctl_$zkid.out 2>&1 & pids[$zkid]=$! done @@ -56,7 +53,7 @@ echo "Started zk servers." # If the node already exists, it's fine, means we used existing data. set +e # shellcheck disable=SC2086 -$VTROOT/bin/vtctl $TOPOLOGY_FLAGS AddCellInfo \ +vtctl $TOPOLOGY_FLAGS AddCellInfo \ -root /vitess/$cell \ -server_address $ZK_SERVER \ $cell diff --git a/examples/local/vtctld-up.sh b/examples/local/vtctld-up.sh deleted file mode 100755 index dbd16a8de66..00000000000 --- a/examples/local/vtctld-up.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is an example script that starts vtctld. - -set -e - -cell=${CELL:-'test'} -grpc_port=15999 - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -optional_auth_args='' -if [ "$1" = "--enable-grpc-static-auth" ]; -then - echo "Enabling Auth with static authentication in grpc" - optional_auth_args='-grpc_auth_static_client_creds ./grpc_static_client_auth.json ' -fi - -echo "Starting vtctld..." -# shellcheck disable=SC2086 -$VTROOT/bin/vtctld \ - $TOPOLOGY_FLAGS \ - -cell $cell \ - -web_dir $VTTOP/web/vtctld \ - -web_dir2 $VTTOP/web/vtctld2/app \ - -workflow_manager_init \ - -workflow_manager_use_election \ - -service_map 'grpc-vtctl' \ - -backup_storage_implementation file \ - -file_backup_storage_root $VTDATAROOT/backups \ - -log_dir $VTDATAROOT/tmp \ - -port $vtctld_web_port \ - -grpc_port $grpc_port \ - -pid_file $VTDATAROOT/tmp/vtctld.pid \ - $optional_auth_args \ - > $VTDATAROOT/tmp/vtctld.out 2>&1 & -disown -a - -echo "Access vtctld web UI at http://$hostname:$vtctld_web_port" -echo "Send commands with: vtctlclient -server $hostname:$grpc_port ..." diff --git a/examples/local/vtgate-up.sh b/examples/local/vtgate-up.sh deleted file mode 100755 index 4cd155018be..00000000000 --- a/examples/local/vtgate-up.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is an example script that starts a single vtgate. - -set -e - -cell=${CELL:-'test'} -web_port=15001 -grpc_port=15991 -mysql_server_port=15306 -mysql_server_socket_path="/tmp/mysql.sock" - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -# When this script is run with the argument "--enable-tls", then it will generate signed certs and -# configure VTGate to accept only TLS connections with client authentication. This allows for end-to-end -# SSL testing (see also the "client_jdbc.sh" script). -optional_tls_args='' -if [ "$1" = "--enable-tls" ]; -then - echo "Enabling TLS with client authentication" - config_dir=../../java/grpc-client/src/test/resources - cert_dir=$VTDATAROOT/tls - rm -Rf $cert_dir - mkdir -p $cert_dir - - # Create CA - openssl genrsa -out $cert_dir/ca-key.pem - openssl req -new -x509 -nodes -days 3600 -batch -config $config_dir/ca.config -key $cert_dir/ca-key.pem -out $cert_dir/ca-cert.pem - - # Create server-side signed cert - openssl req -newkey rsa:2048 -days 3600 -nodes -batch -config $config_dir/cert.config -keyout $cert_dir/server-key.pem -out $cert_dir/server-req.pem - openssl x509 -req -in $cert_dir/server-req.pem -days 3600 -CA $cert_dir/ca-cert.pem -CAkey $cert_dir/ca-key.pem -set_serial 01 -out $cert_dir/server-cert.pem - - # Create client-side signed cert - openssl req -newkey rsa:2048 -days 3600 -nodes -batch -config $config_dir/cert.config -keyout $cert_dir/client-key.pem -out $cert_dir/client-req.pem - openssl x509 -req -in $cert_dir/client-req.pem -days 3600 -CA $cert_dir/ca-cert.pem -CAkey $cert_dir/ca-key.pem -set_serial 02 -out $cert_dir/client-cert.pem - - optional_tls_args="-grpc_cert $cert_dir/server-cert.pem -grpc_key $cert_dir/server-key.pem -grpc_ca $cert_dir/ca-cert.pem" -fi - -optional_auth_args='-mysql_auth_server_impl none' -optional_grpc_auth_args='' -if [ "$1" = "--enable-grpc-static-auth" ]; -then - echo "Enabling Auth with static authentication in grpc" - optional_grpc_auth_args='-grpc_auth_static_client_creds ./grpc_static_client_auth.json' -fi - -if [ "$1" = "--enable-mysql-static-auth" ]; -then - echo "Enabling Auth with mysql static authentication" - optional_auth_args='-mysql_auth_server_static_file ./mysql_auth_server_static_creds.json' -fi - -# Start vtgate. -# shellcheck disable=SC2086 -$VTROOT/bin/vtgate \ - $TOPOLOGY_FLAGS \ - -log_dir $VTDATAROOT/tmp \ - -log_queries_to_file $VTDATAROOT/tmp/vtgate_querylog.txt \ - -port $web_port \ - -grpc_port $grpc_port \ - -mysql_server_port $mysql_server_port \ - -mysql_server_socket_path $mysql_server_socket_path \ - -cell $cell \ - -cells_to_watch $cell \ - -tablet_types_to_wait MASTER,REPLICA \ - -gateway_implementation discoverygateway \ - -service_map 'grpc-vtgateservice' \ - -pid_file $VTDATAROOT/tmp/vtgate.pid \ - $optional_auth_args \ - $optional_grpc_auth_args \ - $optional_tls_args \ - > $VTDATAROOT/tmp/vtgate.out 2>&1 & - -# Block waiting for vtgate to be listening -# Not the same as healthy - -echo "Waiting for vtgate to be up..." -while true; do - curl -I "http://$hostname:$web_port/debug/status" >/dev/null 2>&1 && break - sleep 0.1 -done; -echo "vtgate is up!" - -echo "Access vtgate at http://$hostname:$web_port/debug/status" - -disown -a - diff --git a/examples/local/vttablet-down.sh b/examples/local/vttablet-down.sh deleted file mode 100755 index f73f3f4b087..00000000000 --- a/examples/local/vttablet-down.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is an example script that stops the mysqld and vttablet instances -# created by vttablet-up.sh - -cell=${CELL:-'test'} -uid_base=${UID_BASE:-'100'} - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -# Stop 3 vttablets by default. -# Pass a list of UID indices on the command line to override. -uids=${@:-'0 1 2'} - -wait_pids='' - -for uid_index in $uids; do - uid=$[$uid_base + $uid_index] - printf -v alias '%s-%010d' $cell $uid - printf -v tablet_dir 'vt_%010d' $uid - - echo "Stopping vttablet for $alias..." - pid=`cat $VTDATAROOT/$tablet_dir/vttablet.pid` - kill $pid - wait_pids="$wait_pids $pid" - - echo "Stopping MySQL for tablet $alias..." - $VTROOT/bin/mysqlctl \ - -tablet_uid $uid \ - shutdown & -done - -# Wait for vttablets to die. -while ps -p $wait_pids > /dev/null; do sleep 1; done - -# Wait for 'mysqlctl shutdown' commands to finish. -wait - diff --git a/examples/local/vttablet-up.sh b/examples/local/vttablet-up.sh deleted file mode 100755 index 18e56687373..00000000000 --- a/examples/local/vttablet-up.sh +++ /dev/null @@ -1,145 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The Vitess Authors. -# -# 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 is an example script that creates a single shard vttablet deployment. - -set -e - -cell=${CELL:-'test'} -keyspace=${KEYSPACE:-'test_keyspace'} -shard=${SHARD:-'0'} -uid_base=${UID_BASE:-'100'} -port_base=$[15000 + $uid_base] -grpc_port_base=$[16000 + $uid_base] -mysql_port_base=$[17000 + $uid_base] -tablet_hostname='' - -# Travis hostnames are too long for MySQL, so we use IP. -# Otherwise, blank hostname means the tablet auto-detects FQDN. -if [ "$TRAVIS" == true ]; then - tablet_hostname=`hostname -i` -fi - -script_root=`dirname "${BASH_SOURCE}"` -source $script_root/env.sh - -init_db_sql_file="$VTROOT/config/init_db.sql" - -mkdir -p $VTDATAROOT/backups - -# Start 3 vttablets by default. -# Pass TABLETS_UIDS indices as env variable to change -uids=${TABLETS_UIDS:-'0 1 2'} - -# Start all mysqlds in background. -for uid_index in $uids; do - uid=$[$uid_base + $uid_index] - mysql_port=$[$mysql_port_base + $uid_index] - printf -v alias '%s-%010d' $cell $uid - printf -v tablet_dir 'vt_%010d' $uid - - export KEYSPACE=$keyspace - export SHARD=$shard - export TABLET_ID=$alias - export TABLET_DIR=$tablet_dir - export MYSQL_PORT=$mysql_port - - tablet_type=replica - if [[ $uid_index -gt 1 ]]; then - tablet_type=rdonly - fi - - export TABLET_TYPE=$tablet_type - - echo "Starting MySQL for tablet $alias..." - action="init -init_db_sql_file $init_db_sql_file" - if [ -d $VTDATAROOT/$tablet_dir ]; then - echo "Resuming from existing vttablet dir:" - echo " $VTDATAROOT/$tablet_dir" - action='start' - fi - $VTROOT/bin/mysqlctl \ - -log_dir $VTDATAROOT/tmp \ - -tablet_uid $uid \ - -mysql_port $mysql_port \ - $action & -done - -# Wait for all mysqld to start up. -wait - -optional_auth_args='' -if [ "$1" = "--enable-grpc-static-auth" ]; -then - echo "Enabling Auth with static authentication in grpc" - optional_auth_args='-grpc_auth_mode static -grpc_auth_static_password_file ./grpc_static_auth.json -grpc_auth_static_client_creds ./grpc_static_client_auth.json' -fi - -# Start all vttablets in background. -for uid_index in $uids; do - uid=$[$uid_base + $uid_index] - port=$[$port_base + $uid_index] - grpc_port=$[$grpc_port_base + $uid_index] - printf -v alias '%s-%010d' $cell $uid - printf -v tablet_dir 'vt_%010d' $uid - printf -v tablet_logfile 'vttablet_%010d_querylog.txt' $uid - tablet_type=replica - if [[ $uid_index -gt 1 ]]; then - tablet_type=rdonly - fi - - echo "Starting vttablet for $alias..." - # shellcheck disable=SC2086 - $VTROOT/bin/vttablet \ - $TOPOLOGY_FLAGS \ - -log_dir $VTDATAROOT/tmp \ - -log_queries_to_file $VTDATAROOT/tmp/$tablet_logfile \ - -tablet-path $alias \ - -tablet_hostname "$tablet_hostname" \ - -init_keyspace $keyspace \ - -init_shard $shard \ - -init_tablet_type $tablet_type \ - -health_check_interval 5s \ - -enable_semi_sync \ - -enable_replication_reporter \ - -backup_storage_implementation file \ - -file_backup_storage_root $VTDATAROOT/backups \ - -restore_from_backup \ - -port $port \ - -grpc_port $grpc_port \ - -service_map 'grpc-queryservice,grpc-tabletmanager,grpc-updatestream' \ - -pid_file $VTDATAROOT/$tablet_dir/vttablet.pid \ - -vtctld_addr http://$hostname:$vtctld_web_port/ \ - $optional_auth_args \ - > $VTDATAROOT/$tablet_dir/vttablet.out 2>&1 & - - echo "Access tablet $alias at http://$hostname:$port/debug/status" -done - -# Block waiting for all tablets to be listening -# Not the same as healthy - -echo "Waiting for tablets to be listening..." -for uid_index in $uids; do - port=$[$port_base + $uid_index] - while true; do - curl -I "http://$hostname:$port/debug/status" >/dev/null 2>&1 && break - sleep 0.1 - done; -done; -echo "Tablets up!" - -disown -a diff --git a/go.mod b/go.mod index 6707d58528a..9f2afc72d8e 100644 --- a/go.mod +++ b/go.mod @@ -4,81 +4,91 @@ go 1.12 require ( cloud.google.com/go v0.45.1 + github.com/Azure/azure-storage-blob-go v0.8.0 + github.com/Azure/go-autorest/autorest/adal v0.8.1 // indirect github.com/Bowery/prompt v0.0.0-20190419144237-972d0ceb96f5 // indirect + github.com/GeertJohan/go.rice v1.0.0 github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878 // indirect - github.com/aws/aws-sdk-go v0.0.0-20180223184012-ebef4262e06a - github.com/boltdb/bolt v1.3.1 // indirect + github.com/aws/aws-sdk-go v1.28.8 + github.com/bombsimon/wsl v1.2.8 // indirect github.com/cespare/xxhash/v2 v2.1.1 github.com/cockroachdb/cmux v0.0.0-20170110192607-30d10be49292 // indirect github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd // indirect - github.com/coreos/etcd v0.0.0-20170626015032-703663d1f6ed + github.com/coreos/etcd v3.3.10+incompatible github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect - github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect + github.com/corpix/uarand v0.1.1 // indirect github.com/dchest/safefile v0.0.0-20151022103144-855e8d98f185 // indirect - github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect - github.com/evanphx/json-patch v4.5.0+incompatible // indirect - github.com/ghodss/yaml v0.0.0-20161207003320-04f313413ffd // indirect - github.com/go-ini/ini v1.12.0 // indirect + github.com/evanphx/json-patch v4.5.0+incompatible + github.com/go-critic/go-critic v0.4.0 // indirect + github.com/go-sql-driver/mysql v1.5.0 + github.com/gogo/protobuf v1.3.1 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 // indirect github.com/golang/mock v1.3.1 github.com/golang/protobuf v1.3.2 - github.com/golang/snappy v0.0.0-20170215233205-553a64147049 + github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db + github.com/golangci/gocyclo v0.0.0-20180528144436-0a533e8fa43d // indirect + github.com/golangci/golangci-lint v1.21.0 // indirect + github.com/golangci/revgrep v0.0.0-20180812185044-276a5c0a1039 // indirect + github.com/google/go-cmp v0.4.0 github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf // indirect - github.com/gorilla/websocket v0.0.0-20160912153041-2d1e4548da23 + github.com/gorilla/websocket v1.4.0 + github.com/gostaticanalysis/analysisutil v0.0.3 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 - github.com/grpc-ecosystem/grpc-gateway v0.0.0-20161128002007-199c40a060d1 // indirect - github.com/hashicorp/consul v1.4.0 + github.com/hashicorp/consul v1.5.1 + github.com/hashicorp/consul/api v1.1.0 github.com/hashicorp/go-msgpack v0.5.5 // indirect - github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90 // indirect - github.com/hashicorp/go-uuid v1.0.1 // indirect github.com/hashicorp/golang-lru v0.5.3 // indirect - github.com/hashicorp/memberlist v0.1.4 // indirect - github.com/hashicorp/serf v0.0.0-20161207011743-d3a67ab21bc8 // indirect - github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 // indirect - github.com/jonboulle/clockwork v0.1.0 // indirect - github.com/klauspost/compress v0.0.0-20180801095237-b50017755d44 // indirect - github.com/klauspost/cpuid v1.2.0 // indirect + github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428 github.com/klauspost/crc32 v1.2.0 // indirect github.com/klauspost/pgzip v1.2.0 - github.com/kr/pretty v0.1.0 // indirect - github.com/krishicks/yaml-patch v0.0.10 // indirect + github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect + github.com/krishicks/yaml-patch v0.0.10 + github.com/mattn/go-isatty v0.0.11 // indirect github.com/mattn/go-runewidth v0.0.1 // indirect github.com/minio/minio-go v0.0.0-20190131015406-c8a261de75c1 - github.com/mitchellh/go-testing-interface v1.0.0 // indirect - github.com/mitchellh/mapstructure v1.1.2 // indirect github.com/olekukonko/tablewriter v0.0.0-20160115111002-cca8bbc07984 github.com/opentracing-contrib/go-grpc v0.0.0-20180928155321-4b5a12d3ff02 github.com/opentracing/opentracing-go v1.1.0 - github.com/pborman/uuid v0.0.0-20160824210600-b984ec7fa9ff - github.com/prometheus/client_golang v1.1.0 - github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 // indirect - github.com/prometheus/common v0.7.0 // indirect - github.com/prometheus/procfs v0.0.5 // indirect + github.com/pborman/uuid v1.2.0 + github.com/pelletier/go-toml v1.6.0 // indirect + github.com/philhofer/fwd v1.0.0 // indirect + github.com/pires/go-proxyproto v0.0.0-20191211124218-517ecdf5bb2b + github.com/pkg/errors v0.8.1 + github.com/prometheus/client_golang v1.4.1 + github.com/prometheus/common v0.9.1 github.com/satori/go.uuid v0.0.0-20160713180306-0aa62d5ddceb // indirect + github.com/securego/gosec v0.0.0-20191217083152-cb4f343eaff1 // indirect + github.com/spf13/afero v1.2.2 // indirect + github.com/spf13/cast v1.3.1 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/spf13/viper v1.6.1 // indirect github.com/stretchr/testify v1.4.0 github.com/tchap/go-patricia v0.0.0-20160729071656-dd168db6051b + github.com/tebeka/selenium v0.9.9 + github.com/tinylib/msgp v1.1.1 // indirect github.com/uber-go/atomic v1.4.0 // indirect github.com/uber/jaeger-client-go v2.16.0+incompatible github.com/uber/jaeger-lib v2.0.0+incompatible // indirect github.com/ugorji/go v1.1.7 // indirect - github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect + github.com/uudashr/gocognit v1.0.1 // indirect github.com/z-division/go-zookeeper v0.0.0-20190128072838-6d7457066b9b - golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 + golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 golang.org/x/lint v0.0.0-20190409202823-959b441ac422 golang.org/x/net v0.0.0-20190926025831-c00fd9afed17 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 - golang.org/x/sys v0.0.0-20190926180325-855e68c8590b // indirect golang.org/x/text v0.3.2 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 - golang.org/x/tools v0.0.0-20190830154057-c17b040389b9 + golang.org/x/tools v0.0.0-20191219041853-979b82bfef62 google.golang.org/api v0.9.0 google.golang.org/genproto v0.0.0-20190926190326-7ee9db18f195 // indirect google.golang.org/grpc v1.24.0 - gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175 // indirect - gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect + gopkg.in/DataDog/dd-trace-go.v1 v1.17.0 gopkg.in/ldap.v2 v2.5.0 - honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc + honnef.co/go/tools v0.0.1-2019.2.3 + mvdan.cc/unparam v0.0.0-20191111180625-960b1ec0f2c2 // indirect + sourcegraph.com/sqs/pbtypes v1.0.0 // indirect + vitess.io/vitess/examples/are-you-alive v0.0.0-20200302220708-6b7695375ce9 // indirect ) diff --git a/go.sum b/go.sum index df4e4fb847c..65126378038 100644 --- a/go.sum +++ b/go.sum @@ -1,77 +1,225 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.41.0/go.mod h1:OauMR7DV8fzvZIl2qg6rkaIhD/vmgk4iwEw/h6ercmg= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1 h1:lRi0CHyU+ytlvylOlFKKq0af6JncuyoRh1J+QJBqQx0= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +github.com/Azure/azure-sdk-for-go v16.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-autorest v10.7.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v10.15.3+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/azure-pipeline-go v0.2.1 h1:OLBdZJ3yvOn2MezlWvbrBMTEUQC72zAftRZOMdj5HYo= +github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= +github.com/Azure/azure-storage-blob-go v0.8.0 h1:53qhf0Oxa0nOjgbDeeYPUeyiNmafAFEY95rZLK0Tj6o= +github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0= +github.com/Azure/go-autorest/autorest v0.9.0 h1:MRvx8gncNaXJqOoLmhNjUAKh33JJF8LyxPhomEtOsjs= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.1 h1:pZdL8o72rK+avFWl+p9nE8RWi1JInZrWJYlnpfXJwHk= +github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/Bowery/prompt v0.0.0-20190419144237-972d0ceb96f5 h1:7tNlRGC3pUEPKS3DwgX5L0s+cBloaq/JBoi9ceN1MCM= github.com/Bowery/prompt v0.0.0-20190419144237-972d0ceb96f5/go.mod h1:4/6eNcqZ09BZ9wLK3tZOjBA1nDj+B0728nlX5YRlSmQ= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/BurntSushi/xgbutil v0.0.0-20160919175755-f7c97cef3b4e h1:4ZrkT/RzpnROylmoQL57iVUL57wGKTR5O6KpVnbm2tA= +github.com/BurntSushi/xgbutil v0.0.0-20160919175755-f7c97cef3b4e/go.mod h1:uw9h2sd4WWHOPdJ13MQpwK5qYWKYDumDqxWWIknEQ+k= +github.com/DataDog/datadog-go v0.0.0-20160329135253-cc2f4770f4d6/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/GeertJohan/go.incremental v1.0.0 h1:7AH+pY1XUgQE4Y1HcXYaMqAI0m9yrFqo/jt0CW30vsg= +github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= +github.com/GeertJohan/go.rice v1.0.0 h1:KkI6O9uMaQU3VEKaj01ulavtF7o1fWT7+pk/4voiMLQ= +github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= +github.com/Jeffail/gabs v1.1.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= +github.com/Masterminds/glide v0.13.2/go.mod h1:STyF5vcenH/rUqTEv+/hBXlSTo7KYwg2oc2f4tzPWic= +github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/vcs v1.13.0/go.mod h1:N09YCmOQr6RLxC6UNHzuVwAdodYbbnycGHSmwVJjcKA= +github.com/Microsoft/go-winio v0.4.3/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/NYTimes/gziphandler v1.0.1/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/OpenPeeDeeP/depguard v1.0.1 h1:VlW4R6jmBIv3/u1JNlawEvJMM4J+dPORPaZasQee8Us= +github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM= +github.com/SAP/go-hdb v0.12.0/go.mod h1:etBT+FAi1t5k3K3tf5vQTnosgYmhDkRi8jEnQqCnxF0= +github.com/SermoDigital/jose v0.0.0-20180104203859-803625baeddc/go.mod h1:ARgCUhI1MHQH+ONky/PAtmVHQrP5JlGY0F3poXOp/fA= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af/go.mod h1:5Jv4cbFiHJMsVxt52+i0Ha45fjshj6wxYr1r19tB9bw= +github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw= +github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878 h1:EFSB7Zo9Eg91v7MJPVsifUysc/wPdN+NOnVe6bWbdBM= github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/asaskevich/govalidator v0.0.0-20180319081651-7d2e70ef918f/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/aws/aws-sdk-go v0.0.0-20180223184012-ebef4262e06a h1:Ed33uJE74ksDaYfdY72gK7Cg//o2FgsqlqUfBW079T8= github.com/aws/aws-sdk-go v0.0.0-20180223184012-ebef4262e06a/go.mod h1:ZRmQr0FajVIyZ4ZzBYKG5P3ZqPz9IHG41ZoMu1ADI3k= +github.com/aws/aws-sdk-go v1.15.24/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= +github.com/aws/aws-sdk-go v1.28.8 h1:kPGnElMdW0GDc54Giy1lcE/3gAr2Gzl6cMjYKoBNFhw= +github.com/aws/aws-sdk-go v1.28.8/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= +github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= +github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/bombsimon/wsl v1.2.5 h1:9gTOkIwVtoDZywvX802SDHokeX4kW1cKnV8ZTVAPkRs= +github.com/bombsimon/wsl v1.2.5/go.mod h1:43lEF/i0kpXbLCeDXL9LMT8c92HyBywXb0AsgMHYngM= +github.com/bombsimon/wsl v1.2.8 h1:b+E/W7koicKBZDU+vEsw/hnQTN8026Gv1eMZDLUU/Wc= +github.com/bombsimon/wsl v1.2.8/go.mod h1:43lEF/i0kpXbLCeDXL9LMT8c92HyBywXb0AsgMHYngM= +github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/circonus-labs/circonus-gometrics v0.0.0-20161109192337-d17a8420c36e/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.0.0-20161110002650-365d370cc145/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cockroachdb/cmux v0.0.0-20170110192607-30d10be49292 h1:dzj1/xcivGjNPwwifh/dWTczkwcuqsXXFHY1X/TZMtw= github.com/cockroachdb/cmux v0.0.0-20170110192607-30d10be49292/go.mod h1:qRiX68mZX1lGBkTWyp3CLcenw9I94W2dLeRvMzcn9N4= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/codegangsta/cli v1.20.0/go.mod h1:/qJNoX69yVSKu5o4jLyXAENLRyk1uhi7zkbQ3slBdOA= +github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/coredns/coredns v1.1.2/go.mod h1:zASH/MVDgR6XZTbxvOnsZfffS+31vg6Ackf/wo1+AM0= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v0.0.0-20170626015032-703663d1f6ed h1:uycR38QXnpc8YtCCTsNnQfeq6nPQ55F4ld6/WtGAIlM= github.com/coreos/etcd v0.0.0-20170626015032-703663d1f6ed/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.10+incompatible h1:jFneRYjIvLMLhDLCzuTuU4rSJUjRplcJQ7pD7MnhC04= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/corpix/uarand v0.1.1 h1:RMr1TWc9F4n5jiPDzFHtmaUXLKLNUFK0SgCLo4BhX/U= +github.com/corpix/uarand v0.1.1/go.mod h1:SFKZvkcRoLqVRFZ4u25xPmp6m9ktANfbpXZ7SJ0/FNU= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/daaku/go.zipexe v1.0.0 h1:VSOgZtH418pH9L16hC/JrgSNJbbAL26pj7lmD1+CGdY= +github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dchest/safefile v0.0.0-20151022103144-855e8d98f185 h1:3T8ZyTDp5QxTx3NU48JVb2u+75xc040fofcBaN+6jPA= github.com/dchest/safefile v0.0.0-20151022103144-855e8d98f185/go.mod h1:cFRxtTwTOJkz2x3rQUNCYKWC93yP1VKjR8NUhqFxZNU= +github.com/denisenkom/go-mssqldb v0.0.0-20180620032804-94c9c97e8c9f/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc= +github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/digitalocean/godo v1.1.1/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nbpNqkUIozU= +github.com/digitalocean/godo v1.10.0/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nbpNqkUIozU= +github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/duosecurity/duo_api_golang v0.0.0-20190308151101-6c680f768e74/go.mod h1:UqXY1lYT/ERa4OEAywUqdok1T4RCRdArkhic1Opuavo= +github.com/elazarl/go-bindata-assetfs v0.0.0-20160803192304-e1a2a7ec64b0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= +github.com/envoyproxy/go-control-plane v0.0.0-20180919002855-2137d9196328/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M= github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/structs v0.0.0-20180123065059-ebf56d35bba7/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v0.0.0-20161207003320-04f313413ffd h1:U3yHrYB7NWH2o3UFzJ1J+TknZqM9QQtF8KVIE6Qzrfs= github.com/ghodss/yaml v0.0.0-20161207003320-04f313413ffd/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-critic/go-critic v0.3.5-0.20190904082202-d79a9f0c64db h1:GYXWx7Vr3+zv833u+8IoXbNnQY0AdXsxAgI0kX7xcwA= +github.com/go-critic/go-critic v0.3.5-0.20190904082202-d79a9f0c64db/go.mod h1:+sE8vrLDS2M0pZkBk0wy6+nLdKexVDrl/jBqQOTDThA= +github.com/go-critic/go-critic v0.4.0 h1:sXD3pix0wDemuPuSlrXpJNNYXlUiKiysLrtPVQmxkzI= +github.com/go-critic/go-critic v0.4.0/go.mod h1:7/14rZGnZbY6E38VEGk2kVhoq6itzc1E68facVDK23g= github.com/go-ini/ini v1.12.0 h1:K324HQuOp7fYRWIW84d39Y7MqlH/0JU9fImSXUJ2TWk= github.com/go-ini/ini v1.12.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= +github.com/go-lintpack/lintpack v0.5.2 h1:DI5mA3+eKdWeJ40nU4d6Wc26qmdG8RCi/btYq0TuRN0= +github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-sql-driver/mysql v0.0.0-20180618115901-749ddf1598b4/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g= +github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= +github.com/go-toolsmith/astcopy v1.0.0 h1:OMgl1b1MEpjFQ1m5ztEO06rz5CUd3oBv9RF7+DyvdG8= +github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= +github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/astequal v1.0.0 h1:4zxD8j3JRFNyLN46lodQuqz3xdKSrur7U/sr0SDS/gQ= +github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086/go.mod h1:mP93XdblcopXwlyN4X4uodxXQhldPGZbcEJIimQHrkg= +github.com/go-toolsmith/astfmt v1.0.0 h1:A0vDDXt+vsvLEdbMFJAUBI/uTbRw1ffOPnxsILnFL6k= +github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= +github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU= +github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30/go.mod h1:SV2ur98SGypH1UjcPpCatrV5hPazG6+IfNHbkDXBRrk= +github.com/go-toolsmith/astp v1.0.0 h1:alXE75TXgcmupDsMK1fRAy0YUzLzqPVvBKoyWV+KPXg= +github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI= +github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoMrjiy4zvdS+Bg6z9jZH82QXwkcgCBX6nOfnmdaHks= +github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc= +github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4= +github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= +github.com/go-toolsmith/typep v1.0.0 h1:zKymWyA1TRYvqYrYDrfEMZULyrhcnGY3x7LDKU2XQaA= +github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gocql/gocql v0.0.0-20180617115710-e06f8c1bcd78/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0= +github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b h1:ekuhfTjngPhisSjOJ0QWKpPQE8/rbknHaes6WVJj5Hw= +github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s= @@ -82,168 +230,445 @@ github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20170215233205-553a64147049 h1:K9KHZbXKpGydfDN0aZrsoHpLJlZsBrGMFWbgLDGnPZk= github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= +github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= +github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= +github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= +github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6 h1:YYWNAGTKWhKpcLLt7aSj/odlKrSrelQwlovBpDuf19w= +github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6/go.mod h1:DbHgvLiFKX1Sh2T1w8Q/h4NAI8MHIpzCdnBUDTXU3I0= +github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613 h1:9kfjN3AdxcbsZBf8NjltjWihK2QfBBBZuv91cMFfDHw= +github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8= +github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3 h1:pe9JHs3cHHDQgOFXJJdYkK6fLz2PWyYtP4hthoCMvs8= +github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3/go.mod h1:JXrF4TWy4tXYn62/9x8Wm/K/dm06p8tCKwFRDPZG/1o= +github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee h1:J2XAy40+7yz70uaOiMbNnluTg7gyQhtGqLQncQh+4J8= +github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU= +github.com/golangci/gocyclo v0.0.0-20180528144436-0a533e8fa43d h1:pXTK/gkVNs7Zyy7WKgLXmpQ5bHTrq5GDsp8R9Qs67g0= +github.com/golangci/gocyclo v0.0.0-20180528144436-0a533e8fa43d/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU= +github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a h1:iR3fYXUjHCR97qWS8ch1y9zPNsgXThGwjKPrYfqMPks= +github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU= +github.com/golangci/golangci-lint v1.21.0 h1:HxAxpR8Z0M8omihvQdsD3PF0qPjlqYqp2vMJzstoKeI= +github.com/golangci/golangci-lint v1.21.0/go.mod h1:phxpHK52q7SE+5KpPnti4oZTdFCEsn/tKN+nFvCKXfk= +github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc h1:gLLhTLMk2/SutryVJ6D4VZCU3CUqr8YloG7FPIBWFpI= +github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU= +github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= +github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= +github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= +github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= +github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770 h1:EL/O5HGrF7Jaq0yNhBLucz9hTuRzj2LdwGBOaENgxIk= +github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= +github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21 h1:leSNB7iYzLYSSx3J/s5sVf4Drkc68W2wm4Ixh/mr0us= +github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI= +github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0 h1:HVfrLniijszjS1aiNg8JbBMO2+E1WIQ+j/gL4SQqGPg= +github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4= +github.com/golangci/revgrep v0.0.0-20180812185044-276a5c0a1039 h1:XQKc8IYQOeRwVs36tDrEmTgDgP88d5iEURwpmtiAlOM= +github.com/golangci/revgrep v0.0.0-20180812185044-276a5c0a1039/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4= +github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= +github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-github/v27 v27.0.4/go.mod h1:/0Gr8pJ55COkmv+S/yPKCczSkUPIM/LnFyubufRNIS0= +github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg= github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE= +github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/gophercloud/gophercloud v0.0.0-20180828235145-f29afc2cceca/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4= +github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v0.0.0-20160912153041-2d1e4548da23 h1:NqeYYy/q+eU5bXzLrVTFSEMp5/VFwp3eJ6nkDsi7wos= github.com/gorilla/websocket v0.0.0-20160912153041-2d1e4548da23/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3 h1:JVnpOZS+qxli+rgVl98ILOXVNbW+kb5wcxeGx8ShUIw= +github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= +github.com/gostaticanalysis/analysisutil v0.0.3 h1:iwp+5/UAyzQSFgQ4uR2sni99sJ8Eo9DEacKWM5pekIg= +github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= +github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 h1:THDBEeQ9xZ8JEaCLyLQqXMMdRqNr0QAUJTIkQAUtFjg= github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v0.0.0-20161128002007-199c40a060d1 h1:HpW72214zD3cWQsV9DW4Sd9piuuw8rPmE4/TAjTgYIE= github.com/grpc-ecosystem/grpc-gateway v0.0.0-20161128002007-199c40a060d1/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= github.com/hashicorp/consul v1.4.0 h1:PQTW4xCuAExEiSbhrsFsikzbW5gVBoi74BjUvYFyKHw= github.com/hashicorp/consul v1.4.0/go.mod h1:mFrjN1mfidgJfYP1xrJCF+AfRhr6Eaqhb2+sfyn/OOI= +github.com/hashicorp/consul v1.5.1 h1:p7tRmQ4m3ZMYkGQkuyjLXKbdU1weeumgZFqZOvw7o4c= +github.com/hashicorp/consul v1.5.1/go.mod h1:QsmgXh2YA9Njv6y3/FHXqHYhsMye++3oBoAZ6SR8R8I= +github.com/hashicorp/consul/api v1.1.0 h1:BNQPM9ytxj6jbjjdRPioQ94T6YXriSopn0i8COv6SRA= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-bexpr v0.1.0/go.mod h1:ANbpTX1oAql27TZkKVeW8p1w8NTdnyzPe/0qqPCKohU= +github.com/hashicorp/go-checkpoint v0.0.0-20171009173528-1545e56e46de/go.mod h1:xIwEieBHERyEvaeKF/TcHh1Hu+lxPM+n2vT1+g9I4m4= github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6KdvN3Gig= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-discover v0.0.0-20190403160810-22221edb15cd/go.mod h1:ueUgD9BeIocT7QNuvxSyJyPAM9dfifBcaWmeybb67OY= +github.com/hashicorp/go-hclog v0.0.0-20180402200405-69ff559dc25f/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-memdb v0.0.0-20180223233045-1289e7fffe71/go.mod h1:kbfItVoBJwCfKXDXN4YoAXjxcFVZ7MRrJzyTX6H4giE= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack v0.5.4/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-plugin v0.0.0-20180331002553-e8d22c780116/go.mod h1:JSqWYsict+jzcj0+xElxyrBQRPNoiWQuddnxArJ7XHQ= +github.com/hashicorp/go-retryablehttp v0.0.0-20180531211321-3b087ef2d313/go.mod h1:fXcdFsQoipQa7mwORhKad5jmDCeSy/RCGzWA08PO0lM= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90 h1:VBj0QYQ0u2MCJzBfeYXGexnAl17GsH1yidnoxCqqD9E= github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90/go.mod h1:o4zcYY1e0GEZI6eSEr+43QDYmuGglw1qSO6qdHUHCgg= +github.com/hashicorp/go-rootcerts v1.0.0 h1:Rqb66Oo1X/eSV1x66xbDccZjhJigjg0+e82kpwzSwCI= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v0.0.0-20170202080759-03c5bf6be031/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v0.0.0-20180906183839-65a6292f0157/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/hil v0.0.0-20160711231837-1e86c6b523c5/go.mod h1:KHvg/R2/dPtaePb16oW4qIyzkMxXOL38xjRN64adsts= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/memberlist v0.1.4 h1:gkyML/r71w3FL8gUi74Vk76avkj/9lYAY9lvg0OcoGs= github.com/hashicorp/memberlist v0.1.4/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/net-rpc-msgpackrpc v0.0.0-20151116020338-a14192a58a69/go.mod h1:/z+jUGRBlwVpUZfjute9jWaF6/HuhjuFQuL1YXzVD1Q= +github.com/hashicorp/raft v1.0.1-0.20190409200437-d9fe23f7d472/go.mod h1:DVSAWItjLjTOkVbSpWQ0j0kUADIvDaCtBxIcbNAQLkI= +github.com/hashicorp/raft-boltdb v0.0.0-20150201200839-d1e82c1ec3f1/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk= github.com/hashicorp/serf v0.0.0-20161207011743-d3a67ab21bc8 h1:Vd9tjFEMH3X1AMV1BzVAZRwnjy9MoxOsOl+1pqpCVQs= github.com/hashicorp/serf v0.0.0-20161207011743-d3a67ab21bc8/go.mod h1:h/Ru6tmZazX7WO/GDmwdpS975F019L4t5ng5IgwbNrE= +github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hashicorp/vault v0.10.3/go.mod h1:KfSyffbKxoVyspOdlaGVjIuwLobi07qD1bAbosPMpP0= +github.com/hashicorp/vault-plugin-secrets-kv v0.0.0-20190318174639-195e0e9d07f1/go.mod h1:VJHHT2SC1tAPrfENQeBhLlb5FbZoKZM+oC/ROmEftz0= +github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443/go.mod h1:bEpDU35nTu0ey1EXjwNwPjI9xErAsoOCmcMb9GKvyxo= +github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428 h1:Mo9W14pwbO9VfRe+ygqZ8dFbPpoIK1HFrG/zjTuQ+nc= +github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428/go.mod h1:uhpZMVGznybq1itEKXj6RYw9I71qK4kH+OGMjRC4KEo= +github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4= +github.com/jefferai/jsonx v0.0.0-20160721235117-9cc31c3135ee/go.mod h1:N0t2vlmpe8nyZB5ouIbJQPDSR+mH6oe7xHB9VZHSUzM= +github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jinzhu/gorm v1.9.12 h1:Drgk1clyWT9t9ERbzHza6Mj/8FY/CqMyVzOiHviMo6Q= +github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZT/Qs= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 h1:12VvqtR6Aowv3l/EQUlocDHW2Cp4G9WJVH7uyH8QFJE= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62/go.mod h1:U+RSyWxWd04xTqnuOQxnai7XGS2PrPY2cfGoDKtMHjA= +github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/keybase/go-crypto v0.0.0-20180614160407-5114a9a81e1b/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v0.0.0-20180801095237-b50017755d44 h1:uDhun+KVSncSm1UeN8A4llsQ6E+xAIBmhh816Q2zeOk= github.com/klauspost/compress v0.0.0-20180801095237-b50017755d44/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.4.1 h1:8VMb5+0wMgdBykOV96DwNwKFQ+WTI4pzYURP99CcB9E= +github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/crc32 v1.2.0 h1:0VuyqOCruD33/lJ/ojXNvzVyl8Zr5zdTmj9l9qLZ86I= github.com/klauspost/crc32 v1.2.0/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= github.com/klauspost/pgzip v1.2.0 h1:SPtjjC68wy5g65KwQS4TcYtm6x/O8H4jSxtKZfhN4s0= github.com/klauspost/pgzip v1.2.0/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/krishicks/yaml-patch v0.0.10 h1:H4FcHpnNwVmw8u0MjPRjWyIXtco6zM2F78t+57oNM3E= github.com/krishicks/yaml-patch v0.0.10/go.mod h1:Sm5TchwZS6sm7RJoyg87tzxm2ZcKzdRE4Q7TjNhPrME= +github.com/lib/pq v0.0.0-20180523175426-90697d60dd84/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/lyft/protoc-gen-validate v0.0.0-20180911180927-64fcb82c878e/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb h1:RHba4YImhrUVQDHUCe2BNSOz4tVy2yGyXhvYDvxGgeE= +github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149 h1:HfxbT6/JcvIljmERptWhwa8XzP7H3T+Z2N26gTsaDaA= +github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-runewidth v0.0.1 h1:+EiaBVXhogb1Klb4tRJ7hYnuGK6PkKOZlK04D/GMOqk= github.com/mattn/go-runewidth v0.0.1/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/minio/minio-go v0.0.0-20190131015406-c8a261de75c1 h1:jw16EimP5oAEM/2wt+SiEUov/YDyTCTDuPtIKgQIvk0= github.com/minio/minio-go v0.0.0-20190131015406-c8a261de75c1/go.mod h1:vuvdOZLJuf5HmJAJrKV64MmozrSsk+or0PB5dzdfspg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/copystructure v0.0.0-20160804032330-cdac8253d00f/go.mod h1:eOsF2yLPlBBJPvD+nhl5QMTBSOBbOph6N7j/IDUw7PY= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b h1:9+ke9YJ9KGWw5ANXK6ozjoK47uI3uNbXv4YVINBnGm8= +github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk= github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d h1:AREM5mwr4u1ORQBMvzfzBgpsctsbQikCVpvC+tX285E= +github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= +github.com/ngdinhtoan/glide-cleanup v0.2.0/go.mod h1:UQzsmiDOb8YV3nOsCxK/c9zPpCZVNoHScRE3EO9pVMM= +github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2/go.mod h1:TLb2Sg7HQcgGdloNxkrmtgDNR9uVYF3lfdFIN4Ro6Sk= +github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229 h1:E2B8qYyeSgv5MXpmzZXRNp8IAQ4vjxIjhpAf5hv/tAg= +github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= +github.com/oklog/run v0.0.0-20180308005104-6934b124db28/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20160115111002-cca8bbc07984 h1:c9gVtoY8wPlhJIN2V2I1V+Fn9UcXM8mDG8IHv/1c3r8= github.com/olekukonko/tablewriter v0.0.0-20160115111002-cca8bbc07984/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opentracing-contrib/go-grpc v0.0.0-20180928155321-4b5a12d3ff02 h1:0R5mDLI66Qw13qN80TRz85zthQ2nf2+uDyiV23w6c3Q= github.com/opentracing-contrib/go-grpc v0.0.0-20180928155321-4b5a12d3ff02/go.mod h1:JNdpVEzCpXBgIiv4ds+TzhN1hrtxq6ClLrTlT9OQRSc= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/ory/dockertest v3.3.4+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= +github.com/packethost/packngo v0.1.1-0.20180711074735-b9cb5096f54c/go.mod h1:otzZQXgoO96RTzDB/Hycg0qZcXZsWJGJRSXbmEIJ+4M= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/patrickmn/go-cache v0.0.0-20180527043350-9f6ff22cfff8/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pborman/uuid v0.0.0-20160824210600-b984ec7fa9ff h1:pTiDfW+iOjIxjZeCm88gKn/AmR09UGZYZdqif2yPRrM= github.com/pborman/uuid v0.0.0-20160824210600-b984ec7fa9ff/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= +github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.6.0 h1:aetoXYr0Tv7xRU/V4B4IZJ2QcbtMUFoNb3ORp7TzIK4= +github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ= +github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= +github.com/pires/go-proxyproto v0.0.0-20191211124218-517ecdf5bb2b h1:JPLdtNmpXbWytipbGwYz7zXZzlQNASEiFw5aGAM75us= +github.com/pires/go-proxyproto v0.0.0-20191211124218-517ecdf5bb2b/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.0.0-20180328130430-f504d69affe1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0 h1:BQ53HtBmfOitExawJ6LokA4x8ov/z0SYYb0+HxJfRI8= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= +github.com/prometheus/client_golang v1.4.1 h1:FFSuS004yOQEtDdTq+TAOLP5xUq63KqAFYyOi8zA+Y8= +github.com/prometheus/client_golang v1.4.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20180326160409-38c53a9f4bfc/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 h1:PnBWHBf+6L0jOqq0gIVUe6Yk0/QMZ640k6NvkxcBf+8= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/procfs v0.0.0-20180408092902-8b1c2da0d56d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nLJdBg+pBmGgkJlSaKC2KaQmTCk1XDtE= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8= github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI= +github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03/go.mod h1:gRAiPF5C5Nd0eyyRdqIu9qTiFSoZzpTq727b5B8fkkU= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/satori/go.uuid v0.0.0-20160713180306-0aa62d5ddceb h1:1r/p6yT1FfHR1+qBm7UYBPgfqCmzz/8mpNvfc+iKlfU= github.com/satori/go.uuid v0.0.0-20160713180306-0aa62d5ddceb/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/securego/gosec v0.0.0-20191002120514-e680875ea14d h1:BzRvVq1EHuIjxpijCEKpAxzKUUMurOQ4sknehIATRh8= +github.com/securego/gosec v0.0.0-20191002120514-e680875ea14d/go.mod h1:w5+eXa0mYznDkHaMCXA4XYffjlH+cy1oyKbfzJXa2Do= +github.com/securego/gosec v0.0.0-20191217083152-cb4f343eaff1 h1:p7IOnYri8VyitvXJfgXw7yt2G/teasqQHQ6f/u1RQvc= +github.com/securego/gosec v0.0.0-20191217083152-cb4f343eaff1/go.mod h1:sM2KJ/O9PKom+0jAmXpblJ8PWrLbGAk6F2Lzwj4H6wg= +github.com/shirou/gopsutil v0.0.0-20181107111621-48177ef5f880/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc= +github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= +github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= +github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/smartystreets/assertions v0.0.0-20180820201707-7c9eb446e3cf/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 h1:Jpy1PXuP99tXNrhbq2BaPz9B+jNAvH1JPQQpG/9GCXY= github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c h1:Ho+uVpkel/udgjbwB5Lktg9BtvJSh2DT0Hi6LPSyI2w= github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/softlayer/softlayer-go v0.0.0-20180806151055-260589d94c7d/go.mod h1:Cw4GTlQccdRGSEf6KiMju767x0NEHE0YIVPJSaXjlsw= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sourcegraph/go-diff v0.5.1 h1:gO6i5zugwzo1RVTvgvfwCOSVegNuvnNi6bAD1QCmkHs= +github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/spf13/viper v1.6.1 h1:VPZzIkznI1YhVMRi6vNFLHSwhnhReBfgTxIPccpfdZk= +github.com/spf13/viper v1.6.1/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tchap/go-patricia v0.0.0-20160729071656-dd168db6051b h1:i3lm+BZX5fAaH95wJavMgsSYU95LhSxdNCMa8nLv2gk= github.com/tchap/go-patricia v0.0.0-20160729071656-dd168db6051b/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= +github.com/tebeka/selenium v0.9.9 h1:cNziB+etNgyH/7KlNI7RMC1ua5aH1+5wUlFQyzeMh+w= +github.com/tebeka/selenium v0.9.9/go.mod h1:5Fr8+pUvU6B1OiPfkdCKdXZyr5znvVkxuPd0NOdZCQc= +github.com/tent/http-link-go v0.0.0-20130702225549-ac974c61c2f9/go.mod h1:RHkNRtSLfOK7qBTHaeSX1D6BNpI3qw7NTxsmNr4RvN8= +github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e h1:RumXZ56IrCj4CL+g1b9OL/oH0QnsF976bC8xQFYUD5Q= +github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= +github.com/tinylib/msgp v1.1.1 h1:TnCZ3FIuKeaIy+F45+Cnp+caqdXGy4z74HvwXN+570Y= +github.com/tinylib/msgp v1.1.1/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/uber-go/atomic v1.4.0 h1:yOuPqEq4ovnhEjpHmfFwsqBXDYbQeT6Nb0bwD6XnD5o= github.com/uber-go/atomic v1.4.0/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= @@ -251,14 +676,34 @@ github.com/uber/jaeger-client-go v2.16.0+incompatible h1:Q2Pp6v3QYiocMxomCaJuwQG github.com/uber/jaeger-client-go v2.16.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.0.0+incompatible h1:iMSCV0rmXEogjNWPh2D0xk9YVKvrtGoHJNe9ebLu/pw= github.com/uber/jaeger-lib v2.0.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/ultraware/funlen v0.0.2 h1:Av96YVBwwNSe4MLR7iI/BIa3VyI7/djnto/pK3Uxbdo= +github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= +github.com/ultraware/whitespace v0.0.4 h1:If7Va4cM03mpgrNH9k49/VOicWpGoG70XPBFFODYDsg= +github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= +github.com/uudashr/gocognit v0.0.0-20190926065955-1655d0de0517 h1:ChMKTho2hWKpks/nD/FL2KqM1wuVt62oJeiE8+eFpGs= +github.com/uudashr/gocognit v0.0.0-20190926065955-1655d0de0517/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM= +github.com/uudashr/gocognit v1.0.1 h1:MoG2fZ0b/Eo7NXoIwCVFLG5JED3qgQz5/NEE+rOsjPs= +github.com/uudashr/gocognit v1.0.1/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s= +github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8= +github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= +github.com/valyala/quicktemplate v1.2.0/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4= +github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= +github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/z-division/go-zookeeper v0.0.0-20190128072838-6d7457066b9b h1:Itr7GbuXoM1PK/eCeNNia4Qd3ib9IgX9g9SpXgo8BwQ= github.com/z-division/go-zookeeper v0.0.0-20190128072838-6d7457066b9b/go.mod h1:JNALoWa+nCXR8SmgLluHcBNVJgyejzpKPZk9pX2yXXE= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= @@ -268,14 +713,23 @@ go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190128193316-c7b33c32a30b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 h1:Gv7RPwsi3eZ2Fgewe3CBsuOebPwO27PoXzRpJPsvSSM= golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 h1:ULYEB3JvPRE/IfO+9uO7vKV/xzVTO7XPAwm8xbf4w2g= +golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -283,23 +737,32 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190409202823-959b441ac422 h1:QzoH/1pFpZguR8NrRHLcO6jKqfv2zpuSqZLgdm7ZmjI= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190403144856-b630fd6fe46b/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190926025831-c00fd9afed17 h1:qPnAdmjNA41t3QBTx2mFGf/SD1IoslhYu7AmdsVzCcs= golang.org/x/net v0.0.0-20190926025831-c00fd9afed17/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/oauth2 v0.0.0-20170807180024-9a379c6b3e95/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= @@ -310,13 +773,20 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -324,30 +794,64 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190926180325-855e68c8590b h1:/8GN4qrAmRZQXgjWZHj9z/UJI5vNqQhPtgcw02z2f+8= golang.org/x/sys v0.0.0-20190926180325-855e68c8590b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191218084908-4a24b4065292 h1:Y8q0zsdcgAd+JU8VUA8p8Qv2YhuY9zevDG2ORt5qBUI= +golang.org/x/sys v0.0.0-20191218084908-4a24b4065292/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82 h1:ywK/j/KkyTHcdyYSZNXGjMwgmDSfjglYZ3vStQ/gSCU= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190624190245-7f2218787638/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190719005602-e377ae9d6386/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190830154057-c17b040389b9 h1:5/jaG/gKlo3xxvUn85ReNyTlN7BvlPPsxC6sHZKjGEE= golang.org/x/tools v0.0.0-20190830154057-c17b040389b9/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911151314-feee8acb394c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190930201159-7c411dea38b0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191010075000-0337d82405ff h1:XdBG6es/oFDr1HwaxkxgVve7NB281QhxgK/i4voubFs= +golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191209225234-22774f7dae43 h1:NfPq5mgc5ArFgVLCpeS4z07IoxSAqVfV/gQ5vxdgaxI= +golang.org/x/tools v0.0.0-20191209225234-22774f7dae43/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191217033636-bbbf87ae2631/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191219041853-979b82bfef62 h1:vDaiisQl0rGVXqk3wT2yc43gSnwlj4haEG5J78IGZP4= +golang.org/x/tools v0.0.0-20191219041853-979b82bfef62/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.0.0-20180829000535-087779f1d2c9/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0 h1:9sdfJOzWlkqPltHAuzT2Cp+yrBeY1KRVYgms8soxMwM= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= @@ -364,35 +868,85 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190626174449-989357319d63/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64 h1:iKtrH9Y8mcbADOP0YFaEMth7OfuHY9xHOwNj4znpM1A= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190926190326-7ee9db18f195 h1:dWzgMaXfaHsnkRKZ1l3iJLDmTEB40JMl/dqRbJX4D/o= google.golang.org/genproto v0.0.0-20190926190326-7ee9db18f195/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/grpc v0.0.0-20180920234847-8997b5fa0873/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1 h1:j6XxA85m/6txkUCHvzlV5f+HBNl/1r5cZ2A/3IEFOO8= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s= google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +gopkg.in/DataDog/dd-trace-go.v1 v1.17.0 h1:j9vAp9Re9bbtA/QFehkJpNba/6W2IbJtNuXZophCa54= +gopkg.in/DataDog/dd-trace-go.v1 v1.17.0/go.mod h1:DVp8HmDh8PuTu2Z0fVVlBsyWaC++fzwVCaGWylTe3tg= +gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= +gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175 h1:nn6Zav2sOQHCFJHEspya8KqxhFwKci30UxHy3HXPTyQ= gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= +gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM= +gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.41.0 h1:Ka3ViY6gNYSKiVy71zXBEqKplnV35ImDLVG+8uoIklE= gopkg.in/ini.v1 v1.41.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ldap.v2 v2.5.0 h1:1rO3ojzsHUk+gq4ZYhC4Pg+EzWaaKIV8+DJwExS5/QQ= gopkg.in/ldap.v2 v2.5.0/go.mod h1:oI0cpe/D7HRtBQl8aTg+ZmzFUAvu4lsv3eLXMLGFxWk= +gopkg.in/mgo.v2 v2.0.0-20160818020120-3f83fa500528/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/ory-am/dockertest.v3 v3.3.4/go.mod h1:s9mmoLkaGeAh97qygnNj4xWkiN7e1SKekYC6CovU+ek= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= +gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a h1:LJwr7TCTghdatWv40WobzlKXc9c4s8oGa7QKJUtHhWA= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +k8s.io/api v0.0.0-20180806132203-61b11ee65332/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= +k8s.io/api v0.0.0-20190325185214-7544f9db76f6/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= +k8s.io/apimachinery v0.0.0-20180821005732-488889b0007f/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= +k8s.io/apimachinery v0.0.0-20190223001710-c182ff3b9841/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= +k8s.io/client-go v8.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= +mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= +mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= +mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= +mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= +mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f h1:Cq7MalBHYACRd6EesksG1Q8EoIAKOsiZviGKbOLIej4= +mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw= +mvdan.cc/unparam v0.0.0-20191111180625-960b1ec0f2c2 h1:K7wru2CfJGumS5hkiguQ0Rb9ebKM2Jo8s5d4Jm9lFaM= +mvdan.cc/unparam v0.0.0-20191111180625-960b1ec0f2c2/go.mod h1:rCqoQrfAmpTX/h2APczwM7UymU/uvaOluiVPIYCSY/k= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4 h1:JPJh2pk3+X4lXAkZIk2RuE/7/FoK9maXw+TNPJhVS/c= +sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= +sourcegraph.com/sqs/pbtypes v1.0.0 h1:f7lAwqviDEGvON4kRv0o5V7FT/IQK+tbkF664XMbP3o= +sourcegraph.com/sqs/pbtypes v1.0.0/go.mod h1:3AciMUv4qUuRHRHhOG4TZOB+72GdPVz5k+c648qsFS4= +vitess.io/vitess/examples/are-you-alive v0.0.0-20200302220708-6b7695375ce9 h1:tB4oHYzfEkqCFNUO7yUFWg9xcYw9ULT5U9/tBVbjaD0= +vitess.io/vitess/examples/are-you-alive v0.0.0-20200302220708-6b7695375ce9/go.mod h1:3Lnc7tMP/PtC7X4Yxu2tcqYbXAX4aGLDKEDsaQwPDp4= diff --git a/go/cmd/mysqlctl/mysqlctl.go b/go/cmd/mysqlctl/mysqlctl.go index 4e8b0634d29..8793d8420a6 100644 --- a/go/cmd/mysqlctl/mysqlctl.go +++ b/go/cmd/mysqlctl/mysqlctl.go @@ -25,6 +25,7 @@ import ( "golang.org/x/net/context" + "vitess.io/vitess/go/cmd" "vitess.io/vitess/go/exit" "vitess.io/vitess/go/flagutil" "vitess.io/vitess/go/mysql" @@ -235,6 +236,10 @@ func main() { fmt.Fprintf(os.Stderr, "\n") } + if cmd.IsRunningAsRoot() { + fmt.Fprintln(os.Stderr, "mysqlctl cannot be ran as root. Please run as a different user") + exit.Return(1) + } dbconfigs.RegisterFlags(dbconfigs.Dba) flag.Parse() diff --git a/go/cmd/tools.go b/go/cmd/tools.go index 9722dbc267c..75234b4890d 100644 --- a/go/cmd/tools.go +++ b/go/cmd/tools.go @@ -20,6 +20,7 @@ import ( "os" "os/exec" "strings" + "syscall" ) // DetachFromTerminalAndExit allows a command line program to detach from the terminal and continue running @@ -41,3 +42,8 @@ func DetachFromTerminalAndExit() { fmt.Println("[PID]", cmd.Process.Pid) os.Exit(0) } + +// IsRunningAsRoot checks if a component is being ran as root +func IsRunningAsRoot() bool { + return syscall.Geteuid() == 0 +} diff --git a/go/cmd/vtbackup/plugin_azblobbackupstorage.go b/go/cmd/vtbackup/plugin_azblobbackupstorage.go new file mode 100644 index 00000000000..a4ca64096a9 --- /dev/null +++ b/go/cmd/vtbackup/plugin_azblobbackupstorage.go @@ -0,0 +1,21 @@ +/* +Copyright 2020 The Vitess Authors. + +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. +*/ + +package main + +import ( + _ "vitess.io/vitess/go/vt/mysqlctl/azblobbackupstorage" +) diff --git a/go/cmd/vtctl/plugin_azblobbackupstorage.go b/go/cmd/vtctl/plugin_azblobbackupstorage.go new file mode 100644 index 00000000000..a4ca64096a9 --- /dev/null +++ b/go/cmd/vtctl/plugin_azblobbackupstorage.go @@ -0,0 +1,21 @@ +/* +Copyright 2020 The Vitess Authors. + +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. +*/ + +package main + +import ( + _ "vitess.io/vitess/go/vt/mysqlctl/azblobbackupstorage" +) diff --git a/go/cmd/vtctld/plugin_azblobbackupstorage.go b/go/cmd/vtctld/plugin_azblobbackupstorage.go new file mode 100644 index 00000000000..a4ca64096a9 --- /dev/null +++ b/go/cmd/vtctld/plugin_azblobbackupstorage.go @@ -0,0 +1,21 @@ +/* +Copyright 2020 The Vitess Authors. + +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. +*/ + +package main + +import ( + _ "vitess.io/vitess/go/vt/mysqlctl/azblobbackupstorage" +) diff --git a/go/cmd/vtqueryserver/vtqueryserver.go b/go/cmd/vtqueryserver/vtqueryserver.go deleted file mode 100644 index 705c2bc9c38..00000000000 --- a/go/cmd/vtqueryserver/vtqueryserver.go +++ /dev/null @@ -1,76 +0,0 @@ -/* -Copyright 2019 The Vitess Authors. - -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. -*/ - -package main - -import ( - "flag" - "os" - - "vitess.io/vitess/go/vt/dbconfigs" - "vitess.io/vitess/go/vt/log" - "vitess.io/vitess/go/vt/servenv" - "vitess.io/vitess/go/vt/vtqueryserver" - "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" -) - -var ( - dbName string - mysqlSocketFile = flag.String("mysql-socket-file", "", "path to unix socket file to connect to mysql") -) - -func init() { - servenv.RegisterDefaultFlags() - // TODO(demmer): remove once migrated to using db_name - flag.StringVar(&dbName, "db-config-app-dbname", "", "db connection dbname") - flag.StringVar(&dbName, "db_name", "", "db connection dbname") -} - -func main() { - dbconfigs.RegisterFlags(dbconfigs.App, dbconfigs.AppDebug) - flag.Parse() - - if *servenv.Version { - servenv.AppVersion.Print() - os.Exit(0) - } - - if len(flag.Args()) > 0 { - flag.Usage() - log.Exit("vtqueryserver doesn't take any positional arguments") - } - if err := tabletenv.VerifyConfig(); err != nil { - log.Exitf("invalid config: %v", err) - } - - tabletenv.Init() - - servenv.Init() - - dbcfgs, err := dbconfigs.Init(*mysqlSocketFile) - if err != nil { - log.Fatal(err) - } - // DB name must be explicitly set. - dbcfgs.DBName.Set(dbName) - - err = vtqueryserver.Init(dbcfgs) - if err != nil { - log.Exitf("error initializing proxy: %v", err) - } - - servenv.RunDefault() -} diff --git a/go/cmd/vttablet/plugin_azblobbackupstorage.go b/go/cmd/vttablet/plugin_azblobbackupstorage.go new file mode 100644 index 00000000000..a4ca64096a9 --- /dev/null +++ b/go/cmd/vttablet/plugin_azblobbackupstorage.go @@ -0,0 +1,21 @@ +/* +Copyright 2020 The Vitess Authors. + +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. +*/ + +package main + +import ( + _ "vitess.io/vitess/go/vt/mysqlctl/azblobbackupstorage" +) diff --git a/go/cmd/vttablet/vttablet.go b/go/cmd/vttablet/vttablet.go index 837bc49fc89..0906e7879c3 100644 --- a/go/cmd/vttablet/vttablet.go +++ b/go/cmd/vttablet/vttablet.go @@ -61,7 +61,7 @@ func main() { servenv.Init() if *tabletPath == "" { - log.Exit("tabletPath required") + log.Exit("-tablet-path required") } tabletAlias, err := topoproto.ParseTabletAlias(*tabletPath) if err != nil { @@ -131,7 +131,8 @@ func main() { } servenv.OnClose(func() { - // stop the agent so that our topo entry gets pruned properly + // Close the agent so that our topo entry gets pruned properly and any + // background goroutines that use the topo connection are stopped. agent.Close() // We will still use the topo server during lameduck period diff --git a/go/cmd/vttestserver/main.go b/go/cmd/vttestserver/main.go index f2fd647a18f..8b88103e6d1 100644 --- a/go/cmd/vttestserver/main.go +++ b/go/cmd/vttestserver/main.go @@ -40,50 +40,17 @@ type topoFlags struct { rdonly int } -func (t *topoFlags) buildTopology() (*vttestpb.VTTestTopology, error) { - topo := &vttestpb.VTTestTopology{} - topo.Cells = strings.Split(t.cells, ",") - - keyspaces := strings.Split(t.keyspaces, ",") - shardCounts := strings.Split(t.shards, ",") - if len(keyspaces) != len(shardCounts) { - return nil, fmt.Errorf("--keyspaces must be same length as --shards") - } - - for i := range keyspaces { - name := keyspaces[i] - numshards, err := strconv.ParseInt(shardCounts[i], 10, 32) - if err != nil { - return nil, err - } - - ks := &vttestpb.Keyspace{ - Name: name, - ReplicaCount: int32(t.replicas), - RdonlyCount: int32(t.rdonly), - } - - for _, shardname := range vttest.GetShardNames(int(numshards)) { - ks.Shards = append(ks.Shards, &vttestpb.Shard{ - Name: shardname, - }) - } - - topo.Keyspaces = append(topo.Keyspaces, ks) - } - - return topo, nil -} - -func parseFlags() (config vttest.Config, env vttest.Environment, err error) { - var seed vttest.SeedConfig - var topo topoFlags - - var basePort int - var protoTopo string - var doSeed bool - var mycnf string +var ( + basePort int + config vttest.Config + doSeed bool + mycnf string + protoTopo string + seed vttest.SeedConfig + topo topoFlags +) +func init() { flag.IntVar(&basePort, "port", 0, "Port to use for vtcombo. If this is 0, a random port will be chosen.") @@ -139,12 +106,6 @@ func parseFlags() (config vttest.Config, env vttest.Environment, err error) { " if --initialize_with_random_data is true. Only applies to fields"+ " that can contain NULL values.") - flag.StringVar(&config.WebDir, "web_dir", "", - "location of the vtctld web server files.") - - flag.StringVar(&config.WebDir2, "web_dir2", "", - "location of the vtctld2 web server files.") - flag.StringVar(&config.MySQLBindHost, "mysql_bind_host", "localhost", "which host to bind vtgate mysql listener to") @@ -172,6 +133,45 @@ func parseFlags() (config vttest.Config, env vttest.Environment, err error) { flag.BoolVar(&config.InitWorkflowManager, "workflow_manager_init", false, "Enable workflow manager") + flag.StringVar(&config.VSchemaDDLAuthorizedUsers, "vschema_ddl_authorized_users", "", "Comma separated list of users authorized to execute vschema ddl operations via vtgate") +} + +func (t *topoFlags) buildTopology() (*vttestpb.VTTestTopology, error) { + topo := &vttestpb.VTTestTopology{} + topo.Cells = strings.Split(t.cells, ",") + + keyspaces := strings.Split(t.keyspaces, ",") + shardCounts := strings.Split(t.shards, ",") + if len(keyspaces) != len(shardCounts) { + return nil, fmt.Errorf("--keyspaces must be same length as --shards") + } + + for i := range keyspaces { + name := keyspaces[i] + numshards, err := strconv.ParseInt(shardCounts[i], 10, 32) + if err != nil { + return nil, err + } + + ks := &vttestpb.Keyspace{ + Name: name, + ReplicaCount: int32(t.replicas), + RdonlyCount: int32(t.rdonly), + } + + for _, shardname := range vttest.GetShardNames(int(numshards)) { + ks.Shards = append(ks.Shards, &vttestpb.Shard{ + Name: shardname, + }) + } + + topo.Keyspaces = append(topo.Keyspaces, ks) + } + + return topo, nil +} + +func parseFlags() (env vttest.Environment, err error) { flag.Parse() if basePort != 0 { @@ -217,7 +217,10 @@ func parseFlags() (config vttest.Config, env vttest.Environment, err error) { } func main() { - cluster := runCluster() + cluster, err := runCluster() + if err != nil { + log.Fatal(err) + } defer cluster.TearDown() kvconf := cluster.JSONConfig() @@ -228,8 +231,8 @@ func main() { select {} } -func runCluster() vttest.LocalCluster { - config, env, err := parseFlags() +func runCluster() (vttest.LocalCluster, error) { + env, err := parseFlags() if err != nil { log.Fatal(err) } @@ -241,10 +244,10 @@ func runCluster() vttest.LocalCluster { } err = cluster.Setup() if err != nil { - log.Fatal(err) + return cluster, err } log.Info("Local cluster started.") - return cluster + return cluster, nil } diff --git a/go/cmd/vttestserver/vttestserver_test.go b/go/cmd/vttestserver/vttestserver_test.go index 2e4b4cec91e..799b942f013 100644 --- a/go/cmd/vttestserver/vttestserver_test.go +++ b/go/cmd/vttestserver/vttestserver_test.go @@ -19,9 +19,17 @@ package main import ( "context" "fmt" + "io/ioutil" "os" + "path" "testing" + "vitess.io/vitess/go/vt/tlstest" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/vt/vttest" "github.com/golang/protobuf/jsonpb" @@ -39,22 +47,130 @@ type columnVindex struct { } func TestRunsVschemaMigrations(t *testing.T) { - schemaDirArg := "-schema_dir=data/schema" - webDirArg := "-web_dir=web/vtctld/app" - webDir2Arg := "-web_dir2=web/vtctld2/app" - tabletHostname := "-tablet_hostname=localhost" - keyspaceArg := "-keyspaces=test_keyspace,app_customer" - numShardsArg := "-num_shards=2,2" + cluster, err := startCluster() + defer cluster.TearDown() + args := os.Args + defer resetFlags(args) + + assert.NoError(t, err) + assertColumnVindex(t, cluster, columnVindex{keyspace: "test_keyspace", table: "test_table", vindex: "my_vdx", vindexType: "hash", column: "id"}) + assertColumnVindex(t, cluster, columnVindex{keyspace: "app_customer", table: "customers", vindex: "hash", vindexType: "hash", column: "id"}) - os.Args = append(os.Args, []string{schemaDirArg, keyspaceArg, numShardsArg, webDirArg, webDir2Arg, tabletHostname}...) + // Add Hash vindex via vtgate execution on table + err = addColumnVindex(cluster, "test_keyspace", "alter vschema on test_table1 add vindex my_vdx (id)") + assert.NoError(t, err) + assertColumnVindex(t, cluster, columnVindex{keyspace: "test_keyspace", table: "test_table1", vindex: "my_vdx", vindexType: "hash", column: "id"}) +} - cluster := runCluster() +func TestMtlsAuth(t *testing.T) { + // Our test root. + root, err := ioutil.TempDir("", "tlstest") + if err != nil { + t.Fatalf("TempDir failed: %v", err) + } + defer os.RemoveAll(root) + + // Create the certs and configs. + tlstest.CreateCA(root) + caCert := path.Join(root, "ca-cert.pem") + + tlstest.CreateSignedCert(root, tlstest.CA, "01", "vtctld", "vtctld.example.com") + cert := path.Join(root, "vtctld-cert.pem") + key := path.Join(root, "vtctld-key.pem") + + tlstest.CreateSignedCert(root, tlstest.CA, "02", "client", "ClientApp") + clientCert := path.Join(root, "client-cert.pem") + clientKey := path.Join(root, "client-key.pem") + + // When cluster starts it will apply SQL and VSchema migrations in the configured schema_dir folder + // With mtls authorization enabled, the authorized CN must match the certificate's CN + cluster, err := startCluster( + "-grpc_auth_mode=mtls", + fmt.Sprintf("-grpc_key=%s", key), + fmt.Sprintf("-grpc_cert=%s", cert), + fmt.Sprintf("-grpc_ca=%s", caCert), + fmt.Sprintf("-vtctld_grpc_key=%s", clientKey), + fmt.Sprintf("-vtctld_grpc_cert=%s", clientCert), + fmt.Sprintf("-vtctld_grpc_ca=%s", caCert), + fmt.Sprintf("-grpc_auth_mtls_allowed_substrings=%s", "CN=ClientApp")) + assert.NoError(t, err) defer cluster.TearDown() + args := os.Args + defer resetFlags(args) + // startCluster will apply vschema migrations using vtctl grpc and the clientCert. assertColumnVindex(t, cluster, columnVindex{keyspace: "test_keyspace", table: "test_table", vindex: "my_vdx", vindexType: "hash", column: "id"}) assertColumnVindex(t, cluster, columnVindex{keyspace: "app_customer", table: "customers", vindex: "hash", vindexType: "hash", column: "id"}) } +func TestMtlsAuthUnaothorizedFails(t *testing.T) { + // Our test root. + root, err := ioutil.TempDir("", "tlstest") + if err != nil { + t.Fatalf("TempDir failed: %v", err) + } + defer os.RemoveAll(root) + + // Create the certs and configs. + tlstest.CreateCA(root) + caCert := path.Join(root, "ca-cert.pem") + + tlstest.CreateSignedCert(root, tlstest.CA, "01", "vtctld", "vtctld.example.com") + cert := path.Join(root, "vtctld-cert.pem") + key := path.Join(root, "vtctld-key.pem") + + tlstest.CreateSignedCert(root, tlstest.CA, "02", "client", "AnotherApp") + clientCert := path.Join(root, "client-cert.pem") + clientKey := path.Join(root, "client-key.pem") + + // When cluster starts it will apply SQL and VSchema migrations in the configured schema_dir folder + // For mtls authorization failure by providing a client certificate with different CN thant the + // authorized in the configuration + cluster, err := startCluster( + "-grpc_auth_mode=mtls", + fmt.Sprintf("-grpc_key=%s", key), + fmt.Sprintf("-grpc_cert=%s", cert), + fmt.Sprintf("-grpc_ca=%s", caCert), + fmt.Sprintf("-vtctld_grpc_key=%s", clientKey), + fmt.Sprintf("-vtctld_grpc_cert=%s", clientCert), + fmt.Sprintf("-vtctld_grpc_ca=%s", caCert), + fmt.Sprintf("-grpc_auth_mtls_allowed_substrings=%s", "CN=ClientApp")) + defer cluster.TearDown() + args := os.Args + defer resetFlags(args) + + assert.Error(t, err) + assert.Contains(t, err.Error(), "code = Unauthenticated desc = client certificate not authorized") +} + +func startCluster(flags ...string) (vttest.LocalCluster, error) { + schemaDirArg := "-schema_dir=data/schema" + tabletHostname := "-tablet_hostname=localhost" + keyspaceArg := "-keyspaces=test_keyspace,app_customer" + numShardsArg := "-num_shards=2,2" + vschemaDDLAuthorizedUsers := "-vschema_ddl_authorized_users=%" + os.Args = append(os.Args, []string{schemaDirArg, keyspaceArg, numShardsArg, tabletHostname, vschemaDDLAuthorizedUsers}...) + os.Args = append(os.Args, flags...) + return runCluster() +} + +func addColumnVindex(cluster vttest.LocalCluster, keyspace string, vschemaMigration string) error { + ctx := context.Background() + vtParams := mysql.ConnParams{ + Host: "localhost", + DbName: keyspace, + Port: cluster.Env.PortForProtocol("vtcombo_mysql_port", ""), + } + + conn, err := mysql.Connect(ctx, &vtParams) + if err != nil { + return err + } + defer conn.Close() + _, err = conn.ExecuteFetch(vschemaMigration, 1, false) + return err +} + func assertColumnVindex(t *testing.T, cluster vttest.LocalCluster, expected columnVindex) { server := fmt.Sprintf("localhost:%v", cluster.GrpcPort()) args := []string{"GetVSchema", expected.keyspace} @@ -72,9 +188,7 @@ func assertColumnVindex(t *testing.T, cluster vttest.LocalCluster, expected colu assertEqual(t, columnVindex.Name, expected.vindex, "Actual vindex name different from expected") assertEqual(t, columnVindex.Columns[0], expected.column, "Actual vindex column different from expected") }) - if err != nil { - t.Error(err) - } + require.NoError(t, err) } func assertEqual(t *testing.T, actual string, expected string, message string) { @@ -82,3 +196,7 @@ func assertEqual(t *testing.T, actual string, expected string, message string) { t.Errorf("%s: actual %s, expected %s", message, actual, expected) } } + +func resetFlags(args []string) { + os.Args = args +} diff --git a/go/cmd/zk/zkcmd.go b/go/cmd/zk/zkcmd.go index 67a34773573..1b01f19aaac 100644 --- a/go/cmd/zk/zkcmd.go +++ b/go/cmd/zk/zkcmd.go @@ -177,7 +177,7 @@ func main() { func fixZkPath(zkPath string) string { if zkPath != "/" { - zkPath = strings.TrimRight(zkPath, "/") + zkPath = strings.TrimSuffix(zkPath, "/") } return path.Clean(zkPath) } diff --git a/go/mysql/auth_server_clientcert_test.go b/go/mysql/auth_server_clientcert_test.go index b812211e784..73afb810ce0 100644 --- a/go/mysql/auth_server_clientcert_test.go +++ b/go/mysql/auth_server_clientcert_test.go @@ -39,7 +39,7 @@ func TestValidCert(t *testing.T) { } // Create the listener, so we can get its host. - l, err := NewListener("tcp", ":0", authServer, th, 0, 0) + l, err := NewListener("tcp", ":0", authServer, th, 0, 0, false) if err != nil { t.Fatalf("NewListener failed: %v", err) } @@ -100,7 +100,7 @@ func TestValidCert(t *testing.T) { t.Errorf("Got wrong result from ExecuteFetch(ssl echo): %v", result) } - userData := th.lastConn.UserData.Get() + userData := th.LastConn().UserData.Get() if userData.Username != clientCertUsername { t.Errorf("userdata username is %v, expected %v", userData.Username, clientCertUsername) } @@ -122,7 +122,7 @@ func TestNoCert(t *testing.T) { } // Create the listener, so we can get its host. - l, err := NewListener("tcp", ":0", authServer, th, 0, 0) + l, err := NewListener("tcp", ":0", authServer, th, 0, 0, false) if err != nil { t.Fatalf("NewListener failed: %v", err) } diff --git a/go/mysql/auth_server_static.go b/go/mysql/auth_server_static.go index cad9cb0573e..acb90678f54 100644 --- a/go/mysql/auth_server_static.go +++ b/go/mysql/auth_server_static.go @@ -46,16 +46,21 @@ const ( // AuthServerStatic implements AuthServer using a static configuration. type AuthServerStatic struct { - // Method can be set to: + file, jsonConfig string + reloadInterval time.Duration + // method can be set to: // - MysqlNativePassword // - MysqlClearPassword // - MysqlDialog // It defaults to MysqlNativePassword. - Method string - // This mutex helps us prevent data races between the multiple updates of Entries. + method string + // This mutex helps us prevent data races between the multiple updates of entries. mu sync.Mutex - // Entries contains the users, passwords and user data. - Entries map[string][]*AuthServerStaticEntry + // entries contains the users, passwords and user data. + entries map[string][]*AuthServerStaticEntry + + sigChan chan os.Signal + ticker *time.Ticker } // AuthServerStaticEntry stores the values for a given user. @@ -92,102 +97,104 @@ func InitAuthServerStatic() { } // Create and register auth server. - RegisterAuthServerStaticFromParams(*mysqlAuthServerStaticFile, *mysqlAuthServerStaticString) -} - -// NewAuthServerStatic returns a new empty AuthServerStatic. -func NewAuthServerStatic() *AuthServerStatic { - return &AuthServerStatic{ - Method: MysqlNativePassword, - Entries: make(map[string][]*AuthServerStaticEntry), - } + RegisterAuthServerStaticFromParams(*mysqlAuthServerStaticFile, *mysqlAuthServerStaticString, *mysqlAuthServerStaticReloadInterval) } // RegisterAuthServerStaticFromParams creates and registers a new // AuthServerStatic, loaded for a JSON file or string. If file is set, // it uses file. Otherwise, load the string. It log.Exits out in case // of error. -func RegisterAuthServerStaticFromParams(file, str string) { - authServerStatic := NewAuthServerStatic() - - authServerStatic.loadConfigFromParams(file, str) - - if len(authServerStatic.Entries) <= 0 { +func RegisterAuthServerStaticFromParams(file, jsonConfig string, reloadInterval time.Duration) { + authServerStatic := NewAuthServerStatic(file, jsonConfig, reloadInterval) + if len(authServerStatic.entries) <= 0 { log.Exitf("Failed to populate entries from file: %v", file) } - authServerStatic.installSignalHandlers() - - // And register the server. RegisterAuthServerImpl("static", authServerStatic) } -func (a *AuthServerStatic) loadConfigFromParams(file, str string) { - jsonConfig := []byte(str) - if file != "" { - data, err := ioutil.ReadFile(file) +// NewAuthServerStatic returns a new empty AuthServerStatic. +func NewAuthServerStatic(file, jsonConfig string, reloadInterval time.Duration) *AuthServerStatic { + a := &AuthServerStatic{ + file: file, + jsonConfig: jsonConfig, + reloadInterval: reloadInterval, + method: MysqlNativePassword, + entries: make(map[string][]*AuthServerStaticEntry), + } + a.reload() + a.installSignalHandlers() + return a +} + +func (a *AuthServerStatic) reload() { + jsonBytes := []byte(a.jsonConfig) + if a.file != "" { + data, err := ioutil.ReadFile(a.file) if err != nil { log.Errorf("Failed to read mysql_auth_server_static_file file: %v", err) return } - jsonConfig = data + jsonBytes = data } entries := make(map[string][]*AuthServerStaticEntry) - if err := parseConfig(jsonConfig, &entries); err != nil { + if err := parseConfig(jsonBytes, &entries); err != nil { log.Errorf("Error parsing auth server config: %v", err) return } a.mu.Lock() - a.Entries = entries + a.entries = entries a.mu.Unlock() } func (a *AuthServerStatic) installSignalHandlers() { - if *mysqlAuthServerStaticFile == "" { + if a.file == "" { return } - sigChan := make(chan os.Signal, 1) - signal.Notify(sigChan, syscall.SIGHUP) + a.sigChan = make(chan os.Signal, 1) + signal.Notify(a.sigChan, syscall.SIGHUP) go func() { - for range sigChan { - a.loadConfigFromParams(*mysqlAuthServerStaticFile, "") + for range a.sigChan { + a.reload() } }() // If duration is set, it will reload configuration every interval - if *mysqlAuthServerStaticReloadInterval > 0 { - ticker := time.NewTicker(*mysqlAuthServerStaticReloadInterval) + if a.reloadInterval > 0 { + a.ticker = time.NewTicker(a.reloadInterval) go func() { - for { - select { - case <-ticker.C: - if *mysqlAuthServerStaticReloadInterval <= 0 { - ticker.Stop() - return - } - sigChan <- syscall.SIGHUP - } + for range a.ticker.C { + a.sigChan <- syscall.SIGHUP } }() } } -func parseConfig(jsonConfig []byte, config *map[string][]*AuthServerStaticEntry) error { - decoder := json.NewDecoder(bytes.NewReader(jsonConfig)) +func (a *AuthServerStatic) close() { + if a.ticker != nil { + a.ticker.Stop() + } + if a.sigChan != nil { + signal.Stop(a.sigChan) + } +} + +func parseConfig(jsonBytes []byte, config *map[string][]*AuthServerStaticEntry) error { + decoder := json.NewDecoder(bytes.NewReader(jsonBytes)) decoder.DisallowUnknownFields() if err := decoder.Decode(config); err != nil { // Couldn't parse, will try to parse with legacy config - return parseLegacyConfig(jsonConfig, config) + return parseLegacyConfig(jsonBytes, config) } return validateConfig(*config) } -func parseLegacyConfig(jsonConfig []byte, config *map[string][]*AuthServerStaticEntry) error { +func parseLegacyConfig(jsonBytes []byte, config *map[string][]*AuthServerStaticEntry) error { // legacy config doesn't have an array legacyConfig := make(map[string]*AuthServerStaticEntry) - decoder := json.NewDecoder(bytes.NewReader(jsonConfig)) + decoder := json.NewDecoder(bytes.NewReader(jsonBytes)) decoder.DisallowUnknownFields() if err := decoder.Decode(&legacyConfig); err != nil { return err @@ -212,7 +219,7 @@ func validateConfig(config map[string][]*AuthServerStaticEntry) error { // AuthMethod is part of the AuthServer interface. func (a *AuthServerStatic) AuthMethod(user string) (string, error) { - return a.Method, nil + return a.method, nil } // Salt is part of the AuthServer interface. @@ -223,7 +230,7 @@ func (a *AuthServerStatic) Salt() ([]byte, error) { // ValidateHash is part of the AuthServer interface. func (a *AuthServerStatic) ValidateHash(salt []byte, user string, authResponse []byte, remoteAddr net.Addr) (Getter, error) { a.mu.Lock() - entries, ok := a.Entries[user] + entries, ok := a.entries[user] a.mu.Unlock() if !ok { @@ -248,17 +255,17 @@ func (a *AuthServerStatic) ValidateHash(salt []byte, user string, authResponse [ } // Negotiate is part of the AuthServer interface. -// It will be called if Method is anything else than MysqlNativePassword. +// It will be called if method is anything else than MysqlNativePassword. // We only recognize MysqlClearPassword and MysqlDialog here. func (a *AuthServerStatic) Negotiate(c *Conn, user string, remoteAddr net.Addr) (Getter, error) { // Finish the negotiation. - password, err := AuthServerNegotiateClearOrDialog(c, a.Method) + password, err := AuthServerNegotiateClearOrDialog(c, a.method) if err != nil { return nil, err } a.mu.Lock() - entries, ok := a.Entries[user] + entries, ok := a.entries[user] a.mu.Unlock() if !ok { diff --git a/go/mysql/auth_server_static_test.go b/go/mysql/auth_server_static_test.go index eda98ec3ae5..2586da2f60b 100644 --- a/go/mysql/auth_server_static_test.go +++ b/go/mysql/auth_server_static_test.go @@ -26,6 +26,13 @@ import ( "time" ) +// getEntries is a test-only method for AuthServerStatic. +func (a *AuthServerStatic) getEntries() map[string][]*AuthServerStaticEntry { + a.mu.Lock() + defer a.mu.Unlock() + return a.entries +} + func TestJsonConfigParser(t *testing.T) { // works with legacy format config := make(map[string][]*AuthServerStaticEntry) @@ -75,8 +82,8 @@ func TestJsonConfigParser(t *testing.T) { func TestValidateHashGetter(t *testing.T) { jsonConfig := `{"mysql_user": [{"Password": "password", "UserData": "user.name", "Groups": ["user_group"]}]}` - auth := NewAuthServerStatic() - auth.loadConfigFromParams("", jsonConfig) + auth := NewAuthServerStatic("", jsonConfig, 0) + defer auth.close() ip := net.ParseIP("127.0.0.1") addr := &net.IPAddr{IP: ip, Zone: ""} @@ -121,28 +128,27 @@ func TestHostMatcher(t *testing.T) { } func TestStaticConfigHUP(t *testing.T) { - tmpFile, err := ioutil.TempFile("", "mysql_auth_server_static_file.json") if err != nil { t.Fatalf("couldn't create temp file: %v", err) } defer os.Remove(tmpFile.Name()) - *mysqlAuthServerStaticFile = tmpFile.Name() + oldStr := "str5" jsonConfig := fmt.Sprintf("{\"%s\":[{\"Password\":\"%s\"}]}", oldStr, oldStr) if err := ioutil.WriteFile(tmpFile.Name(), []byte(jsonConfig), 0600); err != nil { t.Fatalf("couldn't write temp file: %v", err) } - InitAuthServerStatic() - aStatic := GetAuthServer("static").(*AuthServerStatic) + aStatic := NewAuthServerStatic(tmpFile.Name(), "", 0) + defer aStatic.close() - if aStatic.Entries[oldStr][0].Password != oldStr { + if aStatic.getEntries()[oldStr][0].Password != oldStr { t.Fatalf("%s's Password should still be '%s'", oldStr, oldStr) } - hupTest(t, tmpFile, oldStr, "str2") - hupTest(t, tmpFile, "str2", "str3") // still handling the signal + hupTest(t, aStatic, tmpFile, oldStr, "str2") + hupTest(t, aStatic, tmpFile, "str2", "str3") // still handling the signal // delete registered Auth server for auth := range authServers { @@ -156,11 +162,6 @@ func TestStaticConfigHUPWithRotation(t *testing.T) { t.Fatalf("couldn't create temp file: %v", err) } defer os.Remove(tmpFile.Name()) - *mysqlAuthServerStaticFile = tmpFile.Name() - - savedReloadInterval := *mysqlAuthServerStaticReloadInterval - defer func() { *mysqlAuthServerStaticReloadInterval = savedReloadInterval }() - *mysqlAuthServerStaticReloadInterval = 10 * time.Millisecond oldStr := "str1" jsonConfig := fmt.Sprintf("{\"%s\":[{\"Password\":\"%s\"}]}", oldStr, oldStr) @@ -168,58 +169,54 @@ func TestStaticConfigHUPWithRotation(t *testing.T) { t.Fatalf("couldn't write temp file: %v", err) } - InitAuthServerStatic() - aStatic := GetAuthServer("static").(*AuthServerStatic) + aStatic := NewAuthServerStatic(tmpFile.Name(), "", 10*time.Millisecond) + defer aStatic.close() - if aStatic.Entries[oldStr][0].Password != oldStr { + if aStatic.getEntries()[oldStr][0].Password != oldStr { t.Fatalf("%s's Password should still be '%s'", oldStr, oldStr) } - hupTestWithRotation(t, tmpFile, oldStr, "str4") - hupTestWithRotation(t, tmpFile, "str4", "str5") + hupTestWithRotation(t, aStatic, tmpFile, oldStr, "str4") + hupTestWithRotation(t, aStatic, tmpFile, "str4", "str5") } -func hupTest(t *testing.T, tmpFile *os.File, oldStr, newStr string) { - aStatic := GetAuthServer("static").(*AuthServerStatic) - +func hupTest(t *testing.T, aStatic *AuthServerStatic, tmpFile *os.File, oldStr, newStr string) { jsonConfig := fmt.Sprintf("{\"%s\":[{\"Password\":\"%s\"}]}", newStr, newStr) if err := ioutil.WriteFile(tmpFile.Name(), []byte(jsonConfig), 0600); err != nil { t.Fatalf("couldn't overwrite temp file: %v", err) } - if aStatic.Entries[oldStr][0].Password != oldStr { + if aStatic.getEntries()[oldStr][0].Password != oldStr { t.Fatalf("%s's Password should still be '%s'", oldStr, oldStr) } syscall.Kill(syscall.Getpid(), syscall.SIGHUP) time.Sleep(100 * time.Millisecond) // wait for signal handler - if aStatic.Entries[oldStr] != nil { + if aStatic.getEntries()[oldStr] != nil { t.Fatalf("Should not have old %s after config reload", oldStr) } - if aStatic.Entries[newStr][0].Password != newStr { + if aStatic.getEntries()[newStr][0].Password != newStr { t.Fatalf("%s's Password should be '%s'", newStr, newStr) } } -func hupTestWithRotation(t *testing.T, tmpFile *os.File, oldStr, newStr string) { - aStatic := GetAuthServer("static").(*AuthServerStatic) - +func hupTestWithRotation(t *testing.T, aStatic *AuthServerStatic, tmpFile *os.File, oldStr, newStr string) { jsonConfig := fmt.Sprintf("{\"%s\":[{\"Password\":\"%s\"}]}", newStr, newStr) if err := ioutil.WriteFile(tmpFile.Name(), []byte(jsonConfig), 0600); err != nil { t.Fatalf("couldn't overwrite temp file: %v", err) } - if aStatic.Entries[oldStr][0].Password != oldStr { + if aStatic.getEntries()[oldStr][0].Password != oldStr { t.Fatalf("%s's Password should still be '%s'", oldStr, oldStr) } time.Sleep(20 * time.Millisecond) // wait for signal handler - if aStatic.Entries[oldStr] != nil { + if aStatic.getEntries()[oldStr] != nil { t.Fatalf("Should not have old %s after config reload", oldStr) } - if aStatic.Entries[newStr][0].Password != newStr { + if aStatic.getEntries()[newStr][0].Password != newStr { t.Fatalf("%s's Password should be '%s'", newStr, newStr) } } @@ -265,8 +262,8 @@ func TestStaticPasswords(t *testing.T) { {"", "password", false}, } - auth := NewAuthServerStatic() - auth.loadConfigFromParams("", jsonConfig) + auth := NewAuthServerStatic("", jsonConfig, 0) + defer auth.close() ip := net.ParseIP("127.0.0.1") addr := &net.IPAddr{IP: ip, Zone: ""} diff --git a/go/mysql/binlog_event_filepos.go b/go/mysql/binlog_event_filepos.go index 5080a323691..dfec653081e 100644 --- a/go/mysql/binlog_event_filepos.go +++ b/go/mysql/binlog_event_filepos.go @@ -19,7 +19,6 @@ package mysql import ( "encoding/binary" "fmt" - "strconv" ) // filePosBinlogEvent wraps a raw packet buffer and provides methods to examine @@ -106,9 +105,11 @@ func (ev filePosQueryEvent) Query(BinlogFormat) (Query, error) { }, nil } -//---------------------------------------------------------------------------- +func (ev filePosQueryEvent) StripChecksum(f BinlogFormat) (BinlogEvent, []byte, error) { + return ev, nil, nil +} -var _ BinlogEvent = filePosFakeEvent{} +//---------------------------------------------------------------------------- // filePosFakeEvent is the base class for fake events. type filePosFakeEvent struct { @@ -207,10 +208,6 @@ func (ev filePosFakeEvent) Rows(BinlogFormat, *TableMap) (Rows, error) { return Rows{}, nil } -func (ev filePosFakeEvent) StripChecksum(f BinlogFormat) (BinlogEvent, []byte, error) { - return ev, nil, nil -} - func (ev filePosFakeEvent) IsPseudo() bool { return false } @@ -230,7 +227,7 @@ func newFilePosGTIDEvent(file string, pos int, timestamp uint32) filePosGTIDEven }, gtid: filePosGTID{ file: file, - pos: strconv.Itoa(pos), + pos: pos, }, } } @@ -239,6 +236,10 @@ func (ev filePosGTIDEvent) IsGTID() bool { return true } +func (ev filePosGTIDEvent) StripChecksum(f BinlogFormat) (BinlogEvent, []byte, error) { + return ev, nil, nil +} + func (ev filePosGTIDEvent) GTID(BinlogFormat) (GTID, bool, error) { return ev.gtid, false, nil } diff --git a/go/mysql/client.go b/go/mysql/client.go index d679de6d733..3494a2a637c 100644 --- a/go/mysql/client.go +++ b/go/mysql/client.go @@ -303,17 +303,23 @@ func (c *Conn) clientHandshake(characterSet uint8, params *ConnParams) error { case AuthSwitchRequestPacket: // Server is asking to use a different auth method. We // only support cleartext plugin. - pluginName, _, err := parseAuthSwitchRequest(response) + pluginName, salt, err := parseAuthSwitchRequest(response) if err != nil { return NewSQLError(CRServerHandshakeErr, SSUnknownSQLState, "cannot parse auth switch request: %v", err) } - if pluginName != MysqlClearPassword { - return NewSQLError(CRServerHandshakeErr, SSUnknownSQLState, "server asked for unsupported auth method: %v", pluginName) - } - // Write the password packet. - if err := c.writeClearTextPassword(params); err != nil { - return err + if pluginName == MysqlClearPassword { + // Write the cleartext password packet. + if err := c.writeClearTextPassword(params); err != nil { + return err + } + } else if pluginName == MysqlNativePassword { + // Write the mysql_native_password packet. + if err := c.writeMysqlNativePassword(params, salt); err != nil { + return err + } + } else { + return NewSQLError(CRServerHandshakeErr, SSUnknownSQLState, "server asked for unsupported auth method: %v", pluginName) } // Wait for OK packet. @@ -380,7 +386,7 @@ func (c *Conn) parseInitialHandshakePacket(data []byte) (uint32, []byte, error) errorCode, pos, _ := readUint16(data, pos) // Normally there would be a 1-byte sql_state_marker field and a 5-byte // sql_state field here, but docs say these will not be present in this case. - errorMsg, pos, _ := readEOFString(data, pos) + errorMsg, _, _ := readEOFString(data, pos) return 0, nil, NewSQLError(CRServerHandshakeErr, SSUnknownSQLState, "immediate error from server errorCode=%v errorMsg=%v", errorCode, errorMsg) } @@ -649,7 +655,12 @@ func parseAuthSwitchRequest(data []byte) (string, []byte, error) { return "", nil, vterrors.Errorf(vtrpc.Code_INTERNAL, "cannot get plugin name from AuthSwitchRequest: %v", data) } - return pluginName, data[pos:], nil + // If this was a request with a salt in it, max 20 bytes + salt := data[pos:] + if len(salt) > 20 { + salt = salt[:20] + } + return pluginName, salt, nil } // writeClearTextPassword writes the clear text password. @@ -665,3 +676,17 @@ func (c *Conn) writeClearTextPassword(params *ConnParams) error { } return c.writeEphemeralPacket() } + +// writeMysqlNativePassword writes the encrypted mysql_native_password format +// Returns a SQLError. +func (c *Conn) writeMysqlNativePassword(params *ConnParams, salt []byte) error { + scrambledPassword := ScramblePassword(salt, []byte(params.Pass)) + data := c.startEphemeralPacket(len(scrambledPassword)) + pos := 0 + pos += copy(data[pos:], scrambledPassword) + // Sanity check. + if pos != len(data) { + return vterrors.Errorf(vtrpc.Code_INTERNAL, "error building MysqlNativePassword packet: got %v bytes expected %v", pos, len(data)) + } + return c.writeEphemeralPacket() +} diff --git a/go/mysql/conn.go b/go/mysql/conn.go index 64161fe6ee1..8cb4d04041f 100644 --- a/go/mysql/conn.go +++ b/go/mysql/conn.go @@ -21,6 +21,7 @@ import ( "crypto/tls" "crypto/x509" "errors" + "flag" "fmt" "io" "net" @@ -38,6 +39,8 @@ import ( "vitess.io/vitess/go/vt/vterrors" ) +var mysqlServerFlushDelay = flag.Duration("mysql_server_flush_delay", 100*time.Millisecond, "Delay after which buffered response will flushed to client.") + const ( // connBufferSize is how much we buffer for reading and // writing. It is also how much we allocate for ephemeral buffers. @@ -139,9 +142,13 @@ type Conn struct { ClientData interface{} // Packet encoding variables. + sequence uint8 bufferedReader *bufio.Reader + + // Buffered writing has a timer which flushes on inactivity. + bufMu sync.Mutex bufferedWriter *bufio.Writer - sequence uint8 + flushTimer *time.Timer // fields contains the fields definitions for an on-going // streaming query. It is set by ExecuteStreamFetch, and @@ -212,15 +219,20 @@ func newServerConn(conn net.Conn, listener *Listener) *Conn { } // startWriterBuffering starts using buffered writes. This should -// be terminated by a call to flush. +// be terminated by a call to endWriteBuffering. func (c *Conn) startWriterBuffering() { + c.bufMu.Lock() + defer c.bufMu.Unlock() + c.bufferedWriter = writersPool.Get().(*bufio.Writer) c.bufferedWriter.Reset(c.conn) } -// flush flushes the written data to the socket. -// This must be called to terminate startBuffering. -func (c *Conn) flush() error { +// endWriterBuffering must be called to terminate startWriteBuffering. +func (c *Conn) endWriterBuffering() error { + c.bufMu.Lock() + defer c.bufMu.Unlock() + if c.bufferedWriter == nil { return nil } @@ -231,16 +243,48 @@ func (c *Conn) flush() error { c.bufferedWriter = nil }() + c.stopFlushTimer() return c.bufferedWriter.Flush() } // getWriter returns the current writer. It may be either -// the original connection or a wrapper. -func (c *Conn) getWriter() io.Writer { +// the original connection or a wrapper. The returned unget +// function must be invoked after the writing is finished. +// In buffered mode, the unget starts a timer to flush any +// buffered data. +func (c *Conn) getWriter() (w io.Writer, unget func()) { + c.bufMu.Lock() if c.bufferedWriter != nil { - return c.bufferedWriter + return c.bufferedWriter, func() { + c.startFlushTimer() + c.bufMu.Unlock() + } + } + c.bufMu.Unlock() + return c.conn, func() {} +} + +// startFlushTimer must be called while holding lock on bufMu. +func (c *Conn) startFlushTimer() { + c.stopFlushTimer() + c.flushTimer = time.AfterFunc(*mysqlServerFlushDelay, func() { + c.bufMu.Lock() + defer c.bufMu.Unlock() + + if c.bufferedWriter == nil { + return + } + c.stopFlushTimer() + c.bufferedWriter.Flush() + }) +} + +// stopFlushTimer must be called while holding lock on bufMu. +func (c *Conn) stopFlushTimer() { + if c.flushTimer != nil { + c.flushTimer.Stop() + c.flushTimer = nil } - return c.conn } // getReader returns reader for connection. It can be *bufio.Reader or net.Conn @@ -474,7 +518,8 @@ func (c *Conn) writePacket(data []byte) error { index := 0 length := len(data) - w := c.getWriter() + w, unget := c.getWriter() + defer unget() for { // Packet length is capped to MaxPacketSize. @@ -740,43 +785,47 @@ func (c *Conn) handleNextCommand(handler Handler) error { return err } case ComQuery: - // flush is called at the end of this block. - // We cannot encapsulate it with a defer inside a func because - // we have to return from this func if it fails. - c.startWriterBuffering() - - queryStart := time.Now() - query := c.parseComQuery(data) - c.recycleReadPacket() + err := func() error { + c.startWriterBuffering() + defer func() { + if err := c.endWriterBuffering(); err != nil { + log.Errorf("conn %v: flush() failed: %v", c.ID(), err) + } + }() - var queries []string - if c.Capabilities&CapabilityClientMultiStatements != 0 { - queries, err = sqlparser.SplitStatementToPieces(query) - if err != nil { - log.Errorf("Conn %v: Error splitting query: %v", c, err) - if werr := c.writeErrorPacketFromError(err); werr != nil { - // If we can't even write the error, we're done. - log.Errorf("Conn %v: Error writing query error: %v", c, werr) - return werr + queryStart := time.Now() + query := c.parseComQuery(data) + c.recycleReadPacket() + + var queries []string + if c.Capabilities&CapabilityClientMultiStatements != 0 { + queries, err = sqlparser.SplitStatementToPieces(query) + if err != nil { + log.Errorf("Conn %v: Error splitting query: %v", c, err) + if werr := c.writeErrorPacketFromError(err); werr != nil { + // If we can't even write the error, we're done. + log.Errorf("Conn %v: Error writing query error: %v", c, werr) + return werr + } } + } else { + queries = []string{query} } - } else { - queries = []string{query} - } - for index, sql := range queries { - more := false - if index != len(queries)-1 { - more = true - } - if err := c.execQuery(sql, handler, more); err != nil { - return err + for index, sql := range queries { + more := false + if index != len(queries)-1 { + more = true + } + if err := c.execQuery(sql, handler, more); err != nil { + return err + } } - } - timings.Record(queryTimingKey, queryStart) + timings.Record(queryTimingKey, queryStart) - if err := c.flush(); err != nil { - log.Errorf("Conn %v: Flush() failed: %v", c.ID(), err) + return nil + }() + if err != nil { return err } @@ -853,7 +902,12 @@ func (c *Conn) handleNextCommand(handler Handler) error { statement, err := sqlparser.ParseStrictDDL(query) if err != nil { - return err + log.Errorf("Conn %v: Error parsing prepared statement: %v", c, err) + if werr := c.writeErrorPacketFromError(err); werr != nil { + // If we can't even write the error, we're done. + log.Errorf("Conn %v: Error writing prepared statement error: %v", c, werr) + return werr + } } paramsCount := uint16(0) @@ -891,84 +945,96 @@ func (c *Conn) handleNextCommand(handler Handler) error { } case ComStmtExecute: - queryStart := time.Now() - stmtID, _, err := c.parseComStmtExecute(c.PrepareData, data) - c.recycleReadPacket() - - if stmtID != uint32(0) { + err := func() error { + c.startWriterBuffering() defer func() { - // Allocate a new bindvar map every time since VTGate.Execute() mutates it. - prepare := c.PrepareData[stmtID] - prepare.BindVars = make(map[string]*querypb.BindVariable, prepare.ParamsCount) + if err := c.endWriterBuffering(); err != nil { + log.Errorf("conn %v: flush() failed: %v", c.ID(), err) + } }() - } - - if err != nil { - if werr := c.writeErrorPacketFromError(err); werr != nil { - // If we can't even write the error, we're done. - log.Error("Error writing query error to client %v: %v", c.ConnectionID, werr) - return werr + queryStart := time.Now() + stmtID, _, err := c.parseComStmtExecute(c.PrepareData, data) + c.recycleReadPacket() + + if stmtID != uint32(0) { + defer func() { + // Allocate a new bindvar map every time since VTGate.Execute() mutates it. + prepare := c.PrepareData[stmtID] + prepare.BindVars = make(map[string]*querypb.BindVariable, prepare.ParamsCount) + }() } - return nil - } - fieldSent := false - // sendFinished is set if the response should just be an OK packet. - sendFinished := false - prepare := c.PrepareData[stmtID] - err = handler.ComStmtExecute(c, prepare, func(qr *sqltypes.Result) error { - if sendFinished { - // Failsafe: Unreachable if server is well-behaved. - return io.EOF + if err != nil { + if werr := c.writeErrorPacketFromError(err); werr != nil { + // If we can't even write the error, we're done. + log.Error("Error writing query error to client %v: %v", c.ConnectionID, werr) + return werr + } + return nil } - if !fieldSent { - fieldSent = true - - if len(qr.Fields) == 0 { - sendFinished = true - // We should not send any more packets after this. - return c.writeOKPacket(qr.RowsAffected, qr.InsertID, c.StatusFlags, 0) - } - if err := c.writeFields(qr); err != nil { - return err + fieldSent := false + // sendFinished is set if the response should just be an OK packet. + sendFinished := false + prepare := c.PrepareData[stmtID] + err = handler.ComStmtExecute(c, prepare, func(qr *sqltypes.Result) error { + if sendFinished { + // Failsafe: Unreachable if server is well-behaved. + return io.EOF } - } - return c.writeBinaryRows(qr) - }) + if !fieldSent { + fieldSent = true + + if len(qr.Fields) == 0 { + sendFinished = true + // We should not send any more packets after this. + return c.writeOKPacket(qr.RowsAffected, qr.InsertID, c.StatusFlags, 0) + } + if err := c.writeFields(qr); err != nil { + return err + } + } - // If no field was sent, we expect an error. - if !fieldSent { - // This is just a failsafe. Should never happen. - if err == nil || err == io.EOF { - err = NewSQLErrorFromError(errors.New("unexpected: query ended without no results and no error")) - } - if werr := c.writeErrorPacketFromError(err); werr != nil { - // If we can't even write the error, we're done. - log.Errorf("Error writing query error to %s: %v", c, werr) - return werr - } - } else { - if err != nil { - // We can't send an error in the middle of a stream. - // All we can do is abort the send, which will cause a 2013. - log.Errorf("Error in the middle of a stream to %s: %v", c, err) - return err - } + return c.writeBinaryRows(qr) + }) - // Send the end packet only sendFinished is false (results were streamed). - // In this case the affectedRows and lastInsertID are always 0 since it - // was a read operation. - if !sendFinished { - if err := c.writeEndResult(false, 0, 0, handler.WarningCount(c)); err != nil { - log.Errorf("Error writing result to %s: %v", c, err) + // If no field was sent, we expect an error. + if !fieldSent { + // This is just a failsafe. Should never happen. + if err == nil || err == io.EOF { + err = NewSQLErrorFromError(errors.New("unexpected: query ended without no results and no error")) + } + if werr := c.writeErrorPacketFromError(err); werr != nil { + // If we can't even write the error, we're done. + log.Errorf("Error writing query error to %s: %v", c, werr) + return werr + } + } else { + if err != nil { + // We can't send an error in the middle of a stream. + // All we can do is abort the send, which will cause a 2013. + log.Errorf("Error in the middle of a stream to %s: %v", c, err) return err } + + // Send the end packet only sendFinished is false (results were streamed). + // In this case the affectedRows and lastInsertID are always 0 since it + // was a read operation. + if !sendFinished { + if err := c.writeEndResult(false, 0, 0, handler.WarningCount(c)); err != nil { + log.Errorf("Error writing result to %s: %v", c, err) + return err + } + } } - } - timings.Record(queryTimingKey, queryStart) + timings.Record(queryTimingKey, queryStart) + return nil + }() + if err != nil { + return err + } case ComStmtSendLongData: stmtID, paramID, chunkData, ok := c.parseComStmtSendLongData(data) c.recycleReadPacket() diff --git a/go/mysql/conn_params.go b/go/mysql/conn_params.go index d3956346612..488cca10199 100644 --- a/go/mysql/conn_params.go +++ b/go/mysql/conn_params.go @@ -30,11 +30,12 @@ type ConnParams struct { // The following SSL flags are only used when flags |= 2048 // is set (CapabilityClientSSL). - SslCa string `json:"ssl_ca"` - SslCaPath string `json:"ssl_ca_path"` - SslCert string `json:"ssl_cert"` - SslKey string `json:"ssl_key"` - ServerName string `json:"server_name"` + SslCa string `json:"ssl_ca"` + SslCaPath string `json:"ssl_ca_path"` + SslCert string `json:"ssl_cert"` + SslKey string `json:"ssl_key"` + ServerName string `json:"server_name"` + ConnectTimeoutMs uint64 `json:"connect_timeout_ms"` // The following is only set when the deprecated "dbname" flags are // supplied and will be removed. diff --git a/go/mysql/conn_test.go b/go/mysql/conn_test.go index 810ffea7a5f..405b23c40d5 100644 --- a/go/mysql/conn_test.go +++ b/go/mysql/conn_test.go @@ -89,7 +89,7 @@ func useWriteEphemeralPacketBuffered(t *testing.T, cConn *Conn, data []byte) { } }() cConn.startWriterBuffering() - defer cConn.flush() + defer cConn.endWriterBuffering() buf := cConn.startEphemeralPacket(len(data)) copy(buf, data) diff --git a/go/mysql/encoding.go b/go/mysql/encoding.go index c9333522cdf..53b9e2efc73 100644 --- a/go/mysql/encoding.go +++ b/go/mysql/encoding.go @@ -281,3 +281,17 @@ func readLenEncStringAsBytes(data []byte, pos int) ([]byte, int, bool) { } return data[pos : pos+s], pos + s, true } + +func readLenEncStringAsBytesCopy(data []byte, pos int) ([]byte, int, bool) { + size, pos, ok := readLenEncInt(data, pos) + if !ok { + return nil, 0, false + } + s := int(size) + if pos+s-1 >= len(data) { + return nil, 0, false + } + result := make([]byte, size) + copy(result, data[pos:pos+s]) + return result, pos + s, true +} diff --git a/go/mysql/encoding_test.go b/go/mysql/encoding_test.go index 2ca9a84c934..ac38b5c7db0 100644 --- a/go/mysql/encoding_test.go +++ b/go/mysql/encoding_test.go @@ -303,6 +303,24 @@ func TestEncString(t *testing.T) { t.Errorf("readLenEncStringAsBytes returned ok=true for empty value %v", test.value) } + // Check successful decoding as bytes. + gotbcopy, posCopy, ok := readLenEncStringAsBytesCopy(test.lenEncoded, 0) + if !ok || string(gotb) != test.value || pos != len(test.lenEncoded) { + t.Errorf("readLenEncString returned %v/%v/%v but expected %v/%v/%v", gotbcopy, posCopy, ok, test.value, len(test.lenEncoded), true) + } + + // Check failed decoding as bytes with shorter data. + _, _, ok = readLenEncStringAsBytesCopy(test.lenEncoded[:len(test.lenEncoded)-1], 0) + if ok { + t.Errorf("readLenEncStringAsBytes returned ok=true for shorter value %v", test.value) + } + + // Check failed decoding as bytes with no data. + _, _, ok = readLenEncStringAsBytesCopy([]byte{}, 0) + if ok { + t.Errorf("readLenEncStringAsBytes returned ok=true for empty value %v", test.value) + } + // null encoded tests. // Check successful encoding. diff --git a/go/mysql/endtoend/replication_test.go b/go/mysql/endtoend/replication_test.go index fa5697bcbf2..df5debcc3d3 100644 --- a/go/mysql/endtoend/replication_test.go +++ b/go/mysql/endtoend/replication_test.go @@ -191,93 +191,6 @@ func TestReplicationConnectionClosing(t *testing.T) { wg.Wait() } -func TestStatementReplicationWithRealDatabase(t *testing.T) { - conn, f := connectForReplication(t, false /* rbr */) - defer conn.Close() - - // Create a table, insert some data in it. - ctx := context.Background() - dConn, err := mysql.Connect(ctx, &connParams) - if err != nil { - t.Fatal(err) - } - defer dConn.Close() - createTable := "create table replication(id int, name varchar(128), primary key(id))" - if _, err := dConn.ExecuteFetch(createTable, 0, false); err != nil { - t.Fatal(err) - } - insert := "insert into replication(id, name) values(10, 'nice name')" - result, err := dConn.ExecuteFetch(insert, 0, false) - if err != nil { - t.Fatalf("insert failed: %v", err) - } - if result.RowsAffected != 1 || len(result.Rows) != 0 { - t.Errorf("unexpected result for insert: %v", result) - } - - // Get the new events from the binlogs. - // Make sure we get two GTIDs, the table creation event and the insert - // (with both a begin and a commit). - gtidCount := 0 - gotCreateTable := false - gotBegin := false - gotInsert := false - gotCommit := false - for gtidCount < 2 || !gotCreateTable || !gotBegin || !gotInsert || !gotCommit { - be, err := conn.ReadBinlogEvent() - if err != nil { - t.Fatalf("ReadPacket failed: %v", err) - } - if !be.IsValid() { - t.Fatalf("read an invalid packet: %v", be) - } - be, _, err = be.StripChecksum(f) - if err != nil { - t.Fatalf("StripChecksum failed: %v", err) - } - switch { - case be.IsGTID(): - // We expect one of these at least. - gtid, hasBegin, err := be.GTID(f) - if err != nil { - t.Fatalf("GTID event is broken: %v", err) - } - t.Logf("Got GTID event: %v %v", gtid, hasBegin) - gtidCount++ - if hasBegin { - gotBegin = true - } - case be.IsQuery(): - q, err := be.Query(f) - if err != nil { - t.Fatalf("Query event is broken: %v", err) - } - t.Logf("Got Query event: %v", q) - switch strings.ToLower(q.SQL) { - case createTable: - gotCreateTable = true - case insert: - gotInsert = true - case "begin": - gotBegin = true - case "commit": - gotCommit = true - } - case be.IsXID(): - gotCommit = true - t.Logf("Got XID event") - default: - t.Logf("Got unrelated event: %v", be) - } - } - - // Drop the table, we're done. - if _, err := dConn.ExecuteFetch("drop table replication", 0, false); err != nil { - t.Fatal(err) - } - -} - func TestRowReplicationWithRealDatabase(t *testing.T) { conn, f := connectForReplication(t, true /* rbr */) defer conn.Close() diff --git a/go/mysql/fakesqldb/server.go b/go/mysql/fakesqldb/server.go index 3c086c22637..dd29a495a0e 100644 --- a/go/mysql/fakesqldb/server.go +++ b/go/mysql/fakesqldb/server.go @@ -32,6 +32,7 @@ import ( "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/vt/dbconfigs" querypb "vitess.io/vitess/go/vt/proto/query" ) @@ -166,7 +167,7 @@ func New(t *testing.T) *DB { authServer := &mysql.AuthServerNone{} // Start listening. - db.listener, err = mysql.NewListener("unix", socketFile, authServer, db, 0, 0) + db.listener, err = mysql.NewListener("unix", socketFile, authServer, db, 0, 0, false) if err != nil { t.Fatalf("NewListener failed: %v", err) } @@ -257,23 +258,24 @@ func (db *DB) WaitForClose(timeout time.Duration) error { } // ConnParams returns the ConnParams to connect to the DB. -func (db *DB) ConnParams() *mysql.ConnParams { - return &mysql.ConnParams{ +func (db *DB) ConnParams() dbconfigs.Connector { + return dbconfigs.New(&mysql.ConnParams{ UnixSocket: db.socketFile, Uname: "user1", Pass: "password1", Charset: "utf8", - } + }) + } // ConnParamsWithUname returns ConnParams to connect to the DB with the Uname set to the provided value. -func (db *DB) ConnParamsWithUname(uname string) *mysql.ConnParams { - return &mysql.ConnParams{ +func (db *DB) ConnParamsWithUname(uname string) dbconfigs.Connector { + return dbconfigs.New(&mysql.ConnParams{ UnixSocket: db.socketFile, Uname: uname, Pass: "password1", Charset: "utf8", - } + }) } // diff --git a/go/mysql/filepos_gtid.go b/go/mysql/filepos_gtid.go index 9894e405494..d261fc52717 100644 --- a/go/mysql/filepos_gtid.go +++ b/go/mysql/filepos_gtid.go @@ -18,6 +18,7 @@ package mysql import ( "fmt" + "strconv" "strings" ) @@ -31,9 +32,14 @@ func parseFilePosGTID(s string) (GTID, error) { return nil, fmt.Errorf("invalid FilePos GTID (%v): expecting file:pos", s) } + pos, err := strconv.Atoi(parts[1]) + if err != nil { + return nil, fmt.Errorf("invalid FilePos GTID (%v): expecting pos to be an integer", s) + } + return filePosGTID{ file: parts[0], - pos: parts[1], + pos: pos, }, nil } @@ -48,12 +54,13 @@ func parseFilePosGTIDSet(s string) (GTIDSet, error) { // filePosGTID implements GTID. type filePosGTID struct { - file, pos string + file string + pos int } // String implements GTID.String(). func (gtid filePosGTID) String() string { - return gtid.file + ":" + gtid.pos + return fmt.Sprintf("%s:%d", gtid.file, gtid.pos) } // Flavor implements GTID.Flavor(). diff --git a/go/mysql/filepos_gtid_test.go b/go/mysql/filepos_gtid_test.go new file mode 100644 index 00000000000..b3c98b74669 --- /dev/null +++ b/go/mysql/filepos_gtid_test.go @@ -0,0 +1,102 @@ +/* +Copyright 2020 The Vitess Authors. + +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. +*/ + +package mysql + +import ( + "testing" +) + +func Test_filePosGTID_String(t *testing.T) { + type fields struct { + file string + pos int + } + tests := []struct { + name string + fields fields + want string + }{ + { + "formats gtid correctly", + fields{file: "mysql-bin.166031", pos: 192394}, + "mysql-bin.166031:192394", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gtid := filePosGTID{ + file: tt.fields.file, + pos: tt.fields.pos, + } + if got := gtid.String(); got != tt.want { + t.Errorf("filePosGTID.String() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_filePosGTID_ContainsGTID(t *testing.T) { + type fields struct { + file string + pos int + } + type args struct { + other GTID + } + tests := []struct { + name string + fields fields + args args + want bool + }{ + { + "returns true when the position is equal", + fields{file: "testfile", pos: 1234}, + args{other: filePosGTID{file: "testfile", pos: 1234}}, + true, + }, + { + "returns true when the position is less than equal", + fields{file: "testfile", pos: 1234}, + args{other: filePosGTID{file: "testfile", pos: 1233}}, + true, + }, + { + "returns false when the position is less than equal", + fields{file: "testfile", pos: 1234}, + args{other: filePosGTID{file: "testfile", pos: 1235}}, + false, + }, + { + "it uses integer value for comparison (it is not lexicographical order)", + fields{file: "testfile", pos: 99761227}, + args{other: filePosGTID{file: "testfile", pos: 103939867}}, + false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gtid := filePosGTID{ + file: tt.fields.file, + pos: tt.fields.pos, + } + if got := gtid.ContainsGTID(tt.args.other); got != tt.want { + t.Errorf("filePosGTID.ContainsGTID() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/go/mysql/flavor.go b/go/mysql/flavor.go index 001ef89df7b..7eb18d4fb8b 100644 --- a/go/mysql/flavor.go +++ b/go/mysql/flavor.go @@ -55,6 +55,9 @@ type flavor interface { // startSlave returns the command to start the slave. startSlaveCommand() string + // restartSlave returns the commands to stop, reset and start the slave. + restartSlaveCommands() []string + // startSlaveUntilAfter will restart replication, but only allow it // to run until `pos` is reached. After reaching pos, replication will be stopped again startSlaveUntilAfter(pos Position) string @@ -71,7 +74,7 @@ type flavor interface { // resetReplicationCommands returns the commands to completely reset // replication on the host. - resetReplicationCommands() []string + resetReplicationCommands(c *Conn) []string // setSlavePositionCommands returns the commands to set the // replication position at which the slave will resume. @@ -165,6 +168,11 @@ func (c *Conn) StartSlaveCommand() string { return c.flavor.startSlaveCommand() } +// RestartSlaveCommands returns the commands to stop, reset and start the slave. +func (c *Conn) RestartSlaveCommands() []string { + return c.flavor.restartSlaveCommands() +} + // StartSlaveUntilAfterCommand returns the command to start the slave. func (c *Conn) StartSlaveUntilAfterCommand(pos Position) string { return c.flavor.startSlaveUntilAfter(pos) @@ -191,7 +199,7 @@ func (c *Conn) ReadBinlogEvent() (BinlogEvent, error) { // ResetReplicationCommands returns the commands to completely reset // replication on the host. func (c *Conn) ResetReplicationCommands() []string { - return c.flavor.resetReplicationCommands() + return c.flavor.resetReplicationCommands(c) } // SetSlavePositionCommands returns the commands to set the diff --git a/go/mysql/flavor_filepos.go b/go/mysql/flavor_filepos.go index 30703fff275..9b943ba5eab 100644 --- a/go/mysql/flavor_filepos.go +++ b/go/mysql/flavor_filepos.go @@ -21,6 +21,7 @@ import ( "fmt" "io" "strconv" + "strings" "time" "golang.org/x/net/context" @@ -39,35 +40,26 @@ func newFilePosFlavor() flavor { // masterGTIDSet is part of the Flavor interface. func (flv *filePosFlavor) masterGTIDSet(c *Conn) (GTIDSet, error) { - qr, err := c.ExecuteFetch("SHOW SLAVE STATUS", 100, true /* wantfields */) + qr, err := c.ExecuteFetch("SHOW MASTER STATUS", 100, true /* wantfields */) if err != nil { return nil, err } if len(qr.Rows) == 0 { - qr, err = c.ExecuteFetch("SHOW MASTER STATUS", 100, true /* wantfields */) - if err != nil { - return nil, err - } - if len(qr.Rows) == 0 { - return nil, errors.New("no master or slave status") - } - resultMap, err := resultToMap(qr) - if err != nil { - return nil, err - } - return filePosGTID{ - file: resultMap["File"], - pos: resultMap["Position"], - }, nil + return nil, errors.New("no master status") } resultMap, err := resultToMap(qr) if err != nil { return nil, err } + pos, err := strconv.Atoi(resultMap["Position"]) + if err != nil { + return nil, fmt.Errorf("invalid FilePos GTID (%v): expecting pos to be an integer", resultMap["Position"]) + } + return filePosGTID{ - file: resultMap["Relay_Master_Log_File"], - pos: resultMap["Exec_Master_Log_Pos"], + file: resultMap["File"], + pos: pos, }, nil } @@ -75,6 +67,10 @@ func (flv *filePosFlavor) startSlaveCommand() string { return "unsupported" } +func (flv *filePosFlavor) restartSlaveCommands() []string { + return []string{"unsupported"} +} + func (flv *filePosFlavor) stopSlaveCommand() string { return "unsupported" } @@ -86,13 +82,8 @@ func (flv *filePosFlavor) sendBinlogDumpCommand(c *Conn, slaveID uint32, startPo return fmt.Errorf("startPos.GTIDSet is wrong type - expected filePosGTID, got: %#v", startPos.GTIDSet) } - pos, err := strconv.Atoi(rpos.pos) - if err != nil { - return fmt.Errorf("invalid position: %v", startPos.GTIDSet) - } flv.file = rpos.file - - return c.WriteComBinlogDump(slaveID, rpos.file, uint32(pos), 0) + return c.WriteComBinlogDump(slaveID, rpos.file, uint32(rpos.pos), 0) } // readBinlogEvent is part of the Flavor interface. @@ -143,12 +134,19 @@ func (flv *filePosFlavor) readBinlogEvent(c *Conn) (BinlogEvent, error) { // No need to transmit. Just update the internal position for the next event. continue } - case eXIDEvent, eQueryEvent, eTableMapEvent, + case eXIDEvent, eTableMapEvent, eWriteRowsEventV0, eWriteRowsEventV1, eWriteRowsEventV2, eDeleteRowsEventV0, eDeleteRowsEventV1, eDeleteRowsEventV2, eUpdateRowsEventV0, eUpdateRowsEventV1, eUpdateRowsEventV2: flv.savedEvent = event return newFilePosGTIDEvent(flv.file, event.nextPosition(flv.format), event.Timestamp()), nil + case eQueryEvent: + q, err := event.Query(flv.format) + if err == nil && strings.HasPrefix(q.SQL, "#") { + continue + } + flv.savedEvent = event + return newFilePosGTIDEvent(flv.file, event.nextPosition(flv.format), event.Timestamp()), nil default: // For unrecognized events, send a fake "repair" event so that // the position gets transmitted. @@ -164,7 +162,7 @@ func (flv *filePosFlavor) readBinlogEvent(c *Conn) (BinlogEvent, error) { } // resetReplicationCommands is part of the Flavor interface. -func (flv *filePosFlavor) resetReplicationCommands() []string { +func (flv *filePosFlavor) resetReplicationCommands(c *Conn) []string { return []string{ "unsupported", } @@ -200,9 +198,14 @@ func (flv *filePosFlavor) status(c *Conn) (SlaveStatus, error) { } status := parseSlaveStatus(resultMap) + pos, err := strconv.Atoi(resultMap["Exec_Master_Log_Pos"]) + if err != nil { + return SlaveStatus{}, fmt.Errorf("invalid FilePos GTID (%v): expecting pos to be an integer", resultMap["Exec_Master_Log_Pos"]) + } + status.Position.GTIDSet = filePosGTID{ file: resultMap["Relay_Master_Log_File"], - pos: resultMap["Exec_Master_Log_Pos"], + pos: pos, } return status, nil } @@ -219,10 +222,10 @@ func (flv *filePosFlavor) waitUntilPositionCommand(ctx context.Context, pos Posi if timeout <= 0 { return "", fmt.Errorf("timed out waiting for position %v", pos) } - return fmt.Sprintf("SELECT MASTER_POS_WAIT('%s', %s, %.6f)", filePosPos.file, filePosPos.pos, timeout.Seconds()), nil + return fmt.Sprintf("SELECT MASTER_POS_WAIT('%s', %d, %.6f)", filePosPos.file, filePosPos.pos, timeout.Seconds()), nil } - return fmt.Sprintf("SELECT MASTER_POS_WAIT('%s', %s)", filePosPos.file, filePosPos.pos), nil + return fmt.Sprintf("SELECT MASTER_POS_WAIT('%s', %d)", filePosPos.file, filePosPos.pos), nil } func (*filePosFlavor) startSlaveUntilAfter(pos Position) string { diff --git a/go/mysql/flavor_mariadb.go b/go/mysql/flavor_mariadb.go index 98174aa9b48..bd22022209b 100644 --- a/go/mysql/flavor_mariadb.go +++ b/go/mysql/flavor_mariadb.go @@ -51,6 +51,14 @@ func (mariadbFlavor) startSlaveCommand() string { return "START SLAVE" } +func (mariadbFlavor) restartSlaveCommands() []string { + return []string{ + "STOP SLAVE", + "RESET SLAVE", + "START SLAVE", + } +} + func (mariadbFlavor) stopSlaveCommand() string { return "STOP SLAVE" } @@ -83,14 +91,17 @@ func (mariadbFlavor) sendBinlogDumpCommand(c *Conn, slaveID uint32, startPos Pos } // resetReplicationCommands is part of the Flavor interface. -func (mariadbFlavor) resetReplicationCommands() []string { - return []string{ +func (mariadbFlavor) resetReplicationCommands(c *Conn) []string { + resetCommands := []string{ "STOP SLAVE", "RESET SLAVE ALL", // "ALL" makes it forget master host:port. "RESET MASTER", "SET GLOBAL gtid_slave_pos = ''", - "SET GLOBAL rpl_semi_sync_master_enabled = false, GLOBAL rpl_semi_sync_slave_enabled = false", // semi-sync will be enabled if needed when slave is started. } + if c.SemiSyncExtensionLoaded() { + resetCommands = append(resetCommands, "SET GLOBAL rpl_semi_sync_master_enabled = false, GLOBAL rpl_semi_sync_slave_enabled = false") // semi-sync will be enabled if needed when slave is started. + } + return resetCommands } // setSlavePositionCommands is part of the Flavor interface. diff --git a/go/mysql/flavor_mysql.go b/go/mysql/flavor_mysql.go index 6ef3a34eb38..04d8e3be055 100644 --- a/go/mysql/flavor_mysql.go +++ b/go/mysql/flavor_mysql.go @@ -45,6 +45,14 @@ func (mysqlFlavor) startSlaveCommand() string { return "START SLAVE" } +func (mysqlFlavor) restartSlaveCommands() []string { + return []string{ + "STOP SLAVE", + "RESET SLAVE", + "START SLAVE", + } +} + func (mysqlFlavor) startSlaveUntilAfter(pos Position) string { return fmt.Sprintf("START SLAVE UNTIL SQL_AFTER_GTIDS = '%s'", pos) } @@ -66,13 +74,16 @@ func (mysqlFlavor) sendBinlogDumpCommand(c *Conn, slaveID uint32, startPos Posit } // resetReplicationCommands is part of the Flavor interface. -func (mysqlFlavor) resetReplicationCommands() []string { - return []string{ +func (mysqlFlavor) resetReplicationCommands(c *Conn) []string { + resetCommands := []string{ "STOP SLAVE", "RESET SLAVE ALL", // "ALL" makes it forget master host:port. "RESET MASTER", // This will also clear gtid_executed and gtid_purged. - "SET GLOBAL rpl_semi_sync_master_enabled = false, GLOBAL rpl_semi_sync_slave_enabled = false", // semi-sync will be enabled if needed when slave is started. } + if c.SemiSyncExtensionLoaded() { + resetCommands = append(resetCommands, "SET GLOBAL rpl_semi_sync_master_enabled = false, GLOBAL rpl_semi_sync_slave_enabled = false") // semi-sync will be enabled if needed when slave is started. + } + return resetCommands } // setSlavePositionCommands is part of the Flavor interface. diff --git a/go/mysql/handshake_test.go b/go/mysql/handshake_test.go index c366b5d86f6..6c3f8b5ff93 100644 --- a/go/mysql/handshake_test.go +++ b/go/mysql/handshake_test.go @@ -36,14 +36,15 @@ import ( func TestClearTextClientAuth(t *testing.T) { th := &testHandler{} - authServer := NewAuthServerStatic() - authServer.Method = MysqlClearPassword - authServer.Entries["user1"] = []*AuthServerStaticEntry{ + authServer := NewAuthServerStatic("", "", 0) + authServer.method = MysqlClearPassword + authServer.entries["user1"] = []*AuthServerStaticEntry{ {Password: "password1"}, } + defer authServer.close() // Create the listener. - l, err := NewListener("tcp", ":0", authServer, th, 0, 0) + l, err := NewListener("tcp", ":0", authServer, th, 0, 0, false) if err != nil { t.Fatalf("NewListener failed: %v", err) } @@ -70,7 +71,7 @@ func TestClearTextClientAuth(t *testing.T) { } // Change server side to allow clear text without auth. - l.AllowClearTextWithoutTLS = true + l.AllowClearTextWithoutTLS.Set(true) conn, err := Connect(ctx, params) if err != nil { t.Fatalf("unexpected connection error: %v", err) @@ -95,13 +96,14 @@ func TestClearTextClientAuth(t *testing.T) { func TestSSLConnection(t *testing.T) { th := &testHandler{} - authServer := NewAuthServerStatic() - authServer.Entries["user1"] = []*AuthServerStaticEntry{ + authServer := NewAuthServerStatic("", "", 0) + authServer.entries["user1"] = []*AuthServerStaticEntry{ {Password: "password1"}, } + defer authServer.close() // Create the listener, so we can get its host. - l, err := NewListener("tcp", ":0", authServer, th, 0, 0) + l, err := NewListener("tcp", ":0", authServer, th, 0, 0, false) if err != nil { t.Fatalf("NewListener failed: %v", err) } @@ -152,7 +154,7 @@ func TestSSLConnection(t *testing.T) { // Make sure clear text auth works over SSL. t.Run("ClearText", func(t *testing.T) { - authServer.Method = MysqlClearPassword + authServer.method = MysqlClearPassword testSSLConnectionClearText(t, params) }) } diff --git a/go/mysql/query.go b/go/mysql/query.go index 6ff9d1e9bc0..8d340a1e6cd 100644 --- a/go/mysql/query.go +++ b/go/mysql/query.go @@ -261,7 +261,7 @@ func (c *Conn) parseRow(data []byte, fields []*querypb.Field) ([]sqltypes.Value, } var s []byte var ok bool - s, pos, ok = readLenEncStringAsBytes(data, pos) + s, pos, ok = readLenEncStringAsBytesCopy(data, pos) if !ok { return nil, NewSQLError(CRMalformedPacket, SSUnknownSQLState, "decoding string failed") } @@ -680,7 +680,7 @@ func (c *Conn) parseStmtArgs(data []byte, typ querypb.Type, pos int) (sqltypes.V strconv.Itoa(int(hour)) + ":" + strconv.Itoa(int(minute)) + ":" + strconv.Itoa(int(second)) + "." + - strconv.Itoa(int(microSecond)) + fmt.Sprintf("%06d", microSecond) return sqltypes.NewVarChar(val), pos, ok case 0x07: @@ -781,7 +781,7 @@ func (c *Conn) parseStmtArgs(data []byte, typ querypb.Type, pos int) (sqltypes.V val += strconv.Itoa(int(hours)) + ":" + strconv.Itoa(int(minute)) + ":" + strconv.Itoa(int(second)) + "." + - strconv.Itoa(int(microSecond)) + fmt.Sprintf("%06d", microSecond) return sqltypes.NewVarChar(val), pos, ok case 0x08: @@ -823,7 +823,7 @@ func (c *Conn) parseStmtArgs(data []byte, typ querypb.Type, pos int) (sqltypes.V } case sqltypes.Decimal, sqltypes.Text, sqltypes.Blob, sqltypes.VarChar, sqltypes.VarBinary, sqltypes.Char, sqltypes.Bit, sqltypes.Enum, sqltypes.Set, sqltypes.Geometry, sqltypes.Binary, sqltypes.TypeJSON: - val, pos, ok := readLenEncStringAsBytes(data, pos) + val, pos, ok := readLenEncStringAsBytesCopy(data, pos) return sqltypes.MakeTrusted(sqltypes.VarBinary, val), pos, ok default: return sqltypes.NULL, pos, false @@ -1063,7 +1063,7 @@ func (c *Conn) writePrepare(fld []*querypb.Field, prepare *PrepareData) error { } } - return c.flush() + return nil } func (c *Conn) writeBinaryRow(fields []*querypb.Field, row []sqltypes.Value) error { diff --git a/go/mysql/replication.go b/go/mysql/replication.go index e45b31d96e5..dcc4c5e20c2 100644 --- a/go/mysql/replication.go +++ b/go/mysql/replication.go @@ -67,3 +67,13 @@ func (c *Conn) WriteComBinlogDumpGTID(serverID uint32, binlogFilename string, bi } return nil } + +// SemiSyncExtensionLoaded checks if the semisync extension has been loaded. +// It should work for both MariaDB and MySQL. +func (c *Conn) SemiSyncExtensionLoaded() bool { + qr, err := c.ExecuteFetch("SHOW GLOBAL VARIABLES LIKE 'rpl_semi_sync%'", 10, false) + if err != nil { + return false + } + return len(qr.Rows) >= 1 +} diff --git a/go/mysql/replication_constants.go b/go/mysql/replication_constants.go index 690f028cbbd..51b8643ab32 100644 --- a/go/mysql/replication_constants.go +++ b/go/mysql/replication_constants.go @@ -189,10 +189,10 @@ const ( eAnonymousGTIDEvent = 34 ePreviousGTIDsEvent = 35 - // MySQL 5.7 events - eTransactionContextEvent = 36 - eViewChangeEvent = 37 - eXAPrepareLogEvent = 38 + // MySQL 5.7 events. Unused. + //eTransactionContextEvent = 36 + //eViewChangeEvent = 37 + //eXAPrepareLogEvent = 38 // MariaDB specific values. They start at 160. eMariaAnnotateRowsEvent = 160 diff --git a/go/mysql/server.go b/go/mysql/server.go index 213af75cb90..53e405b9f0c 100644 --- a/go/mysql/server.go +++ b/go/mysql/server.go @@ -23,6 +23,7 @@ import ( "strings" "time" + proxyproto "github.com/pires/go-proxyproto" "vitess.io/vitess/go/netutil" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/stats" @@ -37,7 +38,7 @@ import ( const ( // DefaultServerVersion is the default server version we're sending to the client. // Can be changed. - DefaultServerVersion = "5.5.10-Vitess" + DefaultServerVersion = "5.7.9-Vitess" // timing metric keys connectTimingKey = "Connect" @@ -54,6 +55,7 @@ var ( timings = stats.NewTimings("MysqlServerTimings", "MySQL server timings", "operation") connCount = stats.NewGauge("MysqlServerConnCount", "Active MySQL server connections") connAccept = stats.NewCounter("MysqlServerConnAccepted", "Connections accepted by MySQL server") + connRefuse = stats.NewCounter("MysqlServerConnRefused", "Connections refused by MySQL server") connSlow = stats.NewCounter("MysqlServerConnSlow", "Connections that took more than the configured mysql_slow_connect_warn_threshold to establish") connCountByTLSVer = stats.NewGaugesWithSingleLabel("MysqlServerConnCountByTLSVer", "Active MySQL server connections by TLS version", "tls") @@ -144,11 +146,11 @@ type Listener struct { // AllowClearTextWithoutTLS needs to be set for the // mysql_clear_password authentication method to be accepted // by the server when TLS is not in use. - AllowClearTextWithoutTLS bool + AllowClearTextWithoutTLS sync2.AtomicBool // SlowConnectWarnThreshold if non-zero specifies an amount of time // beyond which a warning is logged to identify the slow connection - SlowConnectWarnThreshold time.Duration + SlowConnectWarnThreshold sync2.AtomicDuration // The following parameters are changed by the Accept routine. @@ -184,11 +186,15 @@ func NewFromListener(l net.Listener, authServer AuthServer, handler Handler, con } // NewListener creates a new Listener. -func NewListener(protocol, address string, authServer AuthServer, handler Handler, connReadTimeout time.Duration, connWriteTimeout time.Duration) (*Listener, error) { +func NewListener(protocol, address string, authServer AuthServer, handler Handler, connReadTimeout time.Duration, connWriteTimeout time.Duration, proxyProtocol bool) (*Listener, error) { listener, err := net.Listen(protocol, address) if err != nil { return nil, err } + if proxyProtocol { + proxyListener := &proxyproto.Listener{Listener: listener} + return NewFromListener(proxyListener, authServer, handler, connReadTimeout, connWriteTimeout) + } return NewFromListener(listener, authServer, handler, connReadTimeout, connWriteTimeout) } @@ -243,6 +249,7 @@ func (l *Listener) Accept() { conn, err := l.listener.Accept() if err != nil { // Close() was probably called. + connRefuse.Add(1) return } @@ -272,9 +279,9 @@ func (l *Listener) handle(conn net.Conn, connectionID uint32, acceptTime time.Ti if x := recover(); x != nil { log.Errorf("mysql_server caught panic:\n%v\n%s", x, tb.Stack(4)) } - // We call flush here in case there's a premature return after + // We call endWriterBuffering here in case there's a premature return after // startWriterBuffering is called - c.flush() + c.endWriterBuffering() conn.Close() }() @@ -375,9 +382,8 @@ func (l *Listener) handle(conn net.Conn, connectionID uint32, acceptTime time.Ti if err != nil { return } - //lint:ignore SA4006 This line is required because the binary protocol requires padding with 0 - data := make([]byte, 21) - data = append(salt, byte(0x00)) + // The binary protocol requires padding with 0 + data := append(salt, byte(0x00)) if err := c.writeAuthSwitchRequest(MysqlNativePassword, data); err != nil { log.Errorf("Error writing auth switch packet for %s: %v", c, err) return @@ -403,7 +409,7 @@ func (l *Listener) handle(conn net.Conn, connectionID uint32, acceptTime time.Ti // The server wants to use something else, re-negotiate. // The negotiation happens in clear text. Let's check we can. - if !l.AllowClearTextWithoutTLS && c.Capabilities&CapabilityClientSSL == 0 { + if !l.AllowClearTextWithoutTLS.Get() && c.Capabilities&CapabilityClientSSL == 0 { c.writeErrorPacket(CRServerHandshakeErr, SSUnknownSQLState, "Cannot use clear text authentication over non-SSL connections.") return } @@ -446,7 +452,7 @@ func (l *Listener) handle(conn net.Conn, connectionID uint32, acceptTime time.Ti // Log a warning if it took too long to connect connectTime := time.Since(acceptTime) - if l.SlowConnectWarnThreshold != 0 && connectTime > l.SlowConnectWarnThreshold { + if threshold := l.SlowConnectWarnThreshold.Get(); threshold != 0 && connectTime > threshold { connSlow.Add(1) log.Warningf("Slow connection from %s: %v", c, connectTime) } @@ -483,6 +489,7 @@ func (l *Listener) isShutdown() bool { // It returns the salt data. func (c *Conn) writeHandshakeV10(serverVersion string, authServer AuthServer, enableTLS bool) ([]byte, error) { capabilities := CapabilityClientLongPassword | + CapabilityClientFoundRows | CapabilityClientLongFlag | CapabilityClientConnectWithDB | CapabilityClientProtocol41 | diff --git a/go/mysql/server_test.go b/go/mysql/server_test.go index 7fc9fddb1c0..863223296ce 100644 --- a/go/mysql/server_test.go +++ b/go/mysql/server_test.go @@ -24,9 +24,12 @@ import ( "os/exec" "path" "strings" + "sync" "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "golang.org/x/net/context" "vitess.io/vitess/go/sqltypes" @@ -64,13 +67,46 @@ var selectRowsResult = &sqltypes.Result{ } type testHandler struct { + mu sync.Mutex lastConn *Conn result *sqltypes.Result err error warnings uint16 } +func (th *testHandler) LastConn() *Conn { + th.mu.Lock() + defer th.mu.Unlock() + return th.lastConn +} + +func (th *testHandler) Result() *sqltypes.Result { + th.mu.Lock() + defer th.mu.Unlock() + return th.result +} + +func (th *testHandler) SetErr(err error) { + th.mu.Lock() + defer th.mu.Unlock() + th.err = err +} + +func (th *testHandler) Err() error { + th.mu.Lock() + defer th.mu.Unlock() + return th.err +} + +func (th *testHandler) SetWarnings(count uint16) { + th.mu.Lock() + defer th.mu.Unlock() + th.warnings = count +} + func (th *testHandler) NewConnection(c *Conn) { + th.mu.Lock() + defer th.mu.Unlock() th.lastConn = c } @@ -81,21 +117,21 @@ func (th *testHandler) ComInitDB(c *Conn, schemaName string) { } func (th *testHandler) ComQuery(c *Conn, query string, callback func(*sqltypes.Result) error) error { - if th.result != nil { - callback(th.result) + if result := th.Result(); result != nil { + callback(result) return nil } switch query { case "error": - return th.err + return th.Err() case "panic": panic("test panic attack!") case "select rows": callback(selectRowsResult) case "error after send": callback(selectRowsResult) - return th.err + return th.Err() case "insert": callback(&sqltypes.Result{ RowsAffected: 123, @@ -152,6 +188,19 @@ func (th *testHandler) ComQuery(c *Conn, query string, callback func(*sqltypes.R }, }, }) + case "50ms delay": + callback(&sqltypes.Result{ + Fields: []*querypb.Field{{ + Name: "result", + Type: querypb.Type_VARCHAR, + }}, + }) + time.Sleep(50 * time.Millisecond) + callback(&sqltypes.Result{ + Rows: [][]sqltypes.Value{{ + sqltypes.MakeTrusted(querypb.Type_VARCHAR, []byte("delayed")), + }}, + }) default: if strings.HasPrefix(query, benchmarkQueryPrefix) { callback(&sqltypes.Result{ @@ -187,6 +236,8 @@ func (th *testHandler) ComResetConnection(c *Conn) { } func (th *testHandler) WarningCount(c *Conn) uint16 { + th.mu.Lock() + defer th.mu.Unlock() return th.warnings } @@ -206,11 +257,12 @@ func getHostPort(t *testing.T, a net.Addr) (string, int) { func TestConnectionFromListener(t *testing.T) { th := &testHandler{} - authServer := NewAuthServerStatic() - authServer.Entries["user1"] = []*AuthServerStaticEntry{{ + authServer := NewAuthServerStatic("", "", 0) + authServer.entries["user1"] = []*AuthServerStaticEntry{{ Password: "password1", UserData: "userData1", }} + defer authServer.close() // Make sure we can create our own net.Listener for use with the mysql // listener listener, err := net.Listen("tcp", ":0") @@ -245,12 +297,13 @@ func TestConnectionFromListener(t *testing.T) { func TestConnectionWithoutSourceHost(t *testing.T) { th := &testHandler{} - authServer := NewAuthServerStatic() - authServer.Entries["user1"] = []*AuthServerStaticEntry{{ + authServer := NewAuthServerStatic("", "", 0) + authServer.entries["user1"] = []*AuthServerStaticEntry{{ Password: "password1", UserData: "userData1", }} - l, err := NewListener("tcp", ":0", authServer, th, 0, 0) + defer authServer.close() + l, err := NewListener("tcp", ":0", authServer, th, 0, 0, false) if err != nil { t.Fatalf("NewListener failed: %v", err) } @@ -277,17 +330,17 @@ func TestConnectionWithoutSourceHost(t *testing.T) { func TestConnectionWithSourceHost(t *testing.T) { th := &testHandler{} - authServer := NewAuthServerStatic() - - authServer.Entries["user1"] = []*AuthServerStaticEntry{ + authServer := NewAuthServerStatic("", "", 0) + authServer.entries["user1"] = []*AuthServerStaticEntry{ { Password: "password1", UserData: "userData1", SourceHost: "localhost", }, } + defer authServer.close() - l, err := NewListener("tcp", ":0", authServer, th, 0, 0) + l, err := NewListener("tcp", ":0", authServer, th, 0, 0, false) if err != nil { t.Fatalf("NewListener failed: %v", err) } @@ -314,17 +367,17 @@ func TestConnectionWithSourceHost(t *testing.T) { func TestConnectionUseMysqlNativePasswordWithSourceHost(t *testing.T) { th := &testHandler{} - authServer := NewAuthServerStatic() - - authServer.Entries["user1"] = []*AuthServerStaticEntry{ + authServer := NewAuthServerStatic("", "", 0) + authServer.entries["user1"] = []*AuthServerStaticEntry{ { MysqlNativePassword: "*9E128DA0C64A6FCCCDCFBDD0FC0A2C967C6DB36F", UserData: "userData1", SourceHost: "localhost", }, } + defer authServer.close() - l, err := NewListener("tcp", ":0", authServer, th, 0, 0) + l, err := NewListener("tcp", ":0", authServer, th, 0, 0, false) if err != nil { t.Fatalf("NewListener failed: %v", err) } @@ -351,15 +404,15 @@ func TestConnectionUseMysqlNativePasswordWithSourceHost(t *testing.T) { func TestConnectionUnixSocket(t *testing.T) { th := &testHandler{} - authServer := NewAuthServerStatic() - - authServer.Entries["user1"] = []*AuthServerStaticEntry{ + authServer := NewAuthServerStatic("", "", 0) + authServer.entries["user1"] = []*AuthServerStaticEntry{ { Password: "password1", UserData: "userData1", SourceHost: "localhost", }, } + defer authServer.close() unixSocket, err := ioutil.TempFile("", "mysql_vitess_test.sock") if err != nil { @@ -367,7 +420,7 @@ func TestConnectionUnixSocket(t *testing.T) { } os.Remove(unixSocket.Name()) - l, err := NewListener("unix", unixSocket.Name(), authServer, th, 0, 0) + l, err := NewListener("unix", unixSocket.Name(), authServer, th, 0, 0, false) if err != nil { t.Fatalf("NewListener failed: %v", err) } @@ -391,12 +444,13 @@ func TestConnectionUnixSocket(t *testing.T) { func TestClientFoundRows(t *testing.T) { th := &testHandler{} - authServer := NewAuthServerStatic() - authServer.Entries["user1"] = []*AuthServerStaticEntry{{ + authServer := NewAuthServerStatic("", "", 0) + authServer.entries["user1"] = []*AuthServerStaticEntry{{ Password: "password1", UserData: "userData1", }} - l, err := NewListener("tcp", ":0", authServer, th, 0, 0) + defer authServer.close() + l, err := NewListener("tcp", ":0", authServer, th, 0, 0, false) if err != nil { t.Fatalf("NewListener failed: %v", err) } @@ -418,9 +472,9 @@ func TestClientFoundRows(t *testing.T) { if err != nil { t.Fatal(err) } - foundRows := th.lastConn.Capabilities & CapabilityClientFoundRows + foundRows := th.LastConn().Capabilities & CapabilityClientFoundRows if foundRows != 0 { - t.Errorf("FoundRows flag: %x, second bit must be 0", th.lastConn.Capabilities) + t.Errorf("FoundRows flag: %x, second bit must be 0", th.LastConn().Capabilities) } c.Close() if !c.IsClosed() { @@ -433,9 +487,9 @@ func TestClientFoundRows(t *testing.T) { if err != nil { t.Fatal(err) } - foundRows = th.lastConn.Capabilities & CapabilityClientFoundRows + foundRows = th.LastConn().Capabilities & CapabilityClientFoundRows if foundRows == 0 { - t.Errorf("FoundRows flag: %x, second bit must be set", th.lastConn.Capabilities) + t.Errorf("FoundRows flag: %x, second bit must be set", th.LastConn().Capabilities) } c.Close() } @@ -448,12 +502,13 @@ func TestConnCounts(t *testing.T) { user := "anotherNotYetConnectedUser1" passwd := "password1" - authServer := NewAuthServerStatic() - authServer.Entries[user] = []*AuthServerStaticEntry{{ + authServer := NewAuthServerStatic("", "", 0) + authServer.entries[user] = []*AuthServerStaticEntry{{ Password: passwd, UserData: "userData1", }} - l, err := NewListener("tcp", ":0", authServer, th, 0, 0) + defer authServer.close() + l, err := NewListener("tcp", ":0", authServer, th, 0, 0, false) if err != nil { t.Fatalf("NewListener failed: %v", err) } @@ -520,15 +575,17 @@ func checkCountsForUser(t *testing.T, user string, expected int64) { func TestServer(t *testing.T) { th := &testHandler{} - authServer := NewAuthServerStatic() - authServer.Entries["user1"] = []*AuthServerStaticEntry{{ + authServer := NewAuthServerStatic("", "", 0) + authServer.entries["user1"] = []*AuthServerStaticEntry{{ Password: "password1", UserData: "userData1", }} - l, err := NewListener("tcp", ":0", authServer, th, 0, 0) + defer authServer.close() + l, err := NewListener("tcp", ":0", authServer, th, 0, 0, false) if err != nil { t.Fatalf("NewListener failed: %v", err) } + l.SlowConnectWarnThreshold.Set(time.Duration(time.Nanosecond * 1)) defer l.Close() go l.Accept() @@ -545,11 +602,10 @@ func TestServer(t *testing.T) { initialTimingCounts := timings.Counts() initialConnAccept := connAccept.Get() initialConnSlow := connSlow.Get() - - l.SlowConnectWarnThreshold = time.Duration(time.Nanosecond * 1) + initialconnRefuse := connRefuse.Get() // Run an 'error' command. - th.err = NewSQLError(ERUnknownComError, SSUnknownComError, "forced query error") + th.SetErr(NewSQLError(ERUnknownComError, SSUnknownComError, "forced query error")) output, ok := runMysql(t, params, "error") if ok { t.Fatalf("mysql should have failed: %v", output) @@ -567,6 +623,9 @@ func TestServer(t *testing.T) { if connSlow.Get()-initialConnSlow != 1 { t.Errorf("Expected ConnSlow delta=1, got %d", connSlow.Get()-initialConnSlow) } + if connRefuse.Get()-initialconnRefuse != 0 { + t.Errorf("Expected connRefuse delta=0, got %d", connRefuse.Get()-initialconnRefuse) + } expectedTimingDeltas := map[string]int64{ "All": 2, @@ -583,7 +642,7 @@ func TestServer(t *testing.T) { } // Set the slow connect threshold to something high that we don't expect to trigger - l.SlowConnectWarnThreshold = time.Duration(time.Second * 1) + l.SlowConnectWarnThreshold.Set(time.Duration(time.Second * 1)) // Run a 'panic' command, other side should panic, recover and // close the connection. @@ -604,6 +663,9 @@ func TestServer(t *testing.T) { if connSlow.Get()-initialConnSlow != 1 { t.Errorf("Expected ConnSlow delta=1, got %d", connSlow.Get()-initialConnSlow) } + if connRefuse.Get()-initialconnRefuse != 0 { + t.Errorf("Expected connRefuse delta=0, got %d", connRefuse.Get()-initialconnRefuse) + } // Run a 'select rows' command with results. output, ok = runMysql(t, params, "select rows") @@ -620,7 +682,7 @@ func TestServer(t *testing.T) { } // Run a 'select rows' command with warnings - th.warnings = 13 + th.SetWarnings(13) output, ok = runMysql(t, params, "select rows") if !ok { t.Fatalf("mysql failed: %v", output) @@ -631,11 +693,11 @@ func TestServer(t *testing.T) { !strings.Contains(output, "13 warnings") { t.Errorf("Unexpected output for 'select rows': %v", output) } - th.warnings = 0 + th.SetWarnings(0) // If there's an error after streaming has started, // we should get a 2013 - th.err = NewSQLError(ERUnknownComError, SSUnknownComError, "forced error after send") + th.SetErr(NewSQLError(ERUnknownComError, SSUnknownComError, "forced error after send")) output, ok = runMysql(t, params, "error after send") if ok { t.Fatalf("mysql should have failed: %v", output) @@ -719,20 +781,16 @@ func TestServer(t *testing.T) { // TestClearTextServer creates a Server that needs clear text // passwords from the client. func TestClearTextServer(t *testing.T) { - // If the database we're using is MariaDB, the client - // is also the MariaDB client, that does support - // clear text by default. - isMariaDB := os.Getenv("MYSQL_FLAVOR") == "MariaDB" - th := &testHandler{} - authServer := NewAuthServerStatic() - authServer.Entries["user1"] = []*AuthServerStaticEntry{{ + authServer := NewAuthServerStatic("", "", 0) + authServer.entries["user1"] = []*AuthServerStaticEntry{{ Password: "password1", UserData: "userData1", }} - authServer.Method = MysqlClearPassword - l, err := NewListener("tcp", ":0", authServer, th, 0, 0) + authServer.method = MysqlClearPassword + defer authServer.close() + l, err := NewListener("tcp", ":0", authServer, th, 0, 0, false) if err != nil { t.Fatalf("NewListener failed: %v", err) } @@ -741,6 +799,9 @@ func TestClearTextServer(t *testing.T) { host, port := getHostPort(t, l.Addr()) + version, _ := runMysql(t, nil, "--version") + isMariaDB := strings.Contains(version, "MariaDB") + // Setup the right parameters. params := &ConnParams{ Host: host, @@ -752,7 +813,7 @@ func TestClearTextServer(t *testing.T) { // Run a 'select rows' command with results. This should fail // as clear text is not enabled by default on the client // (except MariaDB). - l.AllowClearTextWithoutTLS = true + l.AllowClearTextWithoutTLS.Set(true) sql := "select rows" output, ok := runMysql(t, params, sql) if ok { @@ -772,7 +833,7 @@ func TestClearTextServer(t *testing.T) { } // Now enable clear text plugin in client, but server requires SSL. - l.AllowClearTextWithoutTLS = false + l.AllowClearTextWithoutTLS.Set(false) if !isMariaDB { sql = enableCleartextPluginPrefix + sql } @@ -785,7 +846,7 @@ func TestClearTextServer(t *testing.T) { } // Now enable clear text plugin, it should now work. - l.AllowClearTextWithoutTLS = true + l.AllowClearTextWithoutTLS.Set(true) output, ok = runMysql(t, params, sql) if !ok { t.Fatalf("mysql failed: %v", output) @@ -811,17 +872,18 @@ func TestClearTextServer(t *testing.T) { func TestDialogServer(t *testing.T) { th := &testHandler{} - authServer := NewAuthServerStatic() - authServer.Entries["user1"] = []*AuthServerStaticEntry{{ + authServer := NewAuthServerStatic("", "", 0) + authServer.entries["user1"] = []*AuthServerStaticEntry{{ Password: "password1", UserData: "userData1", }} - authServer.Method = MysqlDialog - l, err := NewListener("tcp", ":0", authServer, th, 0, 0) + authServer.method = MysqlDialog + defer authServer.close() + l, err := NewListener("tcp", ":0", authServer, th, 0, 0, false) if err != nil { t.Fatalf("NewListener failed: %v", err) } - l.AllowClearTextWithoutTLS = true + l.AllowClearTextWithoutTLS.Set(true) defer l.Close() go l.Accept() @@ -855,16 +917,17 @@ func TestDialogServer(t *testing.T) { func TestTLSServer(t *testing.T) { th := &testHandler{} - authServer := NewAuthServerStatic() - authServer.Entries["user1"] = []*AuthServerStaticEntry{{ + authServer := NewAuthServerStatic("", "", 0) + authServer.entries["user1"] = []*AuthServerStaticEntry{{ Password: "password1", }} + defer authServer.close() // Create the listener, so we can get its host. // Below, we are enabling --ssl-verify-server-cert, which adds // a check that the common name of the certificate matches the // server host name we connect to. - l, err := NewListener("tcp", ":0", authServer, th, 0, 0) + l, err := NewListener("tcp", ":0", authServer, th, 0, 0, false) if err != nil { t.Fatalf("NewListener failed: %v", err) } @@ -957,16 +1020,17 @@ func TestTLSServer(t *testing.T) { func TestTLSRequired(t *testing.T) { th := &testHandler{} - authServer := NewAuthServerStatic() - authServer.Entries["user1"] = []*AuthServerStaticEntry{{ + authServer := NewAuthServerStatic("", "", 0) + authServer.entries["user1"] = []*AuthServerStaticEntry{{ Password: "password1", }} + defer authServer.close() // Create the listener, so we can get its host. // Below, we are enabling --ssl-verify-server-cert, which adds // a check that the common name of the certificate matches the // server host name we connect to. - l, err := NewListener("tcp", ":0", authServer, th, 0, 0) + l, err := NewListener("tcp", ":0", authServer, th, 0, 0, false) if err != nil { t.Fatalf("NewListener failed: %v", err) } @@ -1047,12 +1111,13 @@ func checkCountForTLSVer(t *testing.T, version string, expected int64) { func TestErrorCodes(t *testing.T) { th := &testHandler{} - authServer := NewAuthServerStatic() - authServer.Entries["user1"] = []*AuthServerStaticEntry{{ + authServer := NewAuthServerStatic("", "", 0) + authServer.entries["user1"] = []*AuthServerStaticEntry{{ Password: "password1", UserData: "userData1", }} - l, err := NewListener("tcp", ":0", authServer, th, 0, 0) + defer authServer.close() + l, err := NewListener("tcp", ":0", authServer, th, 0, 0, false) if err != nil { t.Fatalf("NewListener failed: %v", err) } @@ -1124,7 +1189,7 @@ func TestErrorCodes(t *testing.T) { } for _, test := range tests { - th.err = NewSQLErrorFromError(test.err) + th.SetErr(NewSQLErrorFromError(test.err)) result, err := client.ExecuteFetch("error", 100, false) if err == nil { t.Fatalf("mysql should have failed but returned: %v", result) @@ -1170,30 +1235,34 @@ func runMysql(t *testing.T, params *ConnParams, command string) (string, bool) { command = command[len(enableCleartextPluginPrefix):] args = append(args, "--enable-cleartext-plugin") } - args = append(args, "-e", command) - if params.UnixSocket != "" { - args = append(args, "-S", params.UnixSocket) + if command == "--version" { + args = append(args, command) } else { - args = append(args, - "-h", params.Host, - "-P", fmt.Sprintf("%v", params.Port)) - } - if params.Uname != "" { - args = append(args, "-u", params.Uname) - } - if params.Pass != "" { - args = append(args, "-p"+params.Pass) - } - if params.DbName != "" { - args = append(args, "-D", params.DbName) - } - if params.Flags&CapabilityClientSSL > 0 { - args = append(args, - "--ssl", - "--ssl-ca", params.SslCa, - "--ssl-cert", params.SslCert, - "--ssl-key", params.SslKey, - "--ssl-verify-server-cert") + args = append(args, "-e", command) + if params.UnixSocket != "" { + args = append(args, "-S", params.UnixSocket) + } else { + args = append(args, + "-h", params.Host, + "-P", fmt.Sprintf("%v", params.Port)) + } + if params.Uname != "" { + args = append(args, "-u", params.Uname) + } + if params.Pass != "" { + args = append(args, "-p"+params.Pass) + } + if params.DbName != "" { + args = append(args, "-D", params.DbName) + } + if params.Flags&CapabilityClientSSL > 0 { + args = append(args, + "--ssl", + "--ssl-ca", params.SslCa, + "--ssl-cert", params.SslCert, + "--ssl-key", params.SslKey, + "--ssl-verify-server-cert") + } } env := []string{ "LD_LIBRARY_PATH=" + path.Join(dir, "lib/mysql"), @@ -1230,12 +1299,13 @@ func binaryPath(root, binary string) (string, error) { func TestListenerShutdown(t *testing.T) { th := &testHandler{} - authServer := NewAuthServerStatic() - authServer.Entries["user1"] = []*AuthServerStaticEntry{{ + authServer := NewAuthServerStatic("", "", 0) + authServer.entries["user1"] = []*AuthServerStaticEntry{{ Password: "password1", UserData: "userData1", }} - l, err := NewListener("tcp", ":0", authServer, th, 0, 0) + defer authServer.close() + l, err := NewListener("tcp", ":0", authServer, th, 0, 0, false) if err != nil { t.Fatalf("NewListener failed: %v", err) } @@ -1251,6 +1321,7 @@ func TestListenerShutdown(t *testing.T) { Uname: "user1", Pass: "password1", } + initialconnRefuse := connRefuse.Get() ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -1266,6 +1337,10 @@ func TestListenerShutdown(t *testing.T) { l.Shutdown() + if connRefuse.Get()-initialconnRefuse != 1 { + t.Errorf("Expected connRefuse delta=1, got %d", connRefuse.Get()-initialconnRefuse) + } + if err := conn.Ping(); err != nil { sqlErr, ok := err.(*SQLError) if !ok { @@ -1320,3 +1395,52 @@ func TestParseConnAttrs(t *testing.T) { } } } + +func TestServerFlush(t *testing.T) { + defer func(saved time.Duration) { *mysqlServerFlushDelay = saved }(*mysqlServerFlushDelay) + *mysqlServerFlushDelay = 10 * time.Millisecond + + th := &testHandler{} + + l, err := NewListener("tcp", ":0", &AuthServerNone{}, th, 0, 0, false) + require.NoError(t, err) + defer l.Close() + go l.Accept() + + host, port := getHostPort(t, l.Addr()) + params := &ConnParams{ + Host: host, + Port: port, + } + + c, err := Connect(context.Background(), params) + require.NoError(t, err) + defer c.Close() + + start := time.Now() + err = c.ExecuteStreamFetch("50ms delay") + require.NoError(t, err) + + flds, err := c.Fields() + require.NoError(t, err) + if duration, want := time.Since(start), 20*time.Millisecond; duration < *mysqlServerFlushDelay || duration > want { + t.Errorf("duration: %v, want between %v and %v", duration, *mysqlServerFlushDelay, want) + } + want1 := []*querypb.Field{{ + Name: "result", + Type: querypb.Type_VARCHAR, + }} + assert.Equal(t, want1, flds) + + row, err := c.FetchNext() + require.NoError(t, err) + if duration, want := time.Since(start), 50*time.Millisecond; duration < want { + t.Errorf("duration: %v, want > %v", duration, want) + } + want2 := []sqltypes.Value{sqltypes.MakeTrusted(querypb.Type_VARCHAR, []byte("delayed"))} + assert.Equal(t, want2, row) + + row, err = c.FetchNext() + require.NoError(t, err) + assert.Nil(t, row) +} diff --git a/go/netutil/netutil.go b/go/netutil/netutil.go index a97be114c81..937e2b46ced 100644 --- a/go/netutil/netutil.go +++ b/go/netutil/netutil.go @@ -154,7 +154,7 @@ func FullyQualifiedHostname() (string, error) { // 127.0.0.1 localhost.localdomain localhost // If the FQDN isn't returned by this function, check the order in the entry // in your /etc/hosts file. - return strings.TrimRight(resolvedHostnames[0], "."), nil + return strings.TrimSuffix(resolvedHostnames[0], "."), nil } // FullyQualifiedHostnameOrPanic is the same as FullyQualifiedHostname diff --git a/go/pools/resource_pool_test.go b/go/pools/resource_pool_flaky_test.go similarity index 100% rename from go/pools/resource_pool_test.go rename to go/pools/resource_pool_flaky_test.go diff --git a/go/proc/proc_flaky_test.go b/go/proc/proc_flaky_test.go index 3058b44859e..4c9d6aa6c2e 100644 --- a/go/proc/proc_flaky_test.go +++ b/go/proc/proc_flaky_test.go @@ -28,6 +28,8 @@ import ( "syscall" "testing" "time" + + "github.com/stretchr/testify/require" ) func TestRestart(t *testing.T) { @@ -65,19 +67,13 @@ func testLaunch(t *testing.T) { cmd2 := launchServer(t, port, 2) defer cmd2.Process.Kill() err = cmd1.Wait() - if err != nil { - t.Error(err) - } + require.NoError(t, err) testPid(t, port, cmd2.Process.Pid) err = syscall.Kill(cmd2.Process.Pid, syscall.SIGTERM) - if err != nil { - t.Error(err) - } + require.NoError(t, err) err = cmd2.Wait() - if err != nil { - t.Error(err) - } + require.NoError(t, err) } func launchServer(t *testing.T, port string, num int) *exec.Cmd { diff --git a/go/sqltypes/bind_variables_test.go b/go/sqltypes/bind_variables_test.go index d5559d07227..73fbd754485 100644 --- a/go/sqltypes/bind_variables_test.go +++ b/go/sqltypes/bind_variables_test.go @@ -22,6 +22,7 @@ import ( "testing" "github.com/golang/protobuf/proto" + "github.com/stretchr/testify/require" querypb "vitess.io/vitess/go/vt/proto/query" ) @@ -524,9 +525,7 @@ func TestValidateBindVariable(t *testing.T) { func TestBindVariableToValue(t *testing.T) { v, err := BindVariableToValue(Int64BindVariable(1)) - if err != nil { - t.Error(err) - } + require.NoError(t, err) want := MakeTrusted(querypb.Type_INT64, []byte("1")) if !reflect.DeepEqual(v, want) { t.Errorf("BindVarToValue(1): %v, want %v", v, want) diff --git a/go/stats/counters.go b/go/stats/counters.go index 6307cf10f2b..46e9b8f904c 100644 --- a/go/stats/counters.go +++ b/go/stats/counters.go @@ -19,104 +19,70 @@ package stats import ( "bytes" "fmt" + "strings" "sync" - "sync/atomic" ) // counters is similar to expvar.Map, except that it doesn't allow floats. // It is used to build CountersWithSingleLabel and GaugesWithSingleLabel. type counters struct { - // mu only protects adding and retrieving the value (*int64) from the - // map. - // The modification to the actual number (int64) must be done with - // atomic funcs. - // If a value for a given name already exists in the map, we only have - // to use a read-lock to retrieve it. This is an important performance - // optimizations because it allows to concurrently increment a counter. - mu sync.RWMutex - counts map[string]*int64 - help string + mu sync.Mutex + counts map[string]int64 + + help string } -// String implements the expvar.Var interface. func (c *counters) String() string { - b := bytes.NewBuffer(make([]byte, 0, 4096)) - - c.mu.RLock() - defer c.mu.RUnlock() + c.mu.Lock() + defer c.mu.Unlock() + b := &strings.Builder{} fmt.Fprintf(b, "{") - firstValue := true - for k, a := range c.counts { - if firstValue { - firstValue = false - } else { - fmt.Fprintf(b, ", ") - } - fmt.Fprintf(b, "%q: %v", k, atomic.LoadInt64(a)) + prefix := "" + for k, v := range c.counts { + fmt.Fprintf(b, "%s%q: %v", prefix, k, v) + prefix = ", " } fmt.Fprintf(b, "}") return b.String() } -func (c *counters) getValueAddr(name string) *int64 { - c.mu.RLock() - a, ok := c.counts[name] - c.mu.RUnlock() - - if ok { - return a - } - +func (c *counters) add(name string, value int64) { c.mu.Lock() defer c.mu.Unlock() - // we need to check the existence again - // as it may be created by other goroutine. - a, ok = c.counts[name] - if ok { - return a - } - a = new(int64) - c.counts[name] = a - return a + c.counts[name] = c.counts[name] + value } -// Add adds a value to a named counter. -func (c *counters) Add(name string, value int64) { - a := c.getValueAddr(name) - atomic.AddInt64(a, value) +func (c *counters) set(name string, value int64) { + c.mu.Lock() + defer c.mu.Unlock() + c.counts[name] = value } -// ResetAll resets all counter values and clears all keys. -func (c *counters) ResetAll() { +func (c *counters) reset() { c.mu.Lock() defer c.mu.Unlock() - c.counts = make(map[string]*int64) + c.counts = make(map[string]int64) } -// ZeroAll resets all counter values to zero +// ZeroAll zeroes out all values func (c *counters) ZeroAll() { c.mu.Lock() defer c.mu.Unlock() - for _, a := range c.counts { - atomic.StoreInt64(a, int64(0)) - } -} -// Reset resets a specific counter value to 0. -func (c *counters) Reset(name string) { - a := c.getValueAddr(name) - atomic.StoreInt64(a, int64(0)) + for k := range c.counts { + c.counts[k] = 0 + } } // Counts returns a copy of the Counters' map. func (c *counters) Counts() map[string]int64 { - c.mu.RLock() - defer c.mu.RUnlock() + c.mu.Lock() + defer c.mu.Unlock() counts := make(map[string]int64, len(c.counts)) - for k, a := range c.counts { - counts[k] = atomic.LoadInt64(a) + for k, v := range c.counts { + counts[k] = v } return counts } @@ -131,7 +97,8 @@ func (c *counters) Help() string { // It provides a Counts method which can be used for tracking rates. type CountersWithSingleLabel struct { counters - label string + label string + labelCombined bool } // NewCountersWithSingleLabel create a new Counters instance. @@ -143,14 +110,19 @@ type CountersWithSingleLabel struct { func NewCountersWithSingleLabel(name, help, label string, tags ...string) *CountersWithSingleLabel { c := &CountersWithSingleLabel{ counters: counters{ - counts: make(map[string]*int64), + counts: make(map[string]int64), help: help, }, - label: label, + label: label, + labelCombined: IsDimensionCombined(label), } - for _, tag := range tags { - c.counts[tag] = new(int64) + if c.labelCombined { + c.counts[StatsAllStr] = 0 + } else { + for _, tag := range tags { + c.counts[tag] = 0 + } } if name != "" { publish(name, c) @@ -168,13 +140,23 @@ func (c *CountersWithSingleLabel) Add(name string, value int64) { if value < 0 { logCounterNegative.Warningf("Adding a negative value to a counter, %v should be a gauge instead", c) } - a := c.getValueAddr(name) - atomic.AddInt64(a, value) + if c.labelCombined { + name = StatsAllStr + } + c.counters.add(name, value) +} + +// Reset resets the value for the name. +func (c *CountersWithSingleLabel) Reset(name string) { + if c.labelCombined { + name = StatsAllStr + } + c.counters.set(name, 0) } // ResetAll clears the counters func (c *CountersWithSingleLabel) ResetAll() { - c.counters.ResetAll() + c.counters.reset() } // CountersWithMultiLabels is a multidimensional counters implementation. @@ -182,7 +164,8 @@ func (c *CountersWithSingleLabel) ResetAll() { // label value where all label values are joined with ".". type CountersWithMultiLabels struct { counters - labels []string + labels []string + combinedLabels []bool } // NewCountersWithMultiLabels creates a new CountersWithMultiLabels @@ -190,9 +173,13 @@ type CountersWithMultiLabels struct { func NewCountersWithMultiLabels(name, help string, labels []string) *CountersWithMultiLabels { t := &CountersWithMultiLabels{ counters: counters{ - counts: make(map[string]*int64), + counts: make(map[string]int64), help: help}, - labels: labels, + labels: labels, + combinedLabels: make([]bool, len(labels)), + } + for i, label := range labels { + t.combinedLabels[i] = IsDimensionCombined(label) } if name != "" { publish(name, t) @@ -215,8 +202,7 @@ func (mc *CountersWithMultiLabels) Add(names []string, value int64) { if value < 0 { logCounterNegative.Warningf("Adding a negative value to a counter, %v should be a gauge instead", mc) } - - mc.counters.Add(safeJoinLabels(names), value) + mc.counters.add(safeJoinLabels(names, mc.combinedLabels), value) } // Reset resets the value of a named counter back to 0. @@ -226,7 +212,12 @@ func (mc *CountersWithMultiLabels) Reset(names []string) { panic("CountersWithMultiLabels: wrong number of values in Reset") } - mc.counters.Reset(safeJoinLabels(names)) + mc.counters.set(safeJoinLabels(names, mc.combinedLabels), 0) +} + +// ResetAll clears the counters +func (mc *CountersWithMultiLabels) ResetAll() { + mc.counters.reset() } // Counts returns a copy of the Counters' map. @@ -317,7 +308,7 @@ func NewGaugesWithSingleLabel(name, help, label string, tags ...string) *GaugesW g := &GaugesWithSingleLabel{ CountersWithSingleLabel: CountersWithSingleLabel{ counters: counters{ - counts: make(map[string]*int64), + counts: make(map[string]int64), help: help, }, label: label, @@ -325,7 +316,7 @@ func NewGaugesWithSingleLabel(name, help, label string, tags ...string) *GaugesW } for _, tag := range tags { - g.counts[tag] = new(int64) + g.counts[tag] = 0 } if name != "" { publish(name, g) @@ -335,14 +326,7 @@ func NewGaugesWithSingleLabel(name, help, label string, tags ...string) *GaugesW // Set sets the value of a named gauge. func (g *GaugesWithSingleLabel) Set(name string, value int64) { - a := g.getValueAddr(name) - atomic.StoreInt64(a, value) -} - -// Add adds a value to a named gauge. -func (g *GaugesWithSingleLabel) Add(name string, value int64) { - a := g.getValueAddr(name) - atomic.AddInt64(a, value) + g.counters.set(name, value) } // GaugesWithMultiLabels is a CountersWithMultiLabels implementation where @@ -357,7 +341,7 @@ func NewGaugesWithMultiLabels(name, help string, labels []string) *GaugesWithMul t := &GaugesWithMultiLabels{ CountersWithMultiLabels: CountersWithMultiLabels{ counters: counters{ - counts: make(map[string]*int64), + counts: make(map[string]int64), help: help, }, labels: labels, @@ -375,18 +359,7 @@ func (mg *GaugesWithMultiLabels) Set(names []string, value int64) { if len(names) != len(mg.CountersWithMultiLabels.labels) { panic("GaugesWithMultiLabels: wrong number of values in Set") } - a := mg.getValueAddr(safeJoinLabels(names)) - atomic.StoreInt64(a, value) -} - -// Add adds a value to a named gauge. -// len(names) must be equal to len(Labels). -func (mg *GaugesWithMultiLabels) Add(names []string, value int64) { - if len(names) != len(mg.labels) { - panic("CountersWithMultiLabels: wrong number of values in Add") - } - - mg.counters.Add(safeJoinLabels(names), value) + mg.counters.set(safeJoinLabels(names, nil), value) } // GaugesFuncWithMultiLabels is a wrapper around CountersFuncWithMultiLabels diff --git a/go/stats/counters_test.go b/go/stats/counters_test.go index a9ea7485604..03c3b244345 100644 --- a/go/stats/counters_test.go +++ b/go/stats/counters_test.go @@ -24,6 +24,8 @@ import ( "strings" "testing" "time" + + "github.com/stretchr/testify/assert" ) func TestCounters(t *testing.T) { @@ -240,3 +242,32 @@ func TestCountersFuncWithMultiLabels_Hook(t *testing.T) { t.Errorf("want %#v, got %#v", v, gotv) } } + +func TestCountersCombineDimension(t *testing.T) { + clear() + // Empty labels shouldn't be combined. + c0 := NewCountersWithSingleLabel("counter_combine_dim0", "help", "") + c0.Add("c1", 1) + assert.Equal(t, `{"c1": 1}`, c0.String()) + + clear() + *combineDimensions = "a,c" + + c1 := NewCountersWithSingleLabel("counter_combine_dim1", "help", "label") + c1.Add("c1", 1) + assert.Equal(t, `{"c1": 1}`, c1.String()) + + c2 := NewCountersWithSingleLabel("counter_combine_dim2", "help", "a") + c2.Add("c1", 1) + assert.Equal(t, `{"all": 1}`, c2.String()) + + c3 := NewCountersWithSingleLabel("counter_combine_dim3", "help", "a") + assert.Equal(t, `{"all": 0}`, c3.String()) + + // Anything under "a" and "c" should get reported under a consolidated "all" value + // instead of the specific supplied values. + c4 := NewCountersWithMultiLabels("counter_combine_dim4", "help", []string{"a", "b", "c"}) + c4.Add([]string{"c1", "c2", "c3"}, 1) + c4.Add([]string{"c4", "c2", "c5"}, 1) + assert.Equal(t, `{"all.c2.all": 2}`, c4.String()) +} diff --git a/go/stats/export.go b/go/stats/export.go index 54aa38d94d7..b61c7278118 100644 --- a/go/stats/export.go +++ b/go/stats/export.go @@ -33,6 +33,7 @@ import ( "flag" "fmt" "strconv" + "strings" "sync" "time" @@ -42,6 +43,11 @@ import ( var emitStats = flag.Bool("emit_stats", false, "true iff we should emit stats to push-based monitoring/stats backends") var statsEmitPeriod = flag.Duration("stats_emit_period", time.Duration(60*time.Second), "Interval between emitting stats to all registered backends") var statsBackend = flag.String("stats_backend", "", "The name of the registered push-based monitoring/stats backend to use") +var combineDimensions = flag.String("stats_combine_dimensions", "", `List of dimensions to be combined into a single "all" value in exported stats vars`) +var dropVariables = flag.String("stats_drop_variables", "", `Variables to be dropped from the list of exported variables.`) + +// StatsAllStr is the consolidated name if a dimension gets combined. +const StatsAllStr = "all" // NewVarHook is the type of a hook to export variables in a different way type NewVarHook func(name string, v expvar.Var) @@ -71,6 +77,9 @@ func (vg *varGroup) register(nvh NewVarHook) { } func (vg *varGroup) publish(name string, v expvar.Var) { + if isVarDropped(name) { + return + } vg.Lock() defer vg.Unlock() @@ -247,3 +256,64 @@ func stringMapToString(m map[string]string) string { fmt.Fprintf(b, "}") return b.String() } + +var ( + varsMu sync.Mutex + combinedDimensions map[string]bool + droppedVars map[string]bool +) + +// IsDimensionCombined returns true if the specified dimension should be combined. +func IsDimensionCombined(name string) bool { + varsMu.Lock() + defer varsMu.Unlock() + + if combinedDimensions == nil { + dims := strings.Split(*combineDimensions, ",") + combinedDimensions = make(map[string]bool, len(dims)) + for _, dim := range dims { + if dim == "" { + continue + } + combinedDimensions[dim] = true + } + } + return combinedDimensions[name] +} + +// safeJoinLabels joins the label values with ".", but first replaces any existing +// "." characters in the labels with the proper replacement, to avoid issues parsing +// them apart later. The function also replaces specific label values with "all" +// if a dimenstion is marked as true in combinedLabels. +func safeJoinLabels(labels []string, combinedLabels []bool) string { + sanitizedLabels := make([]string, len(labels)) + for idx, label := range labels { + if combinedLabels != nil && combinedLabels[idx] { + sanitizedLabels[idx] = StatsAllStr + } else { + sanitizedLabels[idx] = safeLabel(label) + } + } + return strings.Join(sanitizedLabels, ".") +} + +func safeLabel(label string) string { + return strings.Replace(label, ".", "_", -1) +} + +func isVarDropped(name string) bool { + varsMu.Lock() + defer varsMu.Unlock() + + if droppedVars == nil { + dims := strings.Split(*dropVariables, ",") + droppedVars = make(map[string]bool, len(dims)) + for _, dim := range dims { + if dim == "" { + continue + } + droppedVars[dim] = true + } + } + return droppedVars[name] +} diff --git a/go/stats/export_test.go b/go/stats/export_test.go index 86c07064a7d..a765af1ee50 100644 --- a/go/stats/export_test.go +++ b/go/stats/export_test.go @@ -24,6 +24,10 @@ import ( func clear() { defaultVarGroup.vars = make(map[string]expvar.Var) defaultVarGroup.newVarHook = nil + *combineDimensions = "" + *dropVariables = "" + combinedDimensions = nil + droppedVars = nil } func TestNoHook(t *testing.T) { @@ -116,3 +120,12 @@ func TestPublishFunc(t *testing.T) { t.Errorf("want %v, got %#v", f(), gotv()) } } + +func TestDropVariable(t *testing.T) { + clear() + *dropVariables = "dropTest" + + // This should not panic. + _ = NewGaugesWithSingleLabel("dropTest", "help", "label") + _ = NewGaugesWithSingleLabel("dropTest", "help", "label") +} diff --git a/go/stats/prometheusbackend/collectors.go b/go/stats/prometheusbackend/collectors.go index 1303520f61c..8c3731432b9 100644 --- a/go/stats/prometheusbackend/collectors.go +++ b/go/stats/prometheusbackend/collectors.go @@ -21,6 +21,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "vitess.io/vitess/go/stats" + "vitess.io/vitess/go/vt/log" ) type metricFuncCollector struct { @@ -40,6 +41,7 @@ func newMetricFuncCollector(v stats.Variable, name string, vt prometheus.ValueTy nil), vt: vt} + // Will panic if it fails prometheus.MustRegister(collector) } @@ -50,7 +52,12 @@ func (mc *metricFuncCollector) Describe(ch chan<- *prometheus.Desc) { // Collect implements Collector. func (mc *metricFuncCollector) Collect(ch chan<- prometheus.Metric) { - ch <- prometheus.MustNewConstMetric(mc.desc, mc.vt, float64(mc.f())) + metric, err := prometheus.NewConstMetric(mc.desc, mc.vt, float64(mc.f())) + if err != nil { + log.Errorf("Error adding metric: %s", mc.desc) + } else { + ch <- metric + } } // countersWithSingleLabelCollector collects stats.CountersWithSingleLabel. @@ -81,11 +88,12 @@ func (c *countersWithSingleLabelCollector) Describe(ch chan<- *prometheus.Desc) // Collect implements Collector. func (c *countersWithSingleLabelCollector) Collect(ch chan<- prometheus.Metric) { for tag, val := range c.counters.Counts() { - ch <- prometheus.MustNewConstMetric( - c.desc, - c.vt, - float64(val), - tag) + metric, err := prometheus.NewConstMetric(c.desc, c.vt, float64(val), tag) + if err != nil { + log.Errorf("Error adding metric: %s", c.desc) + } else { + ch <- metric + } } } @@ -117,11 +125,12 @@ func (g *gaugesWithSingleLabelCollector) Describe(ch chan<- *prometheus.Desc) { // Collect implements Collector. func (g *gaugesWithSingleLabelCollector) Collect(ch chan<- prometheus.Metric) { for tag, val := range g.gauges.Counts() { - ch <- prometheus.MustNewConstMetric( - g.desc, - g.vt, - float64(val), - tag) + metric, err := prometheus.NewConstMetric(g.desc, g.vt, float64(val), tag) + if err != nil { + log.Errorf("Error adding metric: %s", g.desc) + } else { + ch <- metric + } } } @@ -153,7 +162,12 @@ func (c *metricWithMultiLabelsCollector) Collect(ch chan<- prometheus.Metric) { for lvs, val := range c.cml.Counts() { labelValues := strings.Split(lvs, ".") value := float64(val) - ch <- prometheus.MustNewConstMetric(c.desc, prometheus.CounterValue, value, labelValues...) + metric, err := prometheus.NewConstMetric(c.desc, prometheus.CounterValue, value, labelValues...) + if err != nil { + log.Errorf("Error adding metric: %s", c.desc) + } else { + ch <- metric + } } } @@ -185,7 +199,12 @@ func (c *gaugesWithMultiLabelsCollector) Collect(ch chan<- prometheus.Metric) { for lvs, val := range c.gml.Counts() { labelValues := strings.Split(lvs, ".") value := float64(val) - ch <- prometheus.MustNewConstMetric(c.desc, prometheus.GaugeValue, value, labelValues...) + metric, err := prometheus.NewConstMetric(c.desc, prometheus.GaugeValue, value, labelValues...) + if err != nil { + log.Errorf("Error adding metric: %s", c.desc) + } else { + ch <- metric + } } } @@ -219,7 +238,12 @@ func (c *metricsFuncWithMultiLabelsCollector) Collect(ch chan<- prometheus.Metri for lvs, val := range c.cfml.Counts() { labelValues := strings.Split(lvs, ".") value := float64(val) - ch <- prometheus.MustNewConstMetric(c.desc, c.vt, value, labelValues...) + metric, err := prometheus.NewConstMetric(c.desc, c.vt, value, labelValues...) + if err != nil { + log.Errorf("Error adding metric: %s", c.desc) + } else { + ch <- metric + } } } @@ -256,12 +280,16 @@ func (c *timingsCollector) Describe(ch chan<- *prometheus.Desc) { // Collect implements Collector. func (c *timingsCollector) Collect(ch chan<- prometheus.Metric) { for cat, his := range c.t.Histograms() { - ch <- prometheus.MustNewConstHistogram( - c.desc, + metric, err := prometheus.NewConstHistogram(c.desc, uint64(his.Count()), float64(his.Total())/1000000000, - makeCumulativeBuckets(c.cutoffs, his.Buckets()), - cat) + makeCumulativeBuckets(c.cutoffs, + his.Buckets()), cat) + if err != nil { + log.Errorf("Error adding metric: %s", c.desc) + } else { + ch <- metric + } } } @@ -310,12 +338,17 @@ func (c *multiTimingsCollector) Describe(ch chan<- *prometheus.Desc) { func (c *multiTimingsCollector) Collect(ch chan<- prometheus.Metric) { for cat, his := range c.mt.Timings.Histograms() { labelValues := strings.Split(cat, ".") - ch <- prometheus.MustNewConstHistogram( + metric, err := prometheus.NewConstHistogram( c.desc, uint64(his.Count()), float64(his.Total())/1000000000, makeCumulativeBuckets(c.cutoffs, his.Buckets()), labelValues...) + if err != nil { + log.Errorf("Error adding metric: %s", c.desc) + } else { + ch <- metric + } } } @@ -351,10 +384,13 @@ func (c *histogramCollector) Describe(ch chan<- *prometheus.Desc) { // Collect implements Collector. func (c *histogramCollector) Collect(ch chan<- prometheus.Metric) { - ch <- prometheus.MustNewConstHistogram( - c.desc, + metric, err := prometheus.NewConstHistogram(c.desc, uint64(c.h.Count()), float64(c.h.Total()), - makeCumulativeBuckets(c.cutoffs, c.h.Buckets()), - ) + makeCumulativeBuckets(c.cutoffs, c.h.Buckets())) + if err != nil { + log.Errorf("Error adding metric: %s", c.desc) + } else { + ch <- metric + } } diff --git a/go/stats/prometheusbackend/collectors_test.go b/go/stats/prometheusbackend/collectors_test.go new file mode 100644 index 00000000000..8598bbc4cfc --- /dev/null +++ b/go/stats/prometheusbackend/collectors_test.go @@ -0,0 +1,38 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package prometheusbackend + +import ( + "testing" + + "vitess.io/vitess/go/stats" +) + +func getStats() map[string]int64 { + stats := make(map[string]int64) + stats["table1.plan"] = 1 + stats["table2.plan"] = 2 + // Errors are expected to be logged from collectors.go when + // adding this value (issue #5599). Test will succeed, as intended. + stats["table3.dot.plan"] = 3 + return stats +} + +func TestCollector(t *testing.T) { + c := stats.NewCountersFuncWithMultiLabels("Name", "description", []string{"Table", "Plan"}, getStats) + c.Counts() +} diff --git a/go/stats/prometheusbackend/prometheusbackend.go b/go/stats/prometheusbackend/prometheusbackend.go index fada0aaa4a2..f975a12f08b 100644 --- a/go/stats/prometheusbackend/prometheusbackend.go +++ b/go/stats/prometheusbackend/prometheusbackend.go @@ -82,7 +82,7 @@ func (be PromBackend) publishPrometheusMetric(name string, v expvar.Var) { newMultiTimingsCollector(st, be.buildPromName(name)) case *stats.Histogram: newHistogramCollector(st, be.buildPromName(name)) - case *stats.String, stats.StringFunc, stats.StringMapFunc, *stats.Rates: + case *stats.String, stats.StringFunc, stats.StringMapFunc, *stats.Rates, *stats.RatesFunc: // Silently ignore these types since they don't make sense to // export to Prometheus' data model. default: diff --git a/go/stats/rates.go b/go/stats/rates.go index 2c7a556d3f0..7aa4f7d3ce7 100644 --- a/go/stats/rates.go +++ b/go/stats/rates.go @@ -182,3 +182,32 @@ func (rt *Rates) String() string { } return string(data) } + +type RatesFunc struct { + F func() map[string][]float64 + help string +} + +func NewRateFunc(name string, help string, f func() map[string][]float64) *RatesFunc { + c := &RatesFunc{ + F: f, + help: help, + } + + if name != "" { + publish(name, c) + } + return c +} + +func (rf *RatesFunc) Help() string { + return rf.help +} + +func (rf *RatesFunc) String() string { + data, err := json.Marshal(rf.F()) + if err != nil { + data, _ = json.Marshal(err.Error()) + } + return string(data) +} diff --git a/go/stats/timings.go b/go/stats/timings.go index 8d32ad94bea..697963c4773 100644 --- a/go/stats/timings.go +++ b/go/stats/timings.go @@ -19,7 +19,6 @@ package stats import ( "encoding/json" "fmt" - "strings" "sync" "time" @@ -32,13 +31,12 @@ type Timings struct { totalCount sync2.AtomicInt64 totalTime sync2.AtomicInt64 - // mu protects get and set of hook and the map. - // Modification to the value in the map is not protected. mu sync.RWMutex histograms map[string]*Histogram - hook func(string, time.Duration) - help string - label string + + help string + label string + labelCombined bool } // NewTimings creates a new Timings object, and publishes it if name is set. @@ -47,9 +45,10 @@ type Timings struct { // first time they are updated. func NewTimings(name, help, label string, categories ...string) *Timings { t := &Timings{ - histograms: make(map[string]*Histogram), - help: help, - label: label, + histograms: make(map[string]*Histogram), + help: help, + label: label, + labelCombined: IsDimensionCombined(label), } for _, cat := range categories { t.histograms[cat] = NewGenericHistogram("", "", bucketCutoffs, bucketLabels, "Count", "Time") @@ -63,10 +62,12 @@ func NewTimings(name, help, label string, categories ...string) *Timings { // Add will add a new value to the named histogram. func (t *Timings) Add(name string, elapsed time.Duration) { + if t.labelCombined { + name = StatsAllStr + } // Get existing Histogram. t.mu.RLock() hist, ok := t.histograms[name] - hook := t.hook t.mu.RUnlock() // Create Histogram if it does not exist. @@ -84,14 +85,14 @@ func (t *Timings) Add(name string, elapsed time.Duration) { hist.Add(elapsedNs) t.totalCount.Add(1) t.totalTime.Add(elapsedNs) - if hook != nil { - hook(name, elapsed) - } } // Record is a convenience function that records completion // timing data based on the provided start time of an event. func (t *Timings) Record(name string, startTime time.Time) { + if t.labelCombined { + name = StatsAllStr + } t.Add(name, time.Since(startTime)) } @@ -184,7 +185,8 @@ func init() { // with joining multiple strings with '.'. type MultiTimings struct { Timings - labels []string + labels []string + combinedLabels []bool } // NewMultiTimings creates a new MultiTimings object. @@ -194,7 +196,11 @@ func NewMultiTimings(name string, help string, labels []string) *MultiTimings { histograms: make(map[string]*Histogram), help: help, }, - labels: labels, + labels: labels, + combinedLabels: make([]bool, len(labels)), + } + for i, label := range labels { + t.combinedLabels[i] = IsDimensionCombined(label) } if name != "" { publish(name, t) @@ -208,23 +214,12 @@ func (mt *MultiTimings) Labels() []string { return mt.labels } -// safeJoinLabels joins the label values with ".", but first replaces any existing -// "." characters in the labels with the proper replacement, to avoid issues parsing -// them apart later. -func safeJoinLabels(labels []string) string { - sanitizedLabels := make([]string, len(labels)) - for idx, label := range labels { - sanitizedLabels[idx] = safeLabel(label) - } - return strings.Join(sanitizedLabels, ".") -} - // Add will add a new value to the named histogram. func (mt *MultiTimings) Add(names []string, elapsed time.Duration) { if len(names) != len(mt.labels) { panic("MultiTimings: wrong number of values in Add") } - mt.Timings.Add(safeJoinLabels(names), elapsed) + mt.Timings.Add(safeJoinLabels(names, mt.combinedLabels), elapsed) } // Record is a convenience function that records completion @@ -233,7 +228,7 @@ func (mt *MultiTimings) Record(names []string, startTime time.Time) { if len(names) != len(mt.labels) { panic("MultiTimings: wrong number of values in Record") } - mt.Timings.Record(safeJoinLabels(names), startTime) + mt.Timings.Record(safeJoinLabels(names, mt.combinedLabels), startTime) } // Cutoffs returns the cutoffs used in the component histograms. diff --git a/go/stats/timings_test.go b/go/stats/timings_test.go index 808d1aa15b5..435f5106ba2 100644 --- a/go/stats/timings_test.go +++ b/go/stats/timings_test.go @@ -21,6 +21,8 @@ import ( "strings" "testing" "time" + + "github.com/stretchr/testify/assert" ) func TestTimings(t *testing.T) { @@ -77,3 +79,23 @@ func TestTimingsHook(t *testing.T) { t.Errorf("got %#v, want %#v", gotv, v) } } + +func TestTimingsCombineDimension(t *testing.T) { + clear() + *combineDimensions = "a,c" + + t1 := NewTimings("timing_combine_dim1", "help", "label") + t1.Add("t1", 1*time.Nanosecond) + want := `{"TotalCount":1,"TotalTime":1,"Histograms":{"t1":{"500000":1,"1000000":1,"5000000":1,"10000000":1,"50000000":1,"100000000":1,"500000000":1,"1000000000":1,"5000000000":1,"10000000000":1,"inf":1,"Count":1,"Time":1}}}` + assert.Equal(t, want, t1.String()) + + t2 := NewTimings("timing_combine_dim2", "help", "a") + t2.Add("t1", 1) + want = `{"TotalCount":1,"TotalTime":1,"Histograms":{"all":{"500000":1,"1000000":1,"5000000":1,"10000000":1,"50000000":1,"100000000":1,"500000000":1,"1000000000":1,"5000000000":1,"10000000000":1,"inf":1,"Count":1,"Time":1}}}` + assert.Equal(t, want, t2.String()) + + t3 := NewMultiTimings("timing_combine_dim3", "help", []string{"a", "b", "c"}) + t3.Add([]string{"c1", "c2", "c3"}, 1) + want = `{"TotalCount":1,"TotalTime":1,"Histograms":{"all.c2.all":{"500000":1,"1000000":1,"5000000":1,"10000000":1,"50000000":1,"100000000":1,"500000000":1,"1000000000":1,"5000000000":1,"10000000000":1,"inf":1,"Count":1,"Time":1}}}` + assert.Equal(t, want, t3.String()) +} diff --git a/go/test/endtoend/README.md b/go/test/endtoend/README.md new file mode 100644 index 00000000000..7bd71f9bfef --- /dev/null +++ b/go/test/endtoend/README.md @@ -0,0 +1,44 @@ +This document describe the testing strategy we use for all Vitess components, and the progression in scope / complexity. + +As Vitess developers, our goal is to have great end to end test coverage. In the past, these tests were mostly written in python 2.7 is coming to end of life we are moving all of those into GO. + + +## End to End Tests + +These tests are meant to test end-to-end behaviors of the Vitess ecosystem, and complement the unit tests. For instance, we test each RPC interaction independently (client to vtgate, vtgate to vttablet, vttablet to MySQL, see previous sections). But is also good to have an end-to-end test that validates everything works together. + +These tests almost always launch a topology service, a few mysqld instances, a few vttablets, a vtctld process, a few vtgates, ... They use the real production processes, and real replication. This setup is mandatory for properly testing re-sharding, cluster operations, ... They all however run on the same machine, so they might be limited by the environment. + + +## Strategy + +All the end to end test are placed under path go/test/endtoend. +The main purpose of grouping them together is to make sure we have single place for reference and to combine similar test to run them in the same cluster and save test running time. + + +### Setup +All the tests should be launching a real cluster just like the production setup and execute the tests on that setup followed by a teardown of all the services. + +The cluster launch functions are provided under go/test/endtoend/cluster. This is still work in progress so feel free to add new function as required or update the existing ones. + +In general the cluster is build in following order +- Define Keyspace +- Define Shards +- Start topology service [default etcd] +- Start vtctld client +- Start required mysqld instances +- Start corresponding vttablets (atleast 1 master and 1 replica) +- Start Vtgate + +A good example to refer will be go/test/endtoend/clustertest + +### Pre-Requisite +Make sure you have vitess binary available in bin folder. If not, then you can run `./bootstrap.sh` follow by `make build` & `source build.env`. + +To make it easier to re-run test please add following to you bash profile. + +``` +export VTROOT=//vitess +export VTDATAROOT=${VTROOT}/vtdataroot +export PATH=${VTROOT}/bin:${PATH} +``` diff --git a/go/cmd/vtqueryserver/plugin_auth_static.go b/go/test/endtoend/backup/mysqlctld/backup_mysqlctld_test.go similarity index 60% rename from go/cmd/vtqueryserver/plugin_auth_static.go rename to go/test/endtoend/backup/mysqlctld/backup_mysqlctld_test.go index 84cdec6cec0..2ee11103c72 100644 --- a/go/cmd/vtqueryserver/plugin_auth_static.go +++ b/go/test/endtoend/backup/mysqlctld/backup_mysqlctld_test.go @@ -7,22 +7,22 @@ You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreedto in writing, software +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. */ -package main - -// This plugin imports staticauthserver to register the flat-file implementation of AuthServer. +package mysqlctld import ( - "vitess.io/vitess/go/mysql" - "vitess.io/vitess/go/vt/vtqueryserver" + "testing" + + backup "vitess.io/vitess/go/test/endtoend/backup/vtctlbackup" ) -func init() { - vtqueryserver.RegisterPluginInitializer(func() { mysql.InitAuthServerStatic() }) +// TestBackupMysqlctld - tests the backup using mysqlctld. +func TestBackupMysqlctld(t *testing.T) { + backup.TestBackup(t, backup.Mysqlctld, "", 0) } diff --git a/go/test/endtoend/backup/transform/backup_transform_test.go b/go/test/endtoend/backup/transform/backup_transform_test.go new file mode 100644 index 00000000000..071f7d536e3 --- /dev/null +++ b/go/test/endtoend/backup/transform/backup_transform_test.go @@ -0,0 +1,30 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package transform + +import "testing" + +func TestMain(m *testing.M) { + TestMainSetup(m, false) +} + +func TestBackupTransform(t *testing.T) { + TestBackupTransformImpl(t) +} +func TestBackupTransformError(t *testing.T) { + TestBackupTransformErrorImpl(t) +} diff --git a/go/test/endtoend/backup/transform/backup_transform_utils.go b/go/test/endtoend/backup/transform/backup_transform_utils.go new file mode 100644 index 00000000000..90d6f8827bc --- /dev/null +++ b/go/test/endtoend/backup/transform/backup_transform_utils.go @@ -0,0 +1,351 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package transform + +import ( + "encoding/json" + "flag" + "fmt" + "io/ioutil" + "os" + "os/exec" + "path" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/test/endtoend/cluster" + "vitess.io/vitess/go/test/endtoend/sharding/initialsharding" + "vitess.io/vitess/go/vt/log" +) + +// test main part of the testcase +var ( + master *cluster.Vttablet + replica1 *cluster.Vttablet + replica2 *cluster.Vttablet + localCluster *cluster.LocalProcessCluster + newInitDBFile string + cell = cluster.DefaultCell + hostname = "localhost" + keyspaceName = "ks" + dbPassword = "VtDbaPass" + shardKsName = fmt.Sprintf("%s/%s", keyspaceName, shardName) + dbCredentialFile string + shardName = "0" + commonTabletArg = []string{ + "-vreplication_healthcheck_topology_refresh", "1s", + "-vreplication_healthcheck_retry_delay", "1s", + "-vreplication_retry_delay", "1s", + "-degraded_threshold", "5s", + "-lock_tables_timeout", "5s", + "-watch_replication_stream", + "-enable_replication_reporter", + "-serving_state_grace_period", "1s"} +) + +func TestMainSetup(m *testing.M, useMysqlctld bool) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitCode, err := func() (int, error) { + localCluster = cluster.NewCluster(cell, hostname) + defer localCluster.Teardown() + + // Start topo server + err := localCluster.StartTopo() + if err != nil { + return 1, err + } + + // Start keyspace + localCluster.Keyspaces = []cluster.Keyspace{ + { + Name: keyspaceName, + Shards: []cluster.Shard{ + { + Name: shardName, + }, + }, + }, + } + shard := &localCluster.Keyspaces[0].Shards[0] + // changing password for mysql user + dbCredentialFile = initialsharding.WriteDbCredentialToTmp(localCluster.TmpDirectory) + initDb, _ := ioutil.ReadFile(path.Join(os.Getenv("VTROOT"), "/config/init_db.sql")) + sql := string(initDb) + newInitDBFile = path.Join(localCluster.TmpDirectory, "init_db_with_passwords.sql") + sql = sql + initialsharding.GetPasswordUpdateSQL(localCluster) + ioutil.WriteFile(newInitDBFile, []byte(sql), 0666) + + extraArgs := []string{"-db-credentials-file", dbCredentialFile} + commonTabletArg = append(commonTabletArg, "-db-credentials-file", dbCredentialFile) + + // start mysql process for all replicas and master + var mysqlProcs []*exec.Cmd + for i := 0; i < 3; i++ { + tabletType := "replica" + tablet := localCluster.GetVttabletInstance(tabletType, 0, cell) + tablet.VttabletProcess = localCluster.GetVtprocessInstanceFromVttablet(tablet, shard.Name, keyspaceName) + tablet.VttabletProcess.DbPassword = dbPassword + tablet.VttabletProcess.ExtraArgs = commonTabletArg + tablet.VttabletProcess.SupportsBackup = true + tablet.VttabletProcess.EnableSemiSync = true + + if useMysqlctld { + tablet.MysqlctldProcess = *cluster.MysqlCtldProcessInstance(tablet.TabletUID, tablet.MySQLPort, localCluster.TmpDirectory) + tablet.MysqlctldProcess.InitDBFile = newInitDBFile + tablet.MysqlctldProcess.ExtraArgs = extraArgs + tablet.MysqlctldProcess.Password = tablet.VttabletProcess.DbPassword + err := tablet.MysqlctldProcess.Start() + if err != nil { + return 1, err + } + + shard.Vttablets = append(shard.Vttablets, tablet) + continue + } + + tablet.MysqlctlProcess = *cluster.MysqlCtlProcessInstance(tablet.TabletUID, tablet.MySQLPort, localCluster.TmpDirectory) + tablet.MysqlctlProcess.InitDBFile = newInitDBFile + tablet.MysqlctlProcess.ExtraArgs = extraArgs + proc, err := tablet.MysqlctlProcess.StartProcess() + if err != nil { + return 1, err + } + mysqlProcs = append(mysqlProcs, proc) + + shard.Vttablets = append(shard.Vttablets, tablet) + } + for _, proc := range mysqlProcs { + if err := proc.Wait(); err != nil { + return 1, err + } + } + + // initialize tablets + master = shard.Vttablets[0] + replica1 = shard.Vttablets[1] + replica2 = shard.Vttablets[2] + + for _, tablet := range []*cluster.Vttablet{master, replica1} { + if err := localCluster.VtctlclientProcess.InitTablet(tablet, cell, keyspaceName, hostname, shard.Name); err != nil { + return 1, err + } + } + + // create database for master and replica + for _, tablet := range []cluster.Vttablet{*master, *replica1} { + if err := tablet.VttabletProcess.CreateDB(keyspaceName); err != nil { + return 1, err + } + if err := tablet.VttabletProcess.Setup(); err != nil { + return 1, err + } + } + + // initialize master and start replication + if err := localCluster.VtctlclientProcess.InitShardMaster(keyspaceName, shard.Name, cell, master.TabletUID); err != nil { + return 1, err + } + return m.Run(), nil + }() + + if err != nil { + log.Error(err.Error()) + os.Exit(1) + } else { + os.Exit(exitCode) + } + +} + +// create query for test table creation +var vtInsertTest = `create table vt_insert_test ( + id bigint auto_increment, + msg varchar(64), + primary key (id) + ) Engine=InnoDB` + +func TestBackupTransformImpl(t *testing.T) { + // insert data in master, validate same in slave + defer cluster.PanicHandler(t) + verifyInitialReplication(t) + + // restart the replica with transform hook parameter + replica1.VttabletProcess.TearDown() + replica1.VttabletProcess.ExtraArgs = []string{ + "-db-credentials-file", dbCredentialFile, + "-backup_storage_hook", "test_backup_transform", + "-backup_storage_compress=false", + "-restore_from_backup", + "-backup_storage_implementation", "file", + "-file_backup_storage_root", localCluster.VtctldProcess.FileBackupStorageRoot} + replica1.VttabletProcess.ServingStatus = "SERVING" + err := replica1.VttabletProcess.Setup() + require.Nil(t, err) + + // take backup, it should not give any error + err = localCluster.VtctlclientProcess.ExecuteCommand("Backup", replica1.Alias) + require.Nil(t, err) + + // insert data in master + _, err = master.VttabletProcess.QueryTablet("insert into vt_insert_test (msg) values ('test2')", keyspaceName, true) + require.Nil(t, err) + + // validate backup_list, expecting 1 backup available + backups := localCluster.VerifyBackupCount(t, shardKsName, 1) + + backupLocation := localCluster.CurrentVTDATAROOT + "/backups/" + shardKsName + "/" + backups[0] + + // validate that MANIFEST has TransformHook + // every file should start with 'header' + validateManifestFile(t, backupLocation) + + // restore replica2 from backup, should not give any error + // Note: we don't need to pass in the backup_storage_transform parameter, + // as it is read from the MANIFEST. + // clear replica2 + + if replica2.MysqlctlProcess.TabletUID > 0 { + replica2.MysqlctlProcess.Stop() + os.RemoveAll(replica2.VttabletProcess.Directory) + // start replica2 from backup + err = replica2.MysqlctlProcess.Start() + require.Nil(t, err) + } else { + replica2.MysqlctldProcess.Stop() + os.RemoveAll(replica2.VttabletProcess.Directory) + // start replica2 from backup + err = replica2.MysqlctldProcess.Start() + require.Nil(t, err) + } + + err = localCluster.VtctlclientProcess.InitTablet(replica2, cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + replica2.VttabletProcess.CreateDB(keyspaceName) + replica2.VttabletProcess.ExtraArgs = []string{ + "-db-credentials-file", dbCredentialFile, + "-restore_from_backup", + "-backup_storage_implementation", "file", + "-file_backup_storage_root", localCluster.VtctldProcess.FileBackupStorageRoot} + replica2.VttabletProcess.ServingStatus = "" + err = replica2.VttabletProcess.Setup() + require.Nil(t, err) + err = replica2.VttabletProcess.WaitForTabletTypesForTimeout([]string{"SERVING"}, 25*time.Second) + require.Nil(t, err) + defer replica2.VttabletProcess.TearDown() + + // validate that semi-sync is enabled for replica, disable for rdOnly + if replica2.Type == "replica" { + verifyReplicationStatus(t, replica2, "ON") + } else if replica2.Type == "rdonly" { + verifyReplicationStatus(t, replica2, "OFF") + } + + // validate that new slave has all the data + cluster.VerifyRowsInTablet(t, replica2, keyspaceName, 2) + + // Remove all backups + localCluster.RemoveAllBackups(t, shardKsName) + +} + +// TestBackupTransformError validate backup with test_backup_error +// backup_storage_hook, which should fail. +func TestBackupTransformErrorImpl(t *testing.T) { + // restart the replica with transform hook parameter + defer cluster.PanicHandler(t) + err := replica1.VttabletProcess.TearDown() + require.Nil(t, err) + + replica1.VttabletProcess.ExtraArgs = []string{ + "-db-credentials-file", dbCredentialFile, + "-backup_storage_hook", "test_backup_error", + "-restore_from_backup", + "-backup_storage_implementation", "file", + "-file_backup_storage_root", localCluster.VtctldProcess.FileBackupStorageRoot} + replica1.VttabletProcess.ServingStatus = "SERVING" + err = replica1.VttabletProcess.Setup() + require.Nil(t, err) + + // create backup, it should fail + out, err := localCluster.VtctlclientProcess.ExecuteCommandWithOutput("Backup", replica1.Alias) + require.NotNil(t, err) + require.Containsf(t, out, "backup is not usable, aborting it", "unexpected error received %v", err) + + // validate there is no backup left + localCluster.VerifyBackupCount(t, shardKsName, 0) +} + +// validateManifestFile reads manifest and validates that it +// has a TransformHook, SkipCompress and FileEntries. It also +// validates that backup_files available in FileEntries have +// 'header' as their first line. +func validateManifestFile(t *testing.T, backupLocation string) { + + // reading manifest + data, err := ioutil.ReadFile(backupLocation + "/MANIFEST") + require.Nilf(t, err, "error while reading MANIFEST %v", err) + manifest := make(map[string]interface{}) + + // parsing manifest + err = json.Unmarshal(data, &manifest) + require.Nilf(t, err, "error while parsing MANIFEST %v", err) + + // validate manifest + transformHook, _ := manifest["TransformHook"] + require.Equalf(t, "test_backup_transform", transformHook, "invalid transformHook in MANIFEST") + skipCompress, _ := manifest["SkipCompress"] + assert.Equalf(t, skipCompress, true, "invalid value of skipCompress") + + // validate backup files + fielEntries, _ := manifest["FileEntries"] + fileArr, ok := fielEntries.([]interface{}) + require.True(t, ok) + for i := range fileArr { + f, err := os.Open(fmt.Sprintf("%s/%d", backupLocation, i)) + require.Nilf(t, err, "error while opening backup_file %d: %v", i, err) + var fileHeader string + _, err = fmt.Fscanln(f, &fileHeader) + f.Close() + + require.Nilf(t, err, "error while reading backup_file %d: %v", i, err) + require.Equalf(t, "header", fileHeader, "wrong file contents for %d", i) + } + +} + +// verifyReplicationStatus validates the replication status in tablet. +func verifyReplicationStatus(t *testing.T, vttablet *cluster.Vttablet, expectedStatus string) { + status, err := vttablet.VttabletProcess.GetDBVar("rpl_semi_sync_slave_enabled", keyspaceName) + require.Nil(t, err) + assert.Equal(t, expectedStatus, status) + status, err = vttablet.VttabletProcess.GetDBStatus("rpl_semi_sync_slave_status", keyspaceName) + require.Nil(t, err) + assert.Equal(t, expectedStatus, status) +} + +// verifyInitialReplication creates schema in master, insert some data to master and verify the same data in replica +func verifyInitialReplication(t *testing.T) { + _, err := master.VttabletProcess.QueryTablet(vtInsertTest, keyspaceName, true) + require.Nil(t, err) + _, err = master.VttabletProcess.QueryTablet("insert into vt_insert_test (msg) values ('test1')", keyspaceName, true) + require.Nil(t, err) + cluster.VerifyRowsInTablet(t, replica1, keyspaceName, 1) +} diff --git a/go/test/endtoend/backup/transform/mysqlctld/backup_transform_mysqlctld_test.go b/go/test/endtoend/backup/transform/mysqlctld/backup_transform_mysqlctld_test.go new file mode 100644 index 00000000000..0a3b11227da --- /dev/null +++ b/go/test/endtoend/backup/transform/mysqlctld/backup_transform_mysqlctld_test.go @@ -0,0 +1,34 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package mysqlctld + +import ( + "testing" + + "vitess.io/vitess/go/test/endtoend/backup/transform" +) + +func TestMain(m *testing.M) { + transform.TestMainSetup(m, true) +} + +func TestBackupTransform(t *testing.T) { + transform.TestBackupTransformImpl(t) +} +func TestBackupTransformError(t *testing.T) { + transform.TestBackupTransformErrorImpl(t) +} diff --git a/go/test/endtoend/backup/vtbackup/backup_only_test.go b/go/test/endtoend/backup/vtbackup/backup_only_test.go new file mode 100644 index 00000000000..1ac7a93a212 --- /dev/null +++ b/go/test/endtoend/backup/vtbackup/backup_only_test.go @@ -0,0 +1,302 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package vtbackup + +import ( + "fmt" + "os" + "path" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/test/endtoend/cluster" + + "github.com/stretchr/testify/assert" + + "vitess.io/vitess/go/vt/log" +) + +var ( + vtInsertTest = ` + create table vt_insert_test ( + id bigint auto_increment, + msg varchar(64), + primary key (id) + ) Engine=InnoDB;` +) + +func TestTabletInitialBackup(t *testing.T) { + // Test Initial Backup Flow + // TestTabletInitialBackup will: + // - Create a shard using vtbackup and --initial-backup + // - Create the rest of the cluster restoring from backup + // - Externally Reparenting to a master tablet + // - Insert Some data + // - Verify that the cluster is working + // - Take a Second Backup + // - Bring up a second replica, and restore from the second backup + // - list the backups, remove them + defer cluster.PanicHandler(t) + + vtBackup(t, true) + verifyBackupCount(t, shardKsName, 1) + + // Initialize the tablets + initTablets(t, false, false) + + // Restore the Tablets + restore(t, master, "replica", "NOT_SERVING") + err := localCluster.VtctlclientProcess.ExecuteCommand( + "TabletExternallyReparented", master.Alias) + require.Nil(t, err) + restore(t, replica1, "replica", "SERVING") + + // Run the entire backup test + firstBackupTest(t, "replica") + + tearDown(t, true) +} +func TestTabletBackupOnly(t *testing.T) { + // Test Backup Flow + // TestTabletBackupOnly will: + // - Create a shard using regular init & start tablet + // - Run initShardMaster to start replication + // - Insert Some data + // - Verify that the cluster is working + // - Take a Second Backup + // - Bring up a second replica, and restore from the second backup + // - list the backups, remove them + defer cluster.PanicHandler(t) + + // Reset the tablet object values in order on init tablet in the next step. + master.VttabletProcess.ServingStatus = "NOT_SERVING" + replica1.VttabletProcess.ServingStatus = "NOT_SERVING" + + initTablets(t, true, true) + firstBackupTest(t, "replica") + + tearDown(t, false) +} + +func firstBackupTest(t *testing.T, tabletType string) { + // Test First Backup flow. + // + // firstBackupTest will: + // - create a shard with master and replica1 only + // - run InitShardMaster + // - insert some data + // - take a backup + // - insert more data on the master + // - bring up replica2 after the fact, let it restore the backup + // - check all data is right (before+after backup data) + // - list the backup, remove it + + // Store initial backup counts + backups, err := listBackups(shardKsName) + require.Nil(t, err) + + // insert data on master, wait for slave to get it + _, err = master.VttabletProcess.QueryTablet(vtInsertTest, keyspaceName, true) + require.Nil(t, err) + // Add a single row with value 'test1' to the master tablet + _, err = master.VttabletProcess.QueryTablet("insert into vt_insert_test (msg) values ('test1')", keyspaceName, true) + require.Nil(t, err) + + // Check that the specified tablet has the expected number of rows + cluster.VerifyRowsInTablet(t, replica1, keyspaceName, 1) + + // backup the slave + log.Info("taking backup %s", time.Now()) + vtBackup(t, false) + log.Info("done taking backup %s", time.Now()) + + // check that the backup shows up in the listing + verifyBackupCount(t, shardKsName, len(backups)+1) + + // insert more data on the master + _, err = master.VttabletProcess.QueryTablet("insert into vt_insert_test (msg) values ('test2')", keyspaceName, true) + require.Nil(t, err) + cluster.VerifyRowsInTablet(t, replica1, keyspaceName, 2) + + // now bring up the other slave, letting it restore from backup. + err = localCluster.VtctlclientProcess.InitTablet(replica2, cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + restore(t, replica2, "replica", "SERVING") + // Replica2 takes time to serve. Sleeping for 5 sec. + time.Sleep(5 * time.Second) + //check the new slave has the data + cluster.VerifyRowsInTablet(t, replica2, keyspaceName, 2) + + // check that the restored slave has the right local_metadata + result, err := replica2.VttabletProcess.QueryTabletWithDB("select * from local_metadata", "_vt") + require.Nil(t, err) + assert.Equal(t, replica2.Alias, result.Rows[0][1].ToString(), "Alias") + assert.Equal(t, "ks.0", result.Rows[1][1].ToString(), "ClusterAlias") + assert.Equal(t, cell, result.Rows[2][1].ToString(), "DataCenter") + if tabletType == "replica" { + assert.Equal(t, "neutral", result.Rows[3][1].ToString(), "PromotionRule") + } else { + assert.Equal(t, "must_not", result.Rows[3][1].ToString(), "PromotionRule") + } + + removeBackups(t) + verifyBackupCount(t, shardKsName, 0) + +} + +func vtBackup(t *testing.T, initialBackup bool) { + // Take the back using vtbackup executable + extraArgs := []string{"-allow_first_backup", "-db-credentials-file", dbCredentialFile} + log.Info("starting backup tablet %s", time.Now()) + err := localCluster.StartVtbackup(newInitDBFile, initialBackup, keyspaceName, shardName, cell, extraArgs...) + require.Nil(t, err) +} + +func verifyBackupCount(t *testing.T, shardKsName string, expected int) []string { + backups, err := listBackups(shardKsName) + require.Nil(t, err) + assert.Equalf(t, expected, len(backups), "invalid number of backups") + return backups +} + +func listBackups(shardKsName string) ([]string, error) { + backups, err := localCluster.VtctlProcess.ExecuteCommandWithOutput( + "-backup_storage_implementation", "file", + "-file_backup_storage_root", + path.Join(os.Getenv("VTDATAROOT"), "tmp", "backupstorage"), + "ListBackups", shardKsName, + ) + if err != nil { + return nil, err + } + result := strings.Split(backups, "\n") + var returnResult []string + for _, str := range result { + if str != "" { + returnResult = append(returnResult, str) + } + } + return returnResult, nil +} + +func removeBackups(t *testing.T) { + // Remove all the backups from the shard + backups, err := listBackups(shardKsName) + require.Nil(t, err) + for _, backup := range backups { + _, err := localCluster.VtctlProcess.ExecuteCommandWithOutput( + "-backup_storage_implementation", "file", + "-file_backup_storage_root", + path.Join(os.Getenv("VTDATAROOT"), "tmp", "backupstorage"), + "RemoveBackup", shardKsName, backup, + ) + require.Nil(t, err) + } +} + +func initTablets(t *testing.T, startTablet bool, initShardMaster bool) { + // Initialize tablets + for _, tablet := range []cluster.Vttablet{*master, *replica1} { + err := localCluster.VtctlclientProcess.InitTablet(&tablet, cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + if startTablet { + err = tablet.VttabletProcess.Setup() + require.Nil(t, err) + } + } + + if initShardMaster { + // choose master and start replication + err := localCluster.VtctlclientProcess.InitShardMaster(keyspaceName, shardName, cell, master.TabletUID) + require.Nil(t, err) + } +} + +func restore(t *testing.T, tablet *cluster.Vttablet, tabletType string, waitForState string) { + // Erase mysql/tablet dir, then start tablet with restore enabled. + + log.Info("restoring tablet %s", time.Now()) + resetTabletDirectory(t, *tablet, true) + + err := tablet.VttabletProcess.CreateDB(keyspaceName) + require.Nil(t, err) + + // Start tablets + tablet.VttabletProcess.ExtraArgs = []string{"-db-credentials-file", dbCredentialFile} + tablet.VttabletProcess.TabletType = tabletType + tablet.VttabletProcess.ServingStatus = waitForState + tablet.VttabletProcess.SupportsBackup = true + err = tablet.VttabletProcess.Setup() + require.Nil(t, err) +} + +func resetTabletDirectory(t *testing.T, tablet cluster.Vttablet, initMysql bool) { + + extraArgs := []string{"-db-credentials-file", dbCredentialFile} + tablet.MysqlctlProcess.ExtraArgs = extraArgs + + // Shutdown Mysql + err := tablet.MysqlctlProcess.Stop() + require.Nil(t, err) + // Teardown Tablet + err = tablet.VttabletProcess.TearDown() + require.Nil(t, err) + + // Empty the dir + err = os.RemoveAll(tablet.VttabletProcess.Directory) + require.Nil(t, err) + + if initMysql { + // Init the Mysql + tablet.MysqlctlProcess.InitDBFile = newInitDBFile + err = tablet.MysqlctlProcess.Start() + require.Nil(t, err) + } + +} + +func tearDown(t *testing.T, initMysql bool) { + // reset replication + promoteSlaveCommands := "STOP SLAVE; RESET SLAVE ALL; RESET MASTER;" + disableSemiSyncCommands := "SET GLOBAL rpl_semi_sync_master_enabled = false; SET GLOBAL rpl_semi_sync_slave_enabled = false" + for _, tablet := range []cluster.Vttablet{*master, *replica1, *replica2} { + _, err := tablet.VttabletProcess.QueryTablet(promoteSlaveCommands, keyspaceName, true) + require.Nil(t, err) + _, err = tablet.VttabletProcess.QueryTablet(disableSemiSyncCommands, keyspaceName, true) + require.Nil(t, err) + for _, db := range []string{"_vt", "vt_insert_test"} { + _, err = tablet.VttabletProcess.QueryTablet(fmt.Sprintf("drop database if exists %s", db), keyspaceName, true) + require.Nil(t, err) + } + } + + // TODO: Ideally we should not be resetting the mysql. + // So in below code we will have to uncomment the commented code and remove resetTabletDirectory + for _, tablet := range []cluster.Vttablet{*master, *replica1, *replica2} { + //Tear down Tablet + //err := tablet.VttabletProcess.TearDown() + //require.Nil(t, err) + err := localCluster.VtctlclientProcess.ExecuteCommand("DeleteTablet", "-allow_master", tablet.Alias) + require.Nil(t, err) + + resetTabletDirectory(t, tablet, initMysql) + } +} diff --git a/go/test/endtoend/backup/vtbackup/main_test.go b/go/test/endtoend/backup/vtbackup/main_test.go new file mode 100644 index 00000000000..b7412abe27f --- /dev/null +++ b/go/test/endtoend/backup/vtbackup/main_test.go @@ -0,0 +1,145 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package vtbackup + +import ( + "flag" + "fmt" + "io/ioutil" + "os" + "os/exec" + "path" + "testing" + + "vitess.io/vitess/go/test/endtoend/cluster" + "vitess.io/vitess/go/test/endtoend/sharding/initialsharding" + "vitess.io/vitess/go/vt/log" +) + +var ( + master *cluster.Vttablet + replica1 *cluster.Vttablet + replica2 *cluster.Vttablet + localCluster *cluster.LocalProcessCluster + newInitDBFile string + cell = cluster.DefaultCell + hostname = "localhost" + keyspaceName = "ks" + shardName = "0" + dbPassword = "VtDbaPass" + shardKsName = fmt.Sprintf("%s/%s", keyspaceName, shardName) + dbCredentialFile string + commonTabletArg = []string{ + "-vreplication_healthcheck_topology_refresh", "1s", + "-vreplication_healthcheck_retry_delay", "1s", + "-vreplication_retry_delay", "1s", + "-degraded_threshold", "5s", + "-lock_tables_timeout", "5s", + "-watch_replication_stream", + "-enable_replication_reporter", + "-serving_state_grace_period", "1s"} +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitCode, err := func() (int, error) { + localCluster = cluster.NewCluster(cell, hostname) + defer localCluster.Teardown() + + // Start topo server + err := localCluster.StartTopo() + if err != nil { + return 1, err + } + + // Start keyspace + localCluster.Keyspaces = []cluster.Keyspace{ + { + Name: keyspaceName, + Shards: []cluster.Shard{ + { + Name: shardName, + }, + }, + }, + } + shard := &localCluster.Keyspaces[0].Shards[0] + + // Create a new init_db.sql file that sets up passwords for all users. + // Then we use a db-credentials-file with the passwords. + dbCredentialFile = initialsharding.WriteDbCredentialToTmp(localCluster.TmpDirectory) + initDb, _ := ioutil.ReadFile(path.Join(os.Getenv("VTROOT"), "/config/init_db.sql")) + sql := string(initDb) + newInitDBFile = path.Join(localCluster.TmpDirectory, "init_db_with_passwords.sql") + sql = sql + initialsharding.GetPasswordUpdateSQL(localCluster) + err = ioutil.WriteFile(newInitDBFile, []byte(sql), 0666) + if err != nil { + return 1, err + } + + extraArgs := []string{"-db-credentials-file", dbCredentialFile} + commonTabletArg = append(commonTabletArg, "-db-credentials-file", dbCredentialFile) + + master = localCluster.GetVttabletInstance("replica", 0, "") + replica1 = localCluster.GetVttabletInstance("replica", 0, "") + replica2 = localCluster.GetVttabletInstance("replica", 0, "") + shard.Vttablets = []*cluster.Vttablet{master, replica1, replica2} + + // Start MySql processes + var mysqlProcs []*exec.Cmd + for _, tablet := range shard.Vttablets { + tablet.VttabletProcess = localCluster.GetVtprocessInstanceFromVttablet(tablet, shard.Name, keyspaceName) + tablet.VttabletProcess.DbPassword = dbPassword + tablet.VttabletProcess.ExtraArgs = commonTabletArg + tablet.VttabletProcess.SupportsBackup = true + tablet.VttabletProcess.EnableSemiSync = true + + tablet.MysqlctlProcess = *cluster.MysqlCtlProcessInstance(tablet.TabletUID, tablet.MySQLPort, localCluster.TmpDirectory) + tablet.MysqlctlProcess.InitDBFile = newInitDBFile + tablet.MysqlctlProcess.ExtraArgs = extraArgs + if proc, err := tablet.MysqlctlProcess.StartProcess(); err != nil { + return 1, err + } else { + mysqlProcs = append(mysqlProcs, proc) + } + } + for _, proc := range mysqlProcs { + if err := proc.Wait(); err != nil { + return 1, err + } + } + + // Create database + for _, tablet := range []cluster.Vttablet{*master, *replica1} { + if err := tablet.VttabletProcess.CreateDB(keyspaceName); err != nil { + return 1, err + } + } + + return m.Run(), nil + }() + + if err != nil { + log.Error(err.Error()) + os.Exit(1) + } else { + os.Exit(exitCode) + } + +} diff --git a/go/stats/safe_label.go b/go/test/endtoend/backup/vtctlbackup/backup_test.go similarity index 72% rename from go/stats/safe_label.go rename to go/test/endtoend/backup/vtctlbackup/backup_test.go index a9ca0720f26..6f233eafeda 100644 --- a/go/stats/safe_label.go +++ b/go/test/endtoend/backup/vtctlbackup/backup_test.go @@ -14,14 +14,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -package stats +package vtctlbackup import ( - "strings" + "testing" ) -// safeLabel turns a label into a safe label for stats export. -// It is in its own file so it can be customized. -func safeLabel(label string) string { - return strings.Replace(label, ".", "_", -1) +// TestBackupMain - main tests backup using vtctl commands +func TestBackupMain(t *testing.T) { + TestBackup(t, Backup, "", 0) } diff --git a/go/test/endtoend/backup/vtctlbackup/backup_utils.go b/go/test/endtoend/backup/vtctlbackup/backup_utils.go new file mode 100644 index 00000000000..aeb1d53365a --- /dev/null +++ b/go/test/endtoend/backup/vtctlbackup/backup_utils.go @@ -0,0 +1,661 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package vtctlbackup + +import ( + "bufio" + "encoding/json" + "fmt" + "io/ioutil" + "os" + "os/exec" + "path" + "strings" + "syscall" + "testing" + "time" + + "vitess.io/vitess/go/test/endtoend/sharding/initialsharding" + + "vitess.io/vitess/go/vt/proto/topodata" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/test/endtoend/cluster" +) + +const ( + ExtraBackup = iota + Backup + Mysqlctld +) + +var ( + master *cluster.Vttablet + replica1 *cluster.Vttablet + replica2 *cluster.Vttablet + localCluster *cluster.LocalProcessCluster + newInitDBFile string + useXtrabackup bool + cell = cluster.DefaultCell + hostname = "localhost" + keyspaceName = "ks" + dbPassword = "VtDbaPass" + shardKsName = fmt.Sprintf("%s/%s", keyspaceName, shardName) + dbCredentialFile string + shardName = "0" + commonTabletArg = []string{ + "-vreplication_healthcheck_topology_refresh", "1s", + "-vreplication_healthcheck_retry_delay", "1s", + "-vreplication_retry_delay", "1s", + "-degraded_threshold", "5s", + "-lock_tables_timeout", "5s", + "-watch_replication_stream", + "-enable_replication_reporter", + "-serving_state_grace_period", "1s", + } + + vtInsertTest = ` + create table vt_insert_test ( + id bigint auto_increment, + msg varchar(64), + primary key (id) + ) Engine=InnoDB` +) + +// LaunchCluster : starts the cluster as per given params. +func LaunchCluster(setupType int, streamMode string, stripes int) (int, error) { + localCluster = cluster.NewCluster(cell, hostname) + + // Start topo server + err := localCluster.StartTopo() + if err != nil { + return 1, err + } + + // Start keyspace + localCluster.Keyspaces = []cluster.Keyspace{ + { + Name: keyspaceName, + Shards: []cluster.Shard{ + { + Name: shardName, + }, + }, + }, + } + shard := &localCluster.Keyspaces[0].Shards[0] + + dbCredentialFile = initialsharding.WriteDbCredentialToTmp(localCluster.TmpDirectory) + initDb, _ := ioutil.ReadFile(path.Join(os.Getenv("VTROOT"), "/config/init_db.sql")) + sql := string(initDb) + newInitDBFile = path.Join(localCluster.TmpDirectory, "init_db_with_passwords.sql") + sql = sql + initialsharding.GetPasswordUpdateSQL(localCluster) + err = ioutil.WriteFile(newInitDBFile, []byte(sql), 0666) + if err != nil { + return 1, err + } + + extraArgs := []string{"-db-credentials-file", dbCredentialFile} + commonTabletArg = append(commonTabletArg, "-db-credentials-file", dbCredentialFile) + + // Update arguments for xtrabackup + if setupType == ExtraBackup { + useXtrabackup = true + + xtrabackupArgs := []string{ + "-backup_engine_implementation", "xtrabackup", + fmt.Sprintf("-xtrabackup_stream_mode=%s", streamMode), + "-xtrabackup_user=vt_dba", + fmt.Sprintf("-xtrabackup_stripes=%d", stripes), + "-xtrabackup_backup_flags", fmt.Sprintf("--password=%s", dbPassword), + } + + commonTabletArg = append(commonTabletArg, xtrabackupArgs...) + } + + var mysqlProcs []*exec.Cmd + for i := 0; i < 3; i++ { + tabletType := "replica" + if i == 0 { + tabletType = "master" + } + tablet := localCluster.GetVttabletInstance(tabletType, 0, cell) + tablet.VttabletProcess = localCluster.GetVtprocessInstanceFromVttablet(tablet, shard.Name, keyspaceName) + tablet.VttabletProcess.DbPassword = dbPassword + tablet.VttabletProcess.ExtraArgs = commonTabletArg + tablet.VttabletProcess.SupportsBackup = true + tablet.VttabletProcess.EnableSemiSync = true + + if setupType == Mysqlctld { + tablet.MysqlctldProcess = *cluster.MysqlCtldProcessInstance(tablet.TabletUID, tablet.MySQLPort, localCluster.TmpDirectory) + tablet.MysqlctldProcess.InitDBFile = newInitDBFile + tablet.MysqlctldProcess.ExtraArgs = extraArgs + tablet.MysqlctldProcess.Password = tablet.VttabletProcess.DbPassword + if err := tablet.MysqlctldProcess.Start(); err != nil { + return 1, err + } + shard.Vttablets = append(shard.Vttablets, tablet) + continue + } + + tablet.MysqlctlProcess = *cluster.MysqlCtlProcessInstance(tablet.TabletUID, tablet.MySQLPort, localCluster.TmpDirectory) + tablet.MysqlctlProcess.InitDBFile = newInitDBFile + tablet.MysqlctlProcess.ExtraArgs = extraArgs + proc, err := tablet.MysqlctlProcess.StartProcess() + if err != nil { + return 1, err + } + mysqlProcs = append(mysqlProcs, proc) + + shard.Vttablets = append(shard.Vttablets, tablet) + } + for _, proc := range mysqlProcs { + if err := proc.Wait(); err != nil { + return 1, err + } + } + master = shard.Vttablets[0] + replica1 = shard.Vttablets[1] + replica2 = shard.Vttablets[2] + + if err := localCluster.VtctlclientProcess.InitTablet(master, cell, keyspaceName, hostname, shard.Name); err != nil { + return 1, err + } + if err := localCluster.VtctlclientProcess.InitTablet(replica1, cell, keyspaceName, hostname, shard.Name); err != nil { + return 1, err + } + + for _, tablet := range []cluster.Vttablet{*master, *replica1} { + if err := tablet.VttabletProcess.CreateDB(keyspaceName); err != nil { + return 1, err + } + if err := tablet.VttabletProcess.Setup(); err != nil { + return 1, err + } + } + + if err := localCluster.VtctlclientProcess.InitShardMaster(keyspaceName, shard.Name, cell, master.TabletUID); err != nil { + return 1, err + } + return 0, nil +} + +func TearDownCluster() { + localCluster.Teardown() +} + +func TestBackup(t *testing.T, setupType int, streamMode string, stripes int) { + + testMethods := []struct { + name string + method func(t *testing.T) + }{ + { + name: "TestReplicaBackup", + method: func(t *testing.T) { + vtctlBackup(t, "replica") + }, + }, // + { + name: "TestRdonlyBackup", + method: func(t *testing.T) { + vtctlBackup(t, "rdonly") + }, + }, // + { + name: "TestMasterBackup", + method: masterBackup, + }, // + { + name: "TestMasterReplicaSameBackup", + method: masterReplicaSameBackup, + }, // + { + name: "TestRestoreOldMasterByRestart", + method: restoreOldMasterByRestart, + }, // + { + name: "TestRestoreOldMasterInPlace", + method: restoreOldMasterInPlace, + }, // + { + name: "TestTerminatedRestore", + method: terminatedRestore, + }, // + } + + defer cluster.PanicHandler(t) + + // setup cluster for the testing + code, err := LaunchCluster(setupType, streamMode, stripes) + require.Nilf(t, err, "setup failed with status code %d", code) + + // Teardown the cluster + defer TearDownCluster() + + // Run all the backup tests + + for _, test := range testMethods { + t.Run(test.name, test.method) + } + +} + +type restoreMethod func(t *testing.T, tablet *cluster.Vttablet) + +//- create a shard with master and replica1 only +//- run InitShardMaster +//- insert some data +//- take a backup on master +//- insert more data on the master +//- bring up tablet_replica2 after the fact, let it restore the backup +//- check all data is right (before+after backup data) +//- list the backup, remove it +func masterBackup(t *testing.T) { + verifyInitialReplication(t) + + output, err := localCluster.VtctlclientProcess.ExecuteCommandWithOutput("Backup", master.Alias) + require.Error(t, err) + assert.Contains(t, output, "type MASTER cannot take backup. if you really need to do this, rerun the backup command with -allow_master") + + localCluster.VerifyBackupCount(t, shardKsName, 0) + + err = localCluster.VtctlclientProcess.ExecuteCommand("Backup", "-allow_master=true", master.Alias) + require.Nil(t, err) + + backups := localCluster.VerifyBackupCount(t, shardKsName, 1) + assert.Contains(t, backups[0], master.Alias) + + _, err = master.VttabletProcess.QueryTablet("insert into vt_insert_test (msg) values ('test2')", keyspaceName, true) + require.Nil(t, err) + + restoreWaitForBackup(t, "replica") + err = replica2.VttabletProcess.WaitForTabletTypesForTimeout([]string{"SERVING"}, 25*time.Second) + require.Nil(t, err) + + cluster.VerifyRowsInTablet(t, replica2, keyspaceName, 2) + cluster.VerifyLocalMetadata(t, replica2, keyspaceName, shardName, cell) + verifyAfterRemovingBackupNoBackupShouldBePresent(t, backups) + + err = replica2.VttabletProcess.TearDown() + require.Nil(t, err) + + _, err = master.VttabletProcess.QueryTablet("DROP TABLE vt_insert_test", keyspaceName, true) + require.Nil(t, err) +} + +// Test a master and replica from the same backup. +// +// Check that a replica and master both restored from the same backup +// can replicate successfully. +func masterReplicaSameBackup(t *testing.T) { + // insert data on master, wait for replica to get it + verifyInitialReplication(t) + + // backup the replica + err := localCluster.VtctlclientProcess.ExecuteCommand("Backup", replica1.Alias) + require.Nil(t, err) + + // insert more data on the master + _, err = master.VttabletProcess.QueryTablet("insert into vt_insert_test (msg) values ('test2')", keyspaceName, true) + require.Nil(t, err) + + // now bring up the other replica, letting it restore from backup. + restoreWaitForBackup(t, "replica") + err = replica2.VttabletProcess.WaitForTabletTypesForTimeout([]string{"SERVING"}, 25*time.Second) + require.Nil(t, err) + + // check the new replica has the data + cluster.VerifyRowsInTablet(t, replica2, keyspaceName, 2) + + // Promote replica2 to master + err = localCluster.VtctlclientProcess.ExecuteCommand("PlannedReparentShard", + "-keyspace_shard", shardKsName, + "-new_master", replica2.Alias) + require.Nil(t, err) + + // insert more data on replica2 (current master) + _, err = replica2.VttabletProcess.QueryTablet("insert into vt_insert_test (msg) values ('test3')", keyspaceName, true) + require.Nil(t, err) + + // Force replica1 to restore from backup. + verifyRestoreTablet(t, replica1, "SERVING") + + // wait for replica1 to catch up. + cluster.VerifyRowsInTablet(t, replica1, keyspaceName, 3) + + // This is to test that replicationPosition is processed correctly + // while doing backup/restore after a reparent. + // It is written into the MANIFEST and read back from the MANIFEST. + // + // Take another backup on the replica. + err = localCluster.VtctlclientProcess.ExecuteCommand("Backup", replica1.Alias) + require.Nil(t, err) + + // Insert more data on replica2 (current master). + _, err = replica2.VttabletProcess.QueryTablet("insert into vt_insert_test (msg) values ('test4')", keyspaceName, true) + require.Nil(t, err) + + // Force replica1 to restore from backup. + verifyRestoreTablet(t, replica1, "SERVING") + + cluster.VerifyRowsInTablet(t, replica1, keyspaceName, 4) + err = replica2.VttabletProcess.TearDown() + require.Nil(t, err) + restartMasterReplica(t) +} + +func restoreOldMasterByRestart(t *testing.T) { + testRestoreOldMaster(t, restoreUsingRestart) +} + +func restoreOldMasterInPlace(t *testing.T) { + testRestoreOldMaster(t, restoreInPlace) +} + +//Test that a former master replicates correctly after being restored. +// +//- Take a backup. +//- Reparent from old master to new master. +//- Force old master to restore from a previous backup using restore_method. +// +//Args: +//restore_method: function accepting one parameter of type tablet.Tablet, +//this function is called to force a restore on the provided tablet +// +func testRestoreOldMaster(t *testing.T, method restoreMethod) { + // insert data on master, wait for replica to get it + verifyInitialReplication(t) + + // backup the replica + err := localCluster.VtctlclientProcess.ExecuteCommand("Backup", replica1.Alias) + require.Nil(t, err) + + // insert more data on the master + _, err = master.VttabletProcess.QueryTablet("insert into vt_insert_test (msg) values ('test2')", keyspaceName, true) + require.Nil(t, err) + + // reparent to replica1 + err = localCluster.VtctlclientProcess.ExecuteCommand("PlannedReparentShard", + "-keyspace_shard", shardKsName, + "-new_master", replica1.Alias) + require.Nil(t, err) + + // insert more data to new master + _, err = replica1.VttabletProcess.QueryTablet("insert into vt_insert_test (msg) values ('test3')", keyspaceName, true) + require.Nil(t, err) + + // force the old master to restore at the latest backup. + method(t, master) + + // wait for it to catch up. + cluster.VerifyRowsInTablet(t, master, keyspaceName, 3) + + // teardown + restartMasterReplica(t) +} + +func restoreUsingRestart(t *testing.T, tablet *cluster.Vttablet) { + err := tablet.VttabletProcess.TearDown() + require.Nil(t, err) + verifyRestoreTablet(t, tablet, "SERVING") +} + +func restoreInPlace(t *testing.T, tablet *cluster.Vttablet) { + err := localCluster.VtctlclientProcess.ExecuteCommand("RestoreFromBackup", tablet.Alias) + require.Nil(t, err) +} + +func restartMasterReplica(t *testing.T) { + // Stop all master, replica tablet and mysql instance + stopAllTablets() + + // remove all backups + localCluster.RemoveAllBackups(t, shardKsName) + // start all tablet and mysql instances + var mysqlProcs []*exec.Cmd + for _, tablet := range []*cluster.Vttablet{master, replica1, replica2} { + if tablet.MysqlctldProcess.TabletUID > 0 { + err := tablet.MysqlctldProcess.Start() + require.Nilf(t, err, "error while starting mysqlctld, tabletUID %v", tablet.TabletUID) + continue + } + proc, _ := tablet.MysqlctlProcess.StartProcess() + mysqlProcs = append(mysqlProcs, proc) + } + for _, proc := range mysqlProcs { + proc.Wait() + } + for _, tablet := range []*cluster.Vttablet{master, replica1} { + err := localCluster.VtctlclientProcess.InitTablet(tablet, cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + err = tablet.VttabletProcess.CreateDB(keyspaceName) + require.Nil(t, err) + err = tablet.VttabletProcess.Setup() + require.Nil(t, err) + } + err := localCluster.VtctlclientProcess.InitShardMaster(keyspaceName, shardName, cell, master.TabletUID) + require.Nil(t, err) +} + +func stopAllTablets() { + var mysqlProcs []*exec.Cmd + for _, tablet := range []*cluster.Vttablet{master, replica1, replica2} { + tablet.VttabletProcess.TearDown() + if tablet.MysqlctldProcess.TabletUID > 0 { + tablet.MysqlctldProcess.Stop() + localCluster.VtctlclientProcess.ExecuteCommand("DeleteTablet", "-allow_master", tablet.Alias) + continue + } + proc, _ := tablet.MysqlctlProcess.StopProcess() + mysqlProcs = append(mysqlProcs, proc) + localCluster.VtctlclientProcess.ExecuteCommand("DeleteTablet", "-allow_master", tablet.Alias) + } + for _, proc := range mysqlProcs { + proc.Wait() + } + for _, tablet := range []*cluster.Vttablet{master, replica1} { + os.RemoveAll(tablet.VttabletProcess.Directory) + } +} + +func terminatedRestore(t *testing.T) { + // insert data on master, wait for replica to get it + verifyInitialReplication(t) + + // backup the replica + err := localCluster.VtctlclientProcess.ExecuteCommand("Backup", replica1.Alias) + require.Nil(t, err) + + // insert more data on the master + _, err = master.VttabletProcess.QueryTablet("insert into vt_insert_test (msg) values ('test2')", keyspaceName, true) + require.Nil(t, err) + + // reparent to replica1 + err = localCluster.VtctlclientProcess.ExecuteCommand("PlannedReparentShard", + "-keyspace_shard", shardKsName, + "-new_master", replica1.Alias) + require.Nil(t, err) + + // insert more data to new master + _, err = replica1.VttabletProcess.QueryTablet("insert into vt_insert_test (msg) values ('test3')", keyspaceName, true) + require.Nil(t, err) + + terminateRestore(t) + + err = localCluster.VtctlclientProcess.ExecuteCommand("RestoreFromBackup", master.Alias) + require.Nil(t, err) + + output, err := localCluster.VtctlclientProcess.ExecuteCommandWithOutput("GetTablet", master.Alias) + require.Nil(t, err) + + var tabletPB topodata.Tablet + err = json.Unmarshal([]byte(output), &tabletPB) + require.Nil(t, err) + assert.Equal(t, tabletPB.Type, topodata.TabletType_REPLICA) + + _, err = os.Stat(path.Join(master.VttabletProcess.Directory, "restore_in_progress")) + assert.True(t, os.IsNotExist(err)) + + cluster.VerifyRowsInTablet(t, master, keyspaceName, 3) + stopAllTablets() +} + +//test_backup will: +//- create a shard with master and replica1 only +//- run InitShardMaster +//- bring up tablet_replica2 concurrently, telling it to wait for a backup +//- insert some data +//- take a backup +//- insert more data on the master +//- wait for tablet_replica2 to become SERVING +//- check all data is right (before+after backup data) +//- list the backup, remove it +// +//Args: +//tablet_type: 'replica' or 'rdonly'. +// +// +func vtctlBackup(t *testing.T, tabletType string) { + restoreWaitForBackup(t, tabletType) + verifyInitialReplication(t) + + err := localCluster.VtctlclientProcess.ExecuteCommand("Backup", replica1.Alias) + require.Nil(t, err) + + backups := localCluster.VerifyBackupCount(t, shardKsName, 1) + + _, err = master.VttabletProcess.QueryTablet("insert into vt_insert_test (msg) values ('test2')", keyspaceName, true) + require.Nil(t, err) + + err = replica2.VttabletProcess.WaitForTabletTypesForTimeout([]string{"SERVING"}, 25*time.Second) + require.Nil(t, err) + cluster.VerifyRowsInTablet(t, replica2, keyspaceName, 2) + + cluster.VerifyLocalMetadata(t, replica2, keyspaceName, shardName, cell) + verifyAfterRemovingBackupNoBackupShouldBePresent(t, backups) + + err = replica2.VttabletProcess.TearDown() + require.Nil(t, err) + + err = localCluster.VtctlclientProcess.ExecuteCommand("DeleteTablet", replica2.Alias) + require.Nil(t, err) + _, err = master.VttabletProcess.QueryTablet("DROP TABLE vt_insert_test", keyspaceName, true) + require.Nil(t, err) + +} + +// This will create schema in master, insert some data to master and verify the same data in replica +func verifyInitialReplication(t *testing.T) { + _, err := master.VttabletProcess.QueryTablet(vtInsertTest, keyspaceName, true) + require.Nil(t, err) + _, err = master.VttabletProcess.QueryTablet("insert into vt_insert_test (msg) values ('test1')", keyspaceName, true) + require.Nil(t, err) + cluster.VerifyRowsInTablet(t, replica1, keyspaceName, 1) +} + +// Bring up another replica concurrently, telling it to wait until a backup +// is available instead of starting up empty. +// +// Override the backup engine implementation to a non-existent one for restore. +// This setting should only matter for taking new backups. We should be able +// to restore a previous backup successfully regardless of this setting. +func restoreWaitForBackup(t *testing.T, tabletType string) { + replica2.Type = tabletType + replica2.ValidateTabletRestart(t) + replicaTabletArgs := commonTabletArg + replicaTabletArgs = append(replicaTabletArgs, "-backup_engine_implementation", "fake_implementation") + replicaTabletArgs = append(replicaTabletArgs, "-wait_for_backup_interval", "1s") + replicaTabletArgs = append(replicaTabletArgs, "-init_tablet_type", tabletType) + replica2.VttabletProcess.ExtraArgs = replicaTabletArgs + replica2.VttabletProcess.ServingStatus = "" + err := replica2.VttabletProcess.Setup() + require.Nil(t, err) +} + +func verifyAfterRemovingBackupNoBackupShouldBePresent(t *testing.T, backups []string) { + // Remove the backup + for _, backup := range backups { + err := localCluster.VtctlclientProcess.ExecuteCommand("RemoveBackup", shardKsName, backup) + require.Nil(t, err) + } + + // Now, there should not be no backup + localCluster.VerifyBackupCount(t, shardKsName, 0) +} + +func verifyRestoreTablet(t *testing.T, tablet *cluster.Vttablet, status string) { + + tablet.ValidateTabletRestart(t) + tablet.VttabletProcess.ServingStatus = "" + err := tablet.VttabletProcess.Setup() + require.Nil(t, err) + if status != "" { + err = tablet.VttabletProcess.WaitForTabletTypesForTimeout([]string{status}, 25*time.Second) + require.Nil(t, err) + } + + if tablet.Type == "replica" { + verifyReplicationStatus(t, tablet, "ON") + } else if tablet.Type == "rdonly" { + verifyReplicationStatus(t, tablet, "OFF") + } +} + +func verifyReplicationStatus(t *testing.T, vttablet *cluster.Vttablet, expectedStatus string) { + status, err := vttablet.VttabletProcess.GetDBVar("rpl_semi_sync_slave_enabled", keyspaceName) + require.Nil(t, err) + assert.Equal(t, status, expectedStatus) + status, err = vttablet.VttabletProcess.GetDBStatus("rpl_semi_sync_slave_status", keyspaceName) + require.Nil(t, err) + assert.Equal(t, status, expectedStatus) +} + +func terminateRestore(t *testing.T) { + stopRestoreMsg := "Copying file 10" + if useXtrabackup { + stopRestoreMsg = "Restore: Preparing" + useXtrabackup = false + } + + args := append([]string{"-server", localCluster.VtctlclientProcess.Server, "-alsologtostderr"}, "RestoreFromBackup", master.Alias) + tmpProcess := exec.Command( + "vtctlclient", + args..., + ) + + reader, _ := tmpProcess.StderrPipe() + err := tmpProcess.Start() + require.Nil(t, err) + found := false + + scanner := bufio.NewScanner(reader) + + for scanner.Scan() { + text := scanner.Text() + if strings.Contains(text, stopRestoreMsg) { + if _, err := os.Stat(path.Join(master.VttabletProcess.Directory, "restore_in_progress")); os.IsNotExist(err) { + assert.Fail(t, "restore in progress file missing") + } + tmpProcess.Process.Signal(syscall.SIGTERM) + found = true + return + } + } + assert.True(t, found, "Restore message not found") +} diff --git a/go/test/endtoend/backup/xtrabackup/xtrabackup_test.go b/go/test/endtoend/backup/xtrabackup/xtrabackup_test.go new file mode 100644 index 00000000000..0802d116c93 --- /dev/null +++ b/go/test/endtoend/backup/xtrabackup/xtrabackup_test.go @@ -0,0 +1,28 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package vtctlbackup + +import ( + "testing" + + backup "vitess.io/vitess/go/test/endtoend/backup/vtctlbackup" +) + +// TestXtraBackup - tests the backup using xtrabackup +func TestXtrabackup(t *testing.T) { + backup.TestBackup(t, backup.ExtraBackup, "tar", 0) +} diff --git a/go/test/endtoend/backup/xtrabackupstream/xtrabackup_stream_test.go b/go/test/endtoend/backup/xtrabackupstream/xtrabackup_stream_test.go new file mode 100644 index 00000000000..0f1544e8f14 --- /dev/null +++ b/go/test/endtoend/backup/xtrabackupstream/xtrabackup_stream_test.go @@ -0,0 +1,28 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package vtctlbackup + +import ( + "testing" + + backup "vitess.io/vitess/go/test/endtoend/backup/vtctlbackup" +) + +// TestXtrabackupStream - tests the backup using xtrabackup with xbstream mode +func TestXtrabackupStream(t *testing.T) { + backup.TestBackup(t, backup.ExtraBackup, "xbstream", 8) +} diff --git a/go/test/endtoend/binlog/binlog_test.go b/go/test/endtoend/binlog/binlog_test.go new file mode 100644 index 00000000000..5247b5c9633 --- /dev/null +++ b/go/test/endtoend/binlog/binlog_test.go @@ -0,0 +1,369 @@ +/* +Copyright 2019 The Vitess Authors. + +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 file contains integration tests for the go/vt/binlog package. + It sets up filtered replication between two shards and checks how data flows + through binlog streamer. +*/ + +package binlog + +import ( + "context" + "encoding/json" + "flag" + "fmt" + "os" + "os/exec" + "path" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/test/endtoend/cluster" + "vitess.io/vitess/go/vt/proto/query" +) + +var ( + localCluster *cluster.LocalProcessCluster + cell = "zone1" + hostname = "localhost" + keyspaceName = "ks" + tableName = "test_table" + sqlSchema = ` + create table %s( + id bigint(20) unsigned auto_increment, + msg varchar(64), + primary key (id), + index by_msg (msg) + ) Engine=InnoDB +` + insertSql = `insert into %s(id,msg) values(%d, "%s")` + commonTabletArg = []string{ + "-vreplication_healthcheck_topology_refresh", "1s", + "-vreplication_healthcheck_retry_delay", "1s", + "-vreplication_retry_delay", "1s", + "-degraded_threshold", "5s", + "-lock_tables_timeout", "5s", + "-watch_replication_stream", + "-enable_replication_reporter", + "-serving_state_grace_period", "1s", + "-binlog_player_protocol", "grpc", + "-enable-autocommit", + } + vSchema = ` + { + "sharded": false, + "vindexes": { + "hash_index": { + "type": "hash" + } + }, + "tables": { + "%s": { + "column_vindexes": [ + { + "column": "id", + "name": "hash_index" + } + ] + } + } + } +` + srcMaster *cluster.Vttablet + srcReplica *cluster.Vttablet + srcRdonly *cluster.Vttablet + + destMaster *cluster.Vttablet + destReplica *cluster.Vttablet + destRdonly *cluster.Vttablet +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitcode, err := func() (int, error) { + localCluster = cluster.NewCluster(cell, hostname) + defer localCluster.Teardown() + + localCluster.Keyspaces = append(localCluster.Keyspaces, cluster.Keyspace{ + Name: keyspaceName, + }) + + // Start topo server + if err := localCluster.StartTopo(); err != nil { + return 1, err + } + + srcMaster = localCluster.GetVttabletInstance("master", 0, "") + srcReplica = localCluster.GetVttabletInstance("replica", 0, "") + srcRdonly = localCluster.GetVttabletInstance("rdonly", 0, "") + + destMaster = localCluster.GetVttabletInstance("master", 0, "") + destReplica = localCluster.GetVttabletInstance("replica", 0, "") + destRdonly = localCluster.GetVttabletInstance("rdonly", 0, "") + + var mysqlProcs []*exec.Cmd + for _, tablet := range []*cluster.Vttablet{srcMaster, srcReplica, srcRdonly, destMaster, destReplica, destRdonly} { + tablet.MysqlctlProcess = *cluster.MysqlCtlProcessInstance(tablet.TabletUID, tablet.MySQLPort, localCluster.TmpDirectory) + tablet.VttabletProcess = cluster.VttabletProcessInstance(tablet.HTTPPort, + tablet.GrpcPort, + tablet.TabletUID, + cell, + "", + keyspaceName, + localCluster.VtctldProcess.Port, + tablet.Type, + localCluster.TopoPort, + hostname, + localCluster.TmpDirectory, + commonTabletArg, + true, + ) + tablet.VttabletProcess.SupportsBackup = true + proc, err := tablet.MysqlctlProcess.StartProcess() + if err != nil { + return 1, err + } + mysqlProcs = append(mysqlProcs, proc) + } + for _, proc := range mysqlProcs { + if err := proc.Wait(); err != nil { + return 1, err + } + } + + if err := localCluster.VtctlProcess.CreateKeyspace(keyspaceName); err != nil { + return 1, err + } + + shard1 := cluster.Shard{ + Name: "0", + Vttablets: []*cluster.Vttablet{srcMaster, srcReplica, srcRdonly}, + } + for idx := range shard1.Vttablets { + shard1.Vttablets[idx].VttabletProcess.Shard = shard1.Name + } + localCluster.Keyspaces[0].Shards = append(localCluster.Keyspaces[0].Shards, shard1) + + shard2 := cluster.Shard{ + Name: "-", + Vttablets: []*cluster.Vttablet{destMaster, destReplica, destRdonly}, + } + for idx := range shard2.Vttablets { + shard2.Vttablets[idx].VttabletProcess.Shard = shard2.Name + } + localCluster.Keyspaces[0].Shards = append(localCluster.Keyspaces[0].Shards, shard2) + + for _, tablet := range shard1.Vttablets { + if err := localCluster.VtctlclientProcess.InitTablet(tablet, cell, keyspaceName, hostname, shard1.Name); err != nil { + return 1, err + } + if err := tablet.VttabletProcess.Setup(); err != nil { + return 1, err + } + } + if err := localCluster.VtctlclientProcess.InitShardMaster(keyspaceName, shard1.Name, cell, srcMaster.TabletUID); err != nil { + return 1, err + } + + if err := localCluster.VtctlclientProcess.ApplySchema(keyspaceName, fmt.Sprintf(sqlSchema, tableName)); err != nil { + return 1, err + } + if err := localCluster.VtctlclientProcess.ApplyVSchema(keyspaceName, fmt.Sprintf(vSchema, tableName)); err != nil { + return 1, err + } + + // run a health check on source replica so it responds to discovery + // (for binlog players) and on the source rdonlys (for workers) + for _, tablet := range []string{srcReplica.Alias, srcRdonly.Alias} { + if err := localCluster.VtctlclientProcess.ExecuteCommand("RunHealthCheck", tablet); err != nil { + return 1, err + } + } + + // Create destination shard (won't be serving as there is no DB) + for _, tablet := range shard2.Vttablets { + if err := localCluster.VtctlclientProcess.InitTablet(tablet, cell, keyspaceName, hostname, shard2.Name); err != nil { + return 1, err + } + if err := tablet.VttabletProcess.Setup(); err != nil { + return 1, err + } + } + + if err := localCluster.VtctlclientProcess.InitShardMaster(keyspaceName, shard2.Name, cell, destMaster.TabletUID); err != nil { + return 1, err + } + _ = localCluster.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", keyspaceName) + // Copy schema + if err := localCluster.VtctlclientProcess.ExecuteCommand("CopySchemaShard", srcReplica.Alias, fmt.Sprintf("%s/%s", keyspaceName, shard2.Name)); err != nil { + return 1, err + } + + // run the clone worker (this is a degenerate case, source and destination + // both have the full keyrange. Happens to work correctly). + localCluster.VtworkerProcess = *cluster.VtworkerProcessInstance(localCluster.GetAndReservePort(), + localCluster.GetAndReservePort(), + localCluster.TopoPort, + localCluster.Hostname, + localCluster.TmpDirectory) + localCluster.VtworkerProcess.Cell = cell + if err := localCluster.VtworkerProcess.ExecuteVtworkerCommand(localCluster.VtworkerProcess.Port, + localCluster.VtworkerProcess.GrpcPort, "--use_v3_resharding_mode=true", + "SplitClone", + "--chunk_count", "10", + "--min_rows_per_chunk", "1", + "--exclude_tables", "unrelated", + "--min_healthy_rdonly_tablets", "1", + fmt.Sprintf("%s/%s", keyspaceName, shard1.Name)); err != nil { + return 1, err + } + if err := destMaster.VttabletProcess.WaitForBinLogPlayerCount(1); err != nil { + return 1, err + } + // Wait for dst_replica to be ready. + if err := destReplica.VttabletProcess.WaitForBinlogServerState("Enabled"); err != nil { + return 1, err + } + return m.Run(), nil + }() + if err != nil { + fmt.Printf("%v\n", err) + os.Exit(1) + } else { + os.Exit(exitcode) + } +} + +// Insert something that will replicate incorrectly if the charset is not +// propagated through binlog streamer to the destination. + +// Vitess tablets default to using utf8, so we insert something crazy and +// pretend it's latin1. If the binlog player doesn't also pretend it's +// latin1, it will be inserted as utf8, which will change its value. +func TestCharset(t *testing.T) { + defer cluster.PanicHandler(t) + position, _ := cluster.GetMasterPosition(t, *destReplica, hostname) + + _, err := queryTablet(t, *srcMaster, fmt.Sprintf(insertSql, tableName, 1, "Šṛ́rỏé"), "latin1") + require.Nil(t, err) + println("Waiting to get rows in dest master tablet") + waitForReplicaEvent(t, position, "1", *destReplica) + + verifyData(t, 1, "latin1", `[UINT64(1) VARCHAR("Šṛ́rỏé")]`) +} + +// Enable binlog_checksum, which will also force a log rotation that should +// cause binlog streamer to notice the new checksum setting. +func TestChecksumEnabled(t *testing.T) { + defer cluster.PanicHandler(t) + position, _ := cluster.GetMasterPosition(t, *destReplica, hostname) + _, err := queryTablet(t, *destReplica, "SET @@global.binlog_checksum=1", "") + require.Nil(t, err) + + // Insert something and make sure it comes through intact. + _, err = queryTablet(t, *srcMaster, fmt.Sprintf(insertSql, tableName, 2, "value - 2"), "") + require.Nil(t, err) + + // Look for it using update stream to see if binlog streamer can talk to + // dest_replica, which now has binlog_checksum enabled. + waitForReplicaEvent(t, position, "2", *destReplica) + + verifyData(t, 2, "", `[UINT64(2) VARCHAR("value - 2")]`) +} + +// Disable binlog_checksum to make sure we can also talk to a server without +// checksums enabled, in case they are enabled by default +func TestChecksumDisabled(t *testing.T) { + defer cluster.PanicHandler(t) + position, _ := cluster.GetMasterPosition(t, *destReplica, hostname) + + _, err := queryTablet(t, *destReplica, "SET @@global.binlog_checksum=0", "") + require.Nil(t, err) + + // Insert something and make sure it comes through intact. + _, err = queryTablet(t, *srcMaster, fmt.Sprintf(insertSql, tableName, 3, "value - 3"), "") + require.Nil(t, err) + + // Look for it using update stream to see if binlog streamer can talk to + // dest_replica, which now has binlog_checksum disabled. + waitForReplicaEvent(t, position, "3", *destReplica) + + verifyData(t, 3, "", `[UINT64(3) VARCHAR("value - 3")]`) +} + +// Wait for a replica event with the given SQL string. +func waitForReplicaEvent(t *testing.T, position string, pkKey string, vttablet cluster.Vttablet) { + timeout := time.Now().Add(10 * time.Second) + for time.Now().Before(timeout) { + println("fetching with position " + position) + output, err := localCluster.VtctlclientProcess.ExecuteCommandWithOutput("VtTabletUpdateStream", "-position", position, "-count", "1", vttablet.Alias) + require.Nil(t, err) + + var binlogStreamEvent query.StreamEvent + err = json.Unmarshal([]byte(output), &binlogStreamEvent) + require.Nil(t, err) + for _, statement := range binlogStreamEvent.Statements { + if isCurrentRowPresent(*statement, pkKey) { + return + } + } + time.Sleep(300 * time.Millisecond) + position = binlogStreamEvent.EventToken.Position + } +} + +func isCurrentRowPresent(statement query.StreamEvent_Statement, pkKey string) bool { + if statement.TableName == tableName && + statement.PrimaryKeyFields[0].Name == "id" && + fmt.Sprintf("%s", statement.PrimaryKeyValues[0].Values) == pkKey { + return true + } + return false +} + +func verifyData(t *testing.T, id uint64, charset string, expectedOutput string) { + data, err := queryTablet(t, *destMaster, fmt.Sprintf("select id, msg from %s where id = %d", tableName, id), charset) + require.Nil(t, err) + assert.NotNil(t, data.Rows) + rowFound := assert.Equal(t, len(data.Rows), 1) + assert.Equal(t, len(data.Fields), 2) + if rowFound { + assert.Equal(t, fmt.Sprintf("%v", data.Rows[0]), expectedOutput) + } +} + +func queryTablet(t *testing.T, vttablet cluster.Vttablet, query string, charset string) (*sqltypes.Result, error) { + dbParams := mysql.ConnParams{ + Uname: "vt_dba", + UnixSocket: path.Join(vttablet.VttabletProcess.Directory, "mysql.sock"), + + DbName: fmt.Sprintf("vt_%s", keyspaceName), + } + if charset != "" { + dbParams.Charset = charset + } + ctx := context.Background() + dbConn, err := mysql.Connect(ctx, &dbParams) + require.Nil(t, err) + defer dbConn.Close() + return dbConn.ExecuteFetch(query, 1000, true) +} diff --git a/go/test/endtoend/cellalias/cell_alias_test.go b/go/test/endtoend/cellalias/cell_alias_test.go new file mode 100644 index 00000000000..b0ed2d9f358 --- /dev/null +++ b/go/test/endtoend/cellalias/cell_alias_test.go @@ -0,0 +1,339 @@ +/* +Copyright 2019 The Vitess Authors. + +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 test cell aliases feature + +We start with no aliases and assert that vtgates can't route to replicas/rondly tablets. +Then we add an alias, and these tablets should be routable +*/ + +package binlog + +import ( + "encoding/json" + "flag" + "fmt" + "os" + "os/exec" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/test/endtoend/cluster" + "vitess.io/vitess/go/test/endtoend/sharding" + "vitess.io/vitess/go/vt/proto/topodata" +) + +var ( + localCluster *cluster.LocalProcessCluster + cell1 = "zone1" + cell2 = "zone2" + hostname = "localhost" + keyspaceName = "ks" + tableName = "test_table" + sqlSchema = ` + create table %s( + id bigint(20) unsigned auto_increment, + msg varchar(64), + primary key (id), + index by_msg (msg) + ) Engine=InnoDB +` + commonTabletArg = []string{ + "-vreplication_healthcheck_topology_refresh", "1s", + "-vreplication_healthcheck_retry_delay", "1s", + "-vreplication_retry_delay", "1s", + "-degraded_threshold", "5s", + "-lock_tables_timeout", "5s", + "-watch_replication_stream", + "-enable_replication_reporter", + "-serving_state_grace_period", "1s", + "-binlog_player_protocol", "grpc", + "-enable-autocommit", + } + vSchema = ` + { + "sharded": true, + "vindexes": { + "hash_index": { + "type": "hash" + } + }, + "tables": { + "%s": { + "column_vindexes": [ + { + "column": "id", + "name": "hash_index" + } + ] + } + } + } +` + shard1Master *cluster.Vttablet + shard1Replica *cluster.Vttablet + shard1Rdonly *cluster.Vttablet + shard2Master *cluster.Vttablet + shard2Replica *cluster.Vttablet + shard2Rdonly *cluster.Vttablet +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitcode, err := func() (int, error) { + localCluster = cluster.NewCluster(cell1, hostname) + defer localCluster.Teardown() + localCluster.Keyspaces = append(localCluster.Keyspaces, cluster.Keyspace{ + Name: keyspaceName, + }) + + // Start topo server + if err := localCluster.StartTopo(); err != nil { + return 1, err + } + + // Adding another cell in the same cluster + err := localCluster.TopoProcess.ManageTopoDir("mkdir", "/vitess/"+cell2) + if err != nil { + return 1, err + } + err = localCluster.VtctlProcess.AddCellInfo(cell2) + if err != nil { + return 1, err + } + + shard1Master = localCluster.GetVttabletInstance("master", 0, "") + shard1Replica = localCluster.GetVttabletInstance("replica", 0, cell2) + shard1Rdonly = localCluster.GetVttabletInstance("rdonly", 0, cell2) + + shard2Master = localCluster.GetVttabletInstance("master", 0, "") + shard2Replica = localCluster.GetVttabletInstance("replica", 0, cell2) + shard2Rdonly = localCluster.GetVttabletInstance("rdonly", 0, cell2) + + var mysqlProcs []*exec.Cmd + for _, tablet := range []*cluster.Vttablet{shard1Master, shard1Replica, shard1Rdonly, shard2Master, shard2Replica, shard2Rdonly} { + tablet.MysqlctlProcess = *cluster.MysqlCtlProcessInstance(tablet.TabletUID, tablet.MySQLPort, localCluster.TmpDirectory) + tablet.VttabletProcess = cluster.VttabletProcessInstance(tablet.HTTPPort, + tablet.GrpcPort, + tablet.TabletUID, + tablet.Cell, + "", + keyspaceName, + localCluster.VtctldProcess.Port, + tablet.Type, + localCluster.TopoPort, + hostname, + localCluster.TmpDirectory, + commonTabletArg, + true, + ) + tablet.VttabletProcess.SupportsBackup = true + proc, err := tablet.MysqlctlProcess.StartProcess() + if err != nil { + return 1, err + } + mysqlProcs = append(mysqlProcs, proc) + } + for _, proc := range mysqlProcs { + if err := proc.Wait(); err != nil { + return 1, err + } + } + + if err := localCluster.VtctlProcess.CreateKeyspace(keyspaceName); err != nil { + return 1, err + } + + shard1 := cluster.Shard{ + Name: "-80", + Vttablets: []*cluster.Vttablet{shard1Master, shard1Replica, shard1Rdonly}, + } + for idx := range shard1.Vttablets { + shard1.Vttablets[idx].VttabletProcess.Shard = shard1.Name + } + localCluster.Keyspaces[0].Shards = append(localCluster.Keyspaces[0].Shards, shard1) + + shard2 := cluster.Shard{ + Name: "80-", + Vttablets: []*cluster.Vttablet{shard2Master, shard2Replica, shard2Rdonly}, + } + for idx := range shard2.Vttablets { + shard2.Vttablets[idx].VttabletProcess.Shard = shard2.Name + } + localCluster.Keyspaces[0].Shards = append(localCluster.Keyspaces[0].Shards, shard2) + + for _, tablet := range shard1.Vttablets { + if err := localCluster.VtctlclientProcess.InitTablet(tablet, tablet.Cell, keyspaceName, hostname, shard1.Name); err != nil { + return 1, err + } + if err := tablet.VttabletProcess.CreateDB(keyspaceName); err != nil { + return 1, err + } + if err := tablet.VttabletProcess.Setup(); err != nil { + return 1, err + } + } + if err := localCluster.VtctlclientProcess.InitShardMaster(keyspaceName, shard1.Name, shard1Master.Cell, shard1Master.TabletUID); err != nil { + return 1, err + } + + // run a health check on source replica so it responds to discovery + // (for binlog players) and on the source rdonlys (for workers) + for _, tablet := range []string{shard1Replica.Alias, shard1Rdonly.Alias} { + if err := localCluster.VtctlclientProcess.ExecuteCommand("RunHealthCheck", tablet); err != nil { + return 1, err + } + } + + for _, tablet := range shard2.Vttablets { + if err := localCluster.VtctlclientProcess.InitTablet(tablet, tablet.Cell, keyspaceName, hostname, shard2.Name); err != nil { + return 1, err + } + if err := tablet.VttabletProcess.CreateDB(keyspaceName); err != nil { + return 1, err + } + if err := tablet.VttabletProcess.Setup(); err != nil { + return 1, err + } + } + + if err := localCluster.VtctlclientProcess.InitShardMaster(keyspaceName, shard2.Name, shard2Master.Cell, shard2Master.TabletUID); err != nil { + return 1, err + } + + if err := localCluster.VtctlclientProcess.ApplySchema(keyspaceName, fmt.Sprintf(sqlSchema, tableName)); err != nil { + return 1, err + } + if err := localCluster.VtctlclientProcess.ApplyVSchema(keyspaceName, fmt.Sprintf(vSchema, tableName)); err != nil { + return 1, err + } + + _ = localCluster.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", keyspaceName) + + return m.Run(), nil + }() + if err != nil { + fmt.Printf("%v\n", err) + os.Exit(1) + } else { + os.Exit(exitcode) + } +} + +func TestAlias(t *testing.T) { + defer cluster.PanicHandler(t) + insertInitialValues(t) + err := localCluster.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", keyspaceName) + require.Nil(t, err) + shard1 := localCluster.Keyspaces[0].Shards[0] + shard2 := localCluster.Keyspaces[0].Shards[1] + allCells := fmt.Sprintf("%s,%s", cell1, cell2) + + expectedPartitions := map[topodata.TabletType][]string{} + expectedPartitions[topodata.TabletType_MASTER] = []string{shard1.Name, shard2.Name} + expectedPartitions[topodata.TabletType_REPLICA] = []string{shard1.Name, shard2.Name} + expectedPartitions[topodata.TabletType_RDONLY] = []string{shard1.Name, shard2.Name} + sharding.CheckSrvKeyspace(t, cell1, keyspaceName, "", 0, expectedPartitions, *localCluster) + sharding.CheckSrvKeyspace(t, cell2, keyspaceName, "", 0, expectedPartitions, *localCluster) + + // Adds alias so vtgate can route to replica/rdonly tablets that are not in the same cell, but same alias + err = localCluster.VtctlclientProcess.ExecuteCommand("AddCellsAlias", + "-cells", allCells, + "region_east_coast") + require.Nil(t, err) + err = localCluster.VtctlclientProcess.ExecuteCommand("UpdateCellsAlias", + "-cells", allCells, + "region_east_coast") + require.Nil(t, err) + + vtgateInstance := localCluster.GetVtgateInstance() + vtgateInstance.CellsToWatch = allCells + vtgateInstance.TabletTypesToWait = "MASTER,REPLICA" + err = vtgateInstance.Setup() + require.Nil(t, err) + waitTillAllTabletsAreHealthyInVtgate(t, *vtgateInstance, shard1.Name, shard2.Name) + + testQueriesInDifferentTabletType(t, "master", vtgateInstance.GrpcPort, false) + testQueriesInDifferentTabletType(t, "replica", vtgateInstance.GrpcPort, false) + testQueriesInDifferentTabletType(t, "rdonly", vtgateInstance.GrpcPort, false) + + // now, delete the alias, so that if we run above assertions again, it will fail for replica,rdonly target type + err = localCluster.VtctlclientProcess.ExecuteCommand("DeleteCellsAlias", + "region_east_coast") + require.Nil(t, err) + + // restarts the vtgate process + _ = vtgateInstance.TearDown() + vtgateInstance.TabletTypesToWait = "MASTER" + err = vtgateInstance.Setup() + require.Nil(t, err) + + // since replica and rdonly tablets of all shards in cell2, the last 2 assertion is expected to fail + testQueriesInDifferentTabletType(t, "master", vtgateInstance.GrpcPort, false) + testQueriesInDifferentTabletType(t, "replica", vtgateInstance.GrpcPort, true) + testQueriesInDifferentTabletType(t, "rdonly", vtgateInstance.GrpcPort, true) +} + +func waitTillAllTabletsAreHealthyInVtgate(t *testing.T, vtgateInstance cluster.VtgateProcess, shards ...string) { + for _, shard := range shards { + err := vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.master", keyspaceName, shard), 1) + require.Nil(t, err) + err = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.replica", keyspaceName, shard), 1) + require.Nil(t, err) + err = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.rdonly", keyspaceName, shard), 1) + require.Nil(t, err) + } +} + +func testQueriesInDifferentTabletType(t *testing.T, tabletType string, vtgateGrpcPort int, shouldFail bool) { + output, err := localCluster.VtctlProcess.ExecuteCommandWithOutput("VtGateExecute", "-json", + "-server", fmt.Sprintf("%s:%d", localCluster.Hostname, vtgateGrpcPort), + "-target", "@"+tabletType, + fmt.Sprintf(`select * from %s`, tableName)) + if shouldFail { + require.Error(t, err) + return + } + require.Nil(t, err) + var result sqltypes.Result + + err = json.Unmarshal([]byte(output), &result) + require.Nil(t, err) + assert.Equal(t, len(result.Rows), 3) +} + +func insertInitialValues(t *testing.T) { + sharding.InsertToTablet(t, + fmt.Sprintf(sharding.InsertTabletTemplateKsID, tableName, 1, "msg1", 1), + *shard1Master, + keyspaceName, + false) + + sharding.InsertToTablet(t, + fmt.Sprintf(sharding.InsertTabletTemplateKsID, tableName, 2, "msg2", 2), + *shard1Master, + keyspaceName, + false) + + sharding.InsertToTablet(t, + fmt.Sprintf(sharding.InsertTabletTemplateKsID, tableName, 4, "msg4", 4), + *shard2Master, + keyspaceName, + false) +} diff --git a/go/test/endtoend/cluster/cluster_process.go b/go/test/endtoend/cluster/cluster_process.go index 780917918ce..ac6c113272d 100644 --- a/go/test/endtoend/cluster/cluster_process.go +++ b/go/test/endtoend/cluster/cluster_process.go @@ -17,21 +17,33 @@ limitations under the License. package cluster import ( + "context" "flag" "fmt" + "io/ioutil" "math/rand" "os" + "os/exec" + "os/signal" "path" + "strconv" + "sync" + "syscall" "time" "vitess.io/vitess/go/vt/log" ) // DefaultCell : If no cell name is passed, then use following -const DefaultCell = "zone1" +const ( + DefaultCell = "zone1" + DefaultStartPort = 6700 +) var ( - keepData = flag.Bool("keep-data", false, "don't delete the per-test VTDATAROOT subfolders") + keepData = flag.Bool("keep-data", false, "don't delete the per-test VTDATAROOT subfolders") + topoFlavor = flag.String("topo-flavor", "etcd2", "choose a topo server from etcd2, zk2 or consul") + isCoverage = flag.Bool("is-coverage", false, "whether coverage is required") ) // LocalProcessCluster Testcases need to use this to iniate a cluster @@ -54,9 +66,11 @@ type LocalProcessCluster struct { VtctlProcess VtctlProcess // background executable processes - topoProcess EtcdProcess - vtctldProcess VtctldProcess - VtgateProcess VtgateProcess + TopoProcess TopoProcess + VtctldProcess VtctldProcess + VtgateProcess VtgateProcess + VtworkerProcess VtworkerProcess + VtbackupProcess VtbackupProcess nextPortForProcess int @@ -65,6 +79,33 @@ type LocalProcessCluster struct { //Extra arguments for vtGate VtGateExtraArgs []string + + VtctldExtraArgs []string + + EnableSemiSync bool + + // mutex added to handle the parallel teardowns + mx *sync.Mutex + teardownCompleted bool + + context.Context + context.CancelFunc +} + +// Vttablet stores the properties needed to start a vttablet process +type Vttablet struct { + Type string + TabletUID int + HTTPPort int + GrpcPort int + MySQLPort int + Alias string + Cell string + + // background executable processes + MysqlctlProcess MysqlctlProcess + MysqlctldProcess MysqlctldProcess + VttabletProcess *VttabletProcess } // Keyspace : Cluster accepts keyspace to launch it @@ -78,20 +119,47 @@ type Keyspace struct { // Shard with associated vttablets type Shard struct { Name string - Vttablets []Vttablet + Vttablets []*Vttablet } -// Vttablet stores the properties needed to start a vttablet process -type Vttablet struct { - Type string - TabletUID int - HTTPPort int - GrpcPort int - MySQLPort int +// MasterTablet get the 1st tablet which is master +func (shard *Shard) MasterTablet() *Vttablet { + return shard.Vttablets[0] +} - // background executable processes - mysqlctlProcess MysqlctlProcess - vttabletProcess VttabletProcess +// Rdonly get the last tablet which is rdonly +func (shard *Shard) Rdonly() *Vttablet { + for idx, tablet := range shard.Vttablets { + if tablet.Type == "rdonly" { + return shard.Vttablets[idx] + } + } + return nil +} + +// Replica get the last but one tablet which is replica +// Mostly we have either 3 tablet setup [master, replica, rdonly] +func (shard *Shard) Replica() *Vttablet { + for idx, tablet := range shard.Vttablets { + if tablet.Type == "replica" && idx > 0 { + return shard.Vttablets[idx] + } + } + return nil +} + +// CtrlCHandler handles the teardown for the ctrl-c. +func (cluster *LocalProcessCluster) CtrlCHandler() { + cluster.Context, cluster.CancelFunc = context.WithCancel(context.Background()) + + c := make(chan os.Signal, 2) + signal.Notify(c, os.Interrupt, syscall.SIGTERM) + select { + case <-c: + cluster.Teardown() + os.Exit(0) + case <-cluster.Done(): + } } // StartTopo starts topology server @@ -101,40 +169,45 @@ func (cluster *LocalProcessCluster) StartTopo() (err error) { } cluster.TopoPort = cluster.GetAndReservePort() cluster.TmpDirectory = path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("/tmp_%d", cluster.GetAndReservePort())) - cluster.topoProcess = *EtcdProcessInstance(cluster.TopoPort, cluster.GetAndReservePort(), cluster.Hostname, "global") - log.Info(fmt.Sprintf("Starting etcd server on port : %d", cluster.TopoPort)) - if err = cluster.topoProcess.Setup(); err != nil { - log.Error(err.Error()) - return - } + cluster.TopoProcess = *TopoProcessInstance(cluster.TopoPort, cluster.GetAndReservePort(), cluster.Hostname, *topoFlavor, "global") - log.Info("Creating topo dirs") - if err = cluster.topoProcess.ManageTopoDir("mkdir", "/vitess/global"); err != nil { + log.Info(fmt.Sprintf("Starting topo server %v on port : %d", topoFlavor, cluster.TopoPort)) + if err = cluster.TopoProcess.Setup(*topoFlavor, cluster); err != nil { log.Error(err.Error()) return } - if err = cluster.topoProcess.ManageTopoDir("mkdir", "/vitess/"+cluster.Cell); err != nil { - log.Error(err.Error()) - return + if *topoFlavor == "etcd2" { + log.Info("Creating topo dirs") + if err = cluster.TopoProcess.ManageTopoDir("mkdir", "/vitess/global"); err != nil { + log.Error(err.Error()) + return + } + + if err = cluster.TopoProcess.ManageTopoDir("mkdir", "/vitess/"+cluster.Cell); err != nil { + log.Error(err.Error()) + return + } } log.Info("Adding cell info") - cluster.VtctlProcess = *VtctlProcessInstance(cluster.topoProcess.Port, cluster.Hostname) + cluster.VtctlProcess = *VtctlProcessInstance(cluster.TopoProcess.Port, cluster.Hostname) if err = cluster.VtctlProcess.AddCellInfo(cluster.Cell); err != nil { log.Error(err) return } - cluster.vtctldProcess = *VtctldProcessInstance(cluster.GetAndReservePort(), cluster.GetAndReservePort(), cluster.topoProcess.Port, cluster.Hostname, cluster.TmpDirectory) - log.Info(fmt.Sprintf("Starting vtctld server on port : %d", cluster.vtctldProcess.Port)) - cluster.VtctldHTTPPort = cluster.vtctldProcess.Port - if err = cluster.vtctldProcess.Setup(cluster.Cell); err != nil { + cluster.VtctldProcess = *VtctldProcessInstance(cluster.GetAndReservePort(), cluster.GetAndReservePort(), + cluster.TopoProcess.Port, cluster.Hostname, cluster.TmpDirectory) + log.Info(fmt.Sprintf("Starting vtctld server on port : %d", cluster.VtctldProcess.Port)) + cluster.VtctldHTTPPort = cluster.VtctldProcess.Port + if err = cluster.VtctldProcess.Setup(cluster.Cell, cluster.VtctldExtraArgs...); err != nil { + log.Error(err.Error()) return } - cluster.VtctlclientProcess = *VtctlClientProcessInstance("localhost", cluster.vtctldProcess.GrpcPort, cluster.TmpDirectory) + cluster.VtctlclientProcess = *VtctlClientProcessInstance("localhost", cluster.VtctldProcess.GrpcPort, cluster.TmpDirectory) return } @@ -153,21 +226,25 @@ func (cluster *LocalProcessCluster) StartKeyspace(keyspace Keyspace, shardNames if rdonly { totalTabletsRequired = totalTabletsRequired + 1 // + 1 for rdonly } - shards := make([]Shard, 0) + log.Info("Starting keyspace : " + keyspace.Name) _ = cluster.VtctlProcess.CreateKeyspace(keyspace.Name) + var mysqlctlProcessList []*exec.Cmd for _, shardName := range shardNames { shard := &Shard{ Name: shardName, } log.Info("Starting shard : " + shardName) + mysqlctlProcessList = []*exec.Cmd{} for i := 0; i < totalTabletsRequired; i++ { - // instantiate vttable object with reserved ports + // instantiate vttablet object with reserved ports + tabletUID := cluster.GetAndReserveTabletUID() tablet := &Vttablet{ - TabletUID: cluster.GetAndReserveTabletUID(), + TabletUID: tabletUID, HTTPPort: cluster.GetAndReservePort(), GrpcPort: cluster.GetAndReservePort(), MySQLPort: cluster.GetAndReservePort(), + Alias: fmt.Sprintf("%s-%010d", cluster.Cell, tabletUID), } if i == 0 { // Make the first one as master tablet.Type = "master" @@ -176,33 +253,51 @@ func (cluster *LocalProcessCluster) StartKeyspace(keyspace Keyspace, shardNames } // Start Mysqlctl process log.Info(fmt.Sprintf("Starting mysqlctl for table uid %d, mysql port %d", tablet.TabletUID, tablet.MySQLPort)) - tablet.mysqlctlProcess = *MysqlCtlProcessInstance(tablet.TabletUID, tablet.MySQLPort, cluster.TmpDirectory) - if err = tablet.mysqlctlProcess.Start(); err != nil { + tablet.MysqlctlProcess = *MysqlCtlProcessInstance(tablet.TabletUID, tablet.MySQLPort, cluster.TmpDirectory) + proc, err := tablet.MysqlctlProcess.StartProcess() + if err != nil { log.Error(err.Error()) - return + return err } + mysqlctlProcessList = append(mysqlctlProcessList, proc) // start vttablet process - tablet.vttabletProcess = *VttabletProcessInstance(tablet.HTTPPort, + tablet.VttabletProcess = VttabletProcessInstance(tablet.HTTPPort, tablet.GrpcPort, tablet.TabletUID, cluster.Cell, shardName, keyspace.Name, - cluster.vtctldProcess.Port, + cluster.VtctldProcess.Port, tablet.Type, - cluster.topoProcess.Port, + cluster.TopoProcess.Port, cluster.Hostname, cluster.TmpDirectory, - cluster.VtTabletExtraArgs) - log.Info(fmt.Sprintf("Starting vttablet for tablet uid %d, grpc port %d", tablet.TabletUID, tablet.GrpcPort)) + cluster.VtTabletExtraArgs, + cluster.EnableSemiSync) + tablet.Alias = tablet.VttabletProcess.TabletPath + shard.Vttablets = append(shard.Vttablets, tablet) + } - if err = tablet.vttabletProcess.Setup(); err != nil { + // wait till all mysqlctl is instantiated + for _, proc := range mysqlctlProcessList { + if err = proc.Wait(); err != nil { + log.Errorf("Unable to start mysql , error %v", err.Error()) + return err + } + } + for _, tablet := range shard.Vttablets { + if _, err = tablet.VttabletProcess.QueryTablet(fmt.Sprintf("create database vt_%s", keyspace.Name), keyspace.Name, false); err != nil { log.Error(err.Error()) return } - shard.Vttablets = append(shard.Vttablets, *tablet) + log.Info(fmt.Sprintf("Starting vttablet for tablet uid %d, grpc port %d", tablet.TabletUID, tablet.GrpcPort)) + + if err = tablet.VttabletProcess.Setup(); err != nil { + log.Error(err.Error()) + return + } } // Make first tablet as master @@ -210,16 +305,26 @@ func (cluster *LocalProcessCluster) StartKeyspace(keyspace Keyspace, shardNames log.Error(err.Error()) return } - - shards = append(shards, *shard) + keyspace.Shards = append(keyspace.Shards, *shard) + } + // if the keyspace is present then append the shard info + existingKeyspace := false + for idx, ks := range cluster.Keyspaces { + if ks.Name == keyspace.Name { + cluster.Keyspaces[idx].Shards = append(cluster.Keyspaces[idx].Shards, keyspace.Shards...) + existingKeyspace = true + } + } + if !existingKeyspace { + cluster.Keyspaces = append(cluster.Keyspaces, keyspace) } - keyspace.Shards = shards - cluster.Keyspaces = append(cluster.Keyspaces, keyspace) // Apply Schema SQL - if err = cluster.VtctlclientProcess.ApplySchema(keyspace.Name, keyspace.SchemaSQL); err != nil { - log.Error(err.Error()) - return + if keyspace.SchemaSQL != "" { + if err = cluster.VtctlclientProcess.ApplySchema(keyspace.Name, keyspace.SchemaSQL); err != nil { + log.Error(err.Error()) + return + } } //Apply VSchema @@ -234,13 +339,78 @@ func (cluster *LocalProcessCluster) StartKeyspace(keyspace Keyspace, shardNames return } +// LaunchCluster creates the skeleton for a cluster by creating keyspace +// shards and initializing tablets and mysqlctl processes. +// This does not start any process and user have to explicitly start all +// the required services (ex topo, vtgate, mysql and vttablet) +func (cluster *LocalProcessCluster) LaunchCluster(keyspace *Keyspace, shards []Shard) (err error) { + + log.Info("Starting keyspace : " + keyspace.Name) + + // Create Keyspace + err = cluster.VtctlProcess.CreateKeyspace(keyspace.Name) + if err != nil { + log.Error(err) + return + } + + // Create shard + for _, shard := range shards { + for _, tablet := range shard.Vttablets { + + // Setup MysqlctlProcess + tablet.MysqlctlProcess = *MysqlCtlProcessInstance(tablet.TabletUID, tablet.MySQLPort, cluster.TmpDirectory) + // Setup VttabletProcess + tablet.VttabletProcess = VttabletProcessInstance( + tablet.HTTPPort, + tablet.GrpcPort, + tablet.TabletUID, + tablet.Cell, + shard.Name, + keyspace.Name, + cluster.VtctldProcess.Port, + tablet.Type, + cluster.TopoProcess.Port, + cluster.Hostname, + cluster.TmpDirectory, + cluster.VtTabletExtraArgs, + cluster.EnableSemiSync) + } + + keyspace.Shards = append(keyspace.Shards, shard) + } + + // if the keyspace is present then append the shard info + existingKeyspace := false + for idx, ks := range cluster.Keyspaces { + if ks.Name == keyspace.Name { + cluster.Keyspaces[idx].Shards = append(cluster.Keyspaces[idx].Shards, keyspace.Shards...) + existingKeyspace = true + } + } + if !existingKeyspace { + cluster.Keyspaces = append(cluster.Keyspaces, *keyspace) + } + + log.Info("Done launching keyspace : " + keyspace.Name) + return err +} + // StartVtgate starts vtgate func (cluster *LocalProcessCluster) StartVtgate() (err error) { + vtgateInstance := *cluster.GetVtgateInstance() + cluster.VtgateProcess = vtgateInstance + log.Info(fmt.Sprintf("Starting vtgate on port %d", vtgateInstance.Port)) + log.Info(fmt.Sprintf("Vtgate started, connect to mysql using : mysql -h 127.0.0.1 -P %d", cluster.VtgateMySQLPort)) + return cluster.VtgateProcess.Setup() +} + +// GetVtgateInstance returns an instance of vtgateprocess +func (cluster *LocalProcessCluster) GetVtgateInstance() *VtgateProcess { vtgateHTTPPort := cluster.GetAndReservePort() vtgateGrpcPort := cluster.GetAndReservePort() cluster.VtgateMySQLPort = cluster.GetAndReservePort() - log.Info(fmt.Sprintf("Starting vtgate on port %d", vtgateHTTPPort)) - cluster.VtgateProcess = *VtgateProcessInstance( + vtgateProcInstance := VtgateProcessInstance( vtgateHTTPPort, vtgateGrpcPort, cluster.VtgateMySQLPort, @@ -248,17 +418,16 @@ func (cluster *LocalProcessCluster) StartVtgate() (err error) { cluster.Cell, cluster.Hostname, "MASTER,REPLICA", - cluster.topoProcess.Port, + cluster.TopoProcess.Port, cluster.TmpDirectory, cluster.VtGateExtraArgs) - - log.Info(fmt.Sprintf("Vtgate started, connect to mysql using : mysql -h 127.0.0.1 -P %d", cluster.VtgateMySQLPort)) - return cluster.VtgateProcess.Setup() + return vtgateProcInstance } // NewCluster instantiates a new cluster func NewCluster(cell string, hostname string) *LocalProcessCluster { - cluster := &LocalProcessCluster{Cell: cell, Hostname: hostname} + cluster := &LocalProcessCluster{Cell: cell, Hostname: hostname, mx: new(sync.Mutex)} + go cluster.CtrlCHandler() cluster.OriginalVTDATAROOT = os.Getenv("VTDATAROOT") cluster.CurrentVTDATAROOT = path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("vtroot_%d", cluster.GetAndReservePort())) _ = createDirectory(cluster.CurrentVTDATAROOT, 0700) @@ -282,50 +451,156 @@ func (cluster *LocalProcessCluster) ReStartVtgate() (err error) { return err } +// WaitForTabletsToHealthyInVtgate waits for all tablets in all shards to be healthy as per vtgate +func (cluster *LocalProcessCluster) WaitForTabletsToHealthyInVtgate() (err error) { + var isRdOnlyPresent bool + for _, keyspace := range cluster.Keyspaces { + for _, shard := range keyspace.Shards { + isRdOnlyPresent = false + if err = cluster.VtgateProcess.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.master", keyspace.Name, shard.Name), 1); err != nil { + return err + } + if err = cluster.VtgateProcess.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.replica", keyspace.Name, shard.Name), 1); err != nil { + return err + } + for _, tablet := range shard.Vttablets { + if tablet.Type == "rdonly" { + isRdOnlyPresent = true + } + } + if isRdOnlyPresent { + err = cluster.VtgateProcess.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.rdonly", keyspace.Name, shard.Name), 1) + } + if err != nil { + return err + } + } + } + return nil +} + // Teardown brings down the cluster by invoking teardown for individual processes -func (cluster *LocalProcessCluster) Teardown() (err error) { - if err = cluster.VtgateProcess.TearDown(); err != nil { - log.Error(err.Error()) +func (cluster *LocalProcessCluster) Teardown() { + PanicHandler(nil) + cluster.mx.Lock() + defer cluster.mx.Unlock() + if cluster.teardownCompleted { return } + if cluster.CancelFunc != nil { + cluster.CancelFunc() + } + if err := cluster.VtgateProcess.TearDown(); err != nil { + log.Errorf("Error in vtgate teardown - %s", err.Error()) + } + var mysqlctlProcessList []*exec.Cmd for _, keyspace := range cluster.Keyspaces { for _, shard := range keyspace.Shards { for _, tablet := range shard.Vttablets { - if err = tablet.mysqlctlProcess.Stop(); err != nil { - log.Error(err.Error()) - return + if tablet.MysqlctlProcess.TabletUID > 0 { + if proc, err := tablet.MysqlctlProcess.StopProcess(); err != nil { + log.Errorf("Error in mysqlctl teardown - %s", err.Error()) + } else { + mysqlctlProcessList = append(mysqlctlProcessList, proc) + } + } + if tablet.MysqlctldProcess.TabletUID > 0 { + if err := tablet.MysqlctldProcess.Stop(); err != nil { + log.Errorf("Error in mysqlctl teardown - %s", err.Error()) + } } - if err = tablet.vttabletProcess.TearDown(); err != nil { - log.Error(err.Error()) - return + if err := tablet.VttabletProcess.TearDown(); err != nil { + log.Errorf("Error in vttablet teardown - %s", err.Error()) } } } } - if err = cluster.vtctldProcess.TearDown(); err != nil { - log.Error(err.Error()) - return + for _, proc := range mysqlctlProcessList { + if err := proc.Wait(); err != nil { + log.Errorf("Error in mysqlctl teardown wait - %s", err.Error()) + } } - if err = cluster.topoProcess.TearDown(cluster.Cell, cluster.OriginalVTDATAROOT, cluster.CurrentVTDATAROOT, *keepData); err != nil { - log.Error(err.Error()) - return + if err := cluster.VtctldProcess.TearDown(); err != nil { + log.Errorf("Error in vtctld teardown - %s", err.Error()) } - return err + + if err := cluster.TopoProcess.TearDown(cluster.Cell, cluster.OriginalVTDATAROOT, cluster.CurrentVTDATAROOT, *keepData, *topoFlavor); err != nil { + log.Errorf("Error in topo server teardown - %s", err.Error()) + } + + cluster.teardownCompleted = true +} + +// StartVtworker starts a vtworker +func (cluster *LocalProcessCluster) StartVtworker(cell string, extraArgs ...string) error { + httpPort := cluster.GetAndReservePort() + grpcPort := cluster.GetAndReservePort() + log.Info(fmt.Sprintf("Starting vtworker on port %d", httpPort)) + cluster.VtworkerProcess = *VtworkerProcessInstance( + httpPort, + grpcPort, + cluster.TopoPort, + cluster.Hostname, + cluster.TmpDirectory) + cluster.VtworkerProcess.ExtraArgs = extraArgs + return cluster.VtworkerProcess.Setup(cell) + +} + +// StartVtbackup starts a vtbackup +func (cluster *LocalProcessCluster) StartVtbackup(newInitDBFile string, initalBackup bool, + keyspace string, shard string, cell string, extraArgs ...string) error { + log.Info("Starting vtbackup") + cluster.VtbackupProcess = *VtbackupProcessInstance( + cluster.GetAndReserveTabletUID(), + cluster.GetAndReservePort(), + newInitDBFile, + keyspace, + shard, + cell, + cluster.Hostname, + cluster.TmpDirectory, + cluster.TopoPort, + initalBackup) + cluster.VtbackupProcess.ExtraArgs = extraArgs + return cluster.VtbackupProcess.Setup() + } // GetAndReservePort gives port for required process func (cluster *LocalProcessCluster) GetAndReservePort() int { if cluster.nextPortForProcess == 0 { - cluster.nextPortForProcess = getRandomNumber(20000, 15000) + cluster.nextPortForProcess = getPort() } cluster.nextPortForProcess = cluster.nextPortForProcess + 1 return cluster.nextPortForProcess } +// getPort checks if we have recent used port info in /tmp/todaytime.port +// If no, then use a random port and save that port + 200 in the above file +// If yes, then return that port, and save port + 200 in the same file +// here, assumptions is 200 ports might be consumed for all tests in a package +func getPort() int { + tmpPortFileName := path.Join(os.TempDir(), time.Now().Format("01022006.port")) + var port int + if _, err := os.Stat(tmpPortFileName); os.IsNotExist(err) { + port = getVtStartPort() + } else { + result, _ := ioutil.ReadFile(tmpPortFileName) + cport, err := strconv.Atoi(string(result)) + if err != nil || cport > 60000 || cport == 0 { + cport = getVtStartPort() + } + port = cport + } + ioutil.WriteFile(tmpPortFileName, []byte(fmt.Sprintf("%d", port+200)), 0666) + return port +} + // GetAndReserveTabletUID gives tablet uid func (cluster *LocalProcessCluster) GetAndReserveTabletUID() int { if cluster.BaseTabletUID == 0 { @@ -338,3 +613,81 @@ func (cluster *LocalProcessCluster) GetAndReserveTabletUID() int { func getRandomNumber(maxNumber int32, baseNumber int) int { return int(rand.Int31n(maxNumber)) + baseNumber } + +func getVtStartPort() int { + osVtPort := os.Getenv("VTPORTSTART") + if osVtPort != "" { + cport, err := strconv.Atoi(string(osVtPort)) + if err == nil { + return cport + } + } + return DefaultStartPort +} + +// GetVttabletInstance creates a new vttablet object +func (cluster *LocalProcessCluster) GetVttabletInstance(tabletType string, UID int, cell string) *Vttablet { + if UID == 0 { + UID = cluster.GetAndReserveTabletUID() + } + if cell == "" { + cell = cluster.Cell + } + return &Vttablet{ + TabletUID: UID, + HTTPPort: cluster.GetAndReservePort(), + GrpcPort: cluster.GetAndReservePort(), + MySQLPort: cluster.GetAndReservePort(), + Type: tabletType, + Cell: cell, + Alias: fmt.Sprintf("%s-%010d", cell, UID), + } +} + +// GetVtprocessInstanceFromVttablet creates a new vttablet object +func (cluster *LocalProcessCluster) GetVtprocessInstanceFromVttablet(tablet *Vttablet, shardName string, ksName string) *VttabletProcess { + return VttabletProcessInstance(tablet.HTTPPort, + tablet.GrpcPort, + tablet.TabletUID, + cluster.Cell, + shardName, + ksName, + cluster.VtctldProcess.Port, + tablet.Type, + cluster.TopoProcess.Port, + cluster.Hostname, + cluster.TmpDirectory, + cluster.VtTabletExtraArgs, + cluster.EnableSemiSync) +} + +// StartVttablet starts a new tablet +func (cluster *LocalProcessCluster) StartVttablet(tablet *Vttablet, servingStatus string, + supportBackup bool, cell string, keyspaceName string, hostname string, shardName string) error { + tablet.VttabletProcess = VttabletProcessInstance( + tablet.HTTPPort, + tablet.GrpcPort, + tablet.TabletUID, + cell, + shardName, + keyspaceName, + cluster.VtctldProcess.Port, + tablet.Type, + cluster.TopoProcess.Port, + hostname, + cluster.TmpDirectory, + cluster.VtTabletExtraArgs, + cluster.EnableSemiSync) + + tablet.VttabletProcess.SupportsBackup = supportBackup + tablet.VttabletProcess.ServingStatus = servingStatus + return tablet.VttabletProcess.Setup() +} + +func getCoveragePath(fileName string) string { + covDir := os.Getenv("COV_DIR") + if covDir == "" { + covDir = os.TempDir() + } + return path.Join(covDir, fileName) +} diff --git a/go/test/endtoend/cluster/cluster_util.go b/go/test/endtoend/cluster/cluster_util.go new file mode 100644 index 00000000000..bce1cf73810 --- /dev/null +++ b/go/test/endtoend/cluster/cluster_util.go @@ -0,0 +1,235 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package cluster + +import ( + "context" + "fmt" + "os" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/assert" + + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/mysql" + tabletpb "vitess.io/vitess/go/vt/proto/topodata" + "vitess.io/vitess/go/vt/vtgate/vtgateconn" + tmc "vitess.io/vitess/go/vt/vttablet/grpctmclient" +) + +var ( + tmClient = tmc.NewClient() +) + +// Restart restarts vttablet and mysql. +func (tablet *Vttablet) Restart() error { + if tablet.MysqlctlProcess.TabletUID|tablet.MysqlctldProcess.TabletUID == 0 { + return fmt.Errorf("no mysql process is running") + } + + if tablet.MysqlctlProcess.TabletUID > 0 { + tablet.MysqlctlProcess.Stop() + tablet.VttabletProcess.TearDown() + os.RemoveAll(tablet.VttabletProcess.Directory) + + return tablet.MysqlctlProcess.Start() + } + + tablet.MysqlctldProcess.Stop() + tablet.VttabletProcess.TearDown() + os.RemoveAll(tablet.VttabletProcess.Directory) + + return tablet.MysqlctldProcess.Start() +} + +// ValidateTabletRestart restarts the tablet and validate error if there is any. +func (tablet *Vttablet) ValidateTabletRestart(t *testing.T) { + require.Nilf(t, tablet.Restart(), "tablet restart failed") +} + +// GetMasterPosition gets the master position of required vttablet +func GetMasterPosition(t *testing.T, vttablet Vttablet, hostname string) (string, string) { + ctx := context.Background() + vtablet := getTablet(vttablet.GrpcPort, hostname) + pos, err := tmClient.MasterPosition(ctx, vtablet) + require.Nil(t, err) + gtID := strings.SplitAfter(pos, "/")[1] + return pos, gtID +} + +// VerifyRowsInTablet Verify total number of rows in a tablet +func VerifyRowsInTablet(t *testing.T, vttablet *Vttablet, ksName string, expectedRows int) { + timeout := time.Now().Add(10 * time.Second) + for time.Now().Before(timeout) { + qr, err := vttablet.VttabletProcess.QueryTablet("select * from vt_insert_test", ksName, true) + require.Nil(t, err) + if len(qr.Rows) == expectedRows { + return + } + time.Sleep(300 * time.Millisecond) + } + assert.Fail(t, "expected rows not found.") +} + +// PanicHandler handles the panic in the testcase. +func PanicHandler(t *testing.T) { + err := recover() + if t == nil { + return + } + require.Nilf(t, err, "panic occured in testcase %v", t.Name()) +} + +// VerifyLocalMetadata Verify Local Metadata of a tablet +func VerifyLocalMetadata(t *testing.T, tablet *Vttablet, ksName string, shardName string, cell string) { + qr, err := tablet.VttabletProcess.QueryTablet("select * from _vt.local_metadata", ksName, false) + require.Nil(t, err) + assert.Equal(t, fmt.Sprintf("%v", qr.Rows[0][1]), fmt.Sprintf(`BLOB("%s")`, tablet.Alias)) + assert.Equal(t, fmt.Sprintf("%v", qr.Rows[1][1]), fmt.Sprintf(`BLOB("%s.%s")`, ksName, shardName)) + assert.Equal(t, fmt.Sprintf("%v", qr.Rows[2][1]), fmt.Sprintf(`BLOB("%s")`, cell)) + if tablet.Type == "replica" { + assert.Equal(t, fmt.Sprintf("%v", qr.Rows[3][1]), `BLOB("neutral")`) + } else if tablet.Type == "rdonly" { + assert.Equal(t, fmt.Sprintf("%v", qr.Rows[3][1]), `BLOB("must_not")`) + } +} + +// ListBackups Lists back preset in shard +func (cluster LocalProcessCluster) ListBackups(shardKsName string) ([]string, error) { + output, err := cluster.VtctlclientProcess.ExecuteCommandWithOutput("ListBackups", shardKsName) + if err != nil { + return nil, err + } + result := strings.Split(output, "\n") + var returnResult []string + for _, str := range result { + if str != "" { + returnResult = append(returnResult, str) + } + } + return returnResult, nil +} + +// VerifyBackupCount compares the backup count with expected count. +func (cluster LocalProcessCluster) VerifyBackupCount(t *testing.T, shardKsName string, expected int) []string { + backups, err := cluster.ListBackups(shardKsName) + require.Nil(t, err) + assert.Equalf(t, expected, len(backups), "invalid number of backups") + return backups +} + +// RemoveAllBackups removes all the backup corresponds to list backup. +func (cluster LocalProcessCluster) RemoveAllBackups(t *testing.T, shardKsName string) { + backups, err := cluster.ListBackups(shardKsName) + require.Nil(t, err) + for _, backup := range backups { + cluster.VtctlclientProcess.ExecuteCommand("RemoveBackup", shardKsName, backup) + } +} + +// ResetTabletDirectory transitions back to tablet state (i.e. mysql process restarts with cleaned directory and tablet is off) +func ResetTabletDirectory(tablet Vttablet) error { + tablet.MysqlctlProcess.Stop() + tablet.VttabletProcess.TearDown() + os.RemoveAll(tablet.VttabletProcess.Directory) + + return tablet.MysqlctlProcess.Start() +} + +func getTablet(tabletGrpcPort int, hostname string) *tabletpb.Tablet { + portMap := make(map[string]int32) + portMap["grpc"] = int32(tabletGrpcPort) + return &tabletpb.Tablet{Hostname: hostname, PortMap: portMap} +} + +func filterResultWhenRunsForCoverage(input string) string { + if !*isCoverage { + return input + } + lines := strings.Split(input, "\n") + var result string + for _, line := range lines { + if strings.Contains(line, "=== RUN") { + continue + } + if strings.Contains(line, "--- PASS:") || strings.Contains(line, "PASS") { + break + } + result = result + line + "\n" + } + return result +} + +// WaitForReplicationPos will wait for replication position to catch-up +func WaitForReplicationPos(t *testing.T, tabletA *Vttablet, tabletB *Vttablet, hostname string, timeout float64) { + replicationPosA, _ := GetMasterPosition(t, *tabletA, hostname) + for { + replicationPosB, _ := GetMasterPosition(t, *tabletB, hostname) + if positionAtLeast(t, tabletA, replicationPosB, replicationPosA) { + break + } + msg := fmt.Sprintf("%s's replication position to catch up to %s's;currently at: %s, waiting to catch up to: %s", tabletB.Alias, tabletA.Alias, replicationPosB, replicationPosA) + waitStep(t, msg, timeout, 0.01) + } +} + +func waitStep(t *testing.T, msg string, timeout float64, sleepTime float64) float64 { + timeout = timeout - sleepTime + if timeout < 0.0 { + t.Errorf("timeout waiting for condition '%s'", msg) + } + time.Sleep(time.Duration(sleepTime) * time.Second) + return timeout +} + +func positionAtLeast(t *testing.T, tablet *Vttablet, a string, b string) bool { + isAtleast := false + val, err := tablet.MysqlctlProcess.ExecuteCommandWithOutput("position", "at_least", a, b) + require.NoError(t, err) + if strings.Contains(val, "true") { + isAtleast = true + } + return isAtleast +} + +// ExecuteQueriesUsingVtgate sends query to vtgate using vtgate session. +func ExecuteQueriesUsingVtgate(t *testing.T, session *vtgateconn.VTGateSession, query string) { + _, err := session.Execute(context.Background(), query, nil) + require.Nil(t, err) +} + +// NewConnParams creates ConnParams corresponds to given arguments. +func NewConnParams(port int, password, socketPath, keyspace string) mysql.ConnParams { + if port != 0 { + socketPath = "" + } + cp := mysql.ConnParams{ + Uname: "vt_dba", + Port: port, + UnixSocket: socketPath, + Pass: password, + } + + if keyspace != "" { + cp.DbName = "vt_" + keyspace + } + + return cp + +} diff --git a/go/test/endtoend/cluster/etcd_process.go b/go/test/endtoend/cluster/etcd_process.go deleted file mode 100644 index 284a849d3ca..00000000000 --- a/go/test/endtoend/cluster/etcd_process.go +++ /dev/null @@ -1,178 +0,0 @@ -/* -Copyright 2019 The Vitess Authors. - -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. -*/ - -package cluster - -import ( - "fmt" - "net/http" - "os" - "os/exec" - "path" - "strings" - "syscall" - "time" - - "vitess.io/vitess/go/vt/log" -) - -// EtcdProcess is a generic handle for a running Etcd . -// It can be spawned manually -type EtcdProcess struct { - Name string - Binary string - DataDirectory string - ListenClientURL string - AdvertiseClientURL string - Port int - PeerPort int - Host string - VerifyURL string - PeerURL string - - proc *exec.Cmd - exit chan error -} - -// Setup spawns a new etcd service and initializes it with the defaults. -// The service is kept running in the background until TearDown() is called. -func (etcd *EtcdProcess) Setup() (err error) { - etcd.proc = exec.Command( - etcd.Binary, - "--name", etcd.Name, - "--data-dir", etcd.DataDirectory, - "--listen-client-urls", etcd.ListenClientURL, - "--advertise-client-urls", etcd.AdvertiseClientURL, - "--initial-advertise-peer-urls", etcd.PeerURL, - "--listen-peer-urls", etcd.PeerURL, - "--initial-cluster", fmt.Sprintf("%s=%s", etcd.Name, etcd.PeerURL), - ) - - etcd.proc.Stderr = os.Stderr - etcd.proc.Stdout = os.Stdout - - etcd.proc.Env = append(etcd.proc.Env, os.Environ()...) - - log.Infof("%v %v", strings.Join(etcd.proc.Args, " ")) - println("Starting etcd with args " + strings.Join(etcd.proc.Args, " ")) - err = etcd.proc.Start() - if err != nil { - return - } - - etcd.exit = make(chan error) - go func() { - etcd.exit <- etcd.proc.Wait() - }() - - timeout := time.Now().Add(60 * time.Second) - for time.Now().Before(timeout) { - if etcd.IsHealthy() { - return - } - select { - case err := <-etcd.exit: - return fmt.Errorf("process '%s' exited prematurely (err: %s)", etcd.Binary, err) - default: - time.Sleep(300 * time.Millisecond) - } - } - - return fmt.Errorf("process '%s' timed out after 60s (err: %s)", etcd.Binary, <-etcd.exit) -} - -// TearDown shutdowns the running mysqld service -func (etcd *EtcdProcess) TearDown(Cell string, originalVtRoot string, currentRoot string, keepdata bool) error { - if etcd.proc == nil || etcd.exit == nil { - return nil - } - - etcd.removeTopoDirectories(Cell) - - // Attempt graceful shutdown with SIGTERM first - _ = etcd.proc.Process.Signal(syscall.SIGTERM) - if !*keepData { - _ = os.RemoveAll(etcd.DataDirectory) - _ = os.RemoveAll(currentRoot) - } - _ = os.Setenv("VTDATAROOT", originalVtRoot) - select { - case err := <-etcd.exit: - etcd.proc = nil - return err - - case <-time.After(10 * time.Second): - etcd.proc.Process.Kill() - etcd.proc = nil - return <-etcd.exit - } - -} - -// IsHealthy function checks if etcd server is up and running -func (etcd *EtcdProcess) IsHealthy() bool { - resp, err := http.Get(etcd.VerifyURL) - if err != nil { - return false - } - if resp.StatusCode == 200 { - return true - } - return false -} - -func (etcd *EtcdProcess) removeTopoDirectories(Cell string) { - _ = etcd.ManageTopoDir("rmdir", "/vitess/global") - _ = etcd.ManageTopoDir("rmdir", "/vitess/"+Cell) -} - -// ManageTopoDir creates global and zone in etcd2 -func (etcd *EtcdProcess) ManageTopoDir(command string, directory string) (err error) { - url := etcd.VerifyURL + directory - payload := strings.NewReader(`{"dir":"true"}`) - if command == "mkdir" { - req, _ := http.NewRequest("PUT", url, payload) - req.Header.Add("content-type", "application/json") - _, err = http.DefaultClient.Do(req) - return err - } else if command == "rmdir" { - req, _ := http.NewRequest("DELETE", url+"?dir=true", payload) - _, err = http.DefaultClient.Do(req) - return err - } else { - return nil - } -} - -// EtcdProcessInstance returns a EtcdProcess handle for a etcd sevice, -// configured with the given Config. -// The process must be manually started by calling setup() -func EtcdProcessInstance(port int, peerPort int, hostname string, name string) *EtcdProcess { - etcd := &EtcdProcess{ - Name: name, - Binary: "etcd", - Port: port, - Host: hostname, - PeerPort: peerPort, - } - - etcd.AdvertiseClientURL = fmt.Sprintf("http://%s:%d", etcd.Host, etcd.Port) - etcd.ListenClientURL = fmt.Sprintf("http://%s:%d", etcd.Host, etcd.Port) - etcd.DataDirectory = path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("%s_%d", "etcd", port)) - etcd.VerifyURL = fmt.Sprintf("http://%s:%d/v2/keys", etcd.Host, etcd.Port) - etcd.PeerURL = fmt.Sprintf("http://%s:%d", hostname, peerPort) - return etcd -} diff --git a/go/test/endtoend/cluster/mysqlctl_process.go b/go/test/endtoend/cluster/mysqlctl_process.go index baec38d391d..b619c4fe78b 100644 --- a/go/test/endtoend/cluster/mysqlctl_process.go +++ b/go/test/endtoend/cluster/mysqlctl_process.go @@ -17,10 +17,15 @@ limitations under the License. package cluster import ( + "context" "fmt" "os" "os/exec" "path" + "strings" + + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/vt/log" ) // MysqlctlProcess is a generic handle for a running mysqlctl command . @@ -32,42 +37,91 @@ type MysqlctlProcess struct { TabletUID int MySQLPort int InitDBFile string + ExtraArgs []string + InitMysql bool } // InitDb executes mysqlctl command to add cell info func (mysqlctl *MysqlctlProcess) InitDb() (err error) { - tmpProcess := exec.Command( - mysqlctl.Binary, - "-log_dir", mysqlctl.LogDirectory, + args := []string{"-log_dir", mysqlctl.LogDirectory, "-tablet_uid", fmt.Sprintf("%d", mysqlctl.TabletUID), "-mysql_port", fmt.Sprintf("%d", mysqlctl.MySQLPort), "init", - "-init_db_sql_file", mysqlctl.InitDBFile, - ) + "-init_db_sql_file", mysqlctl.InitDBFile} + if *isCoverage { + args = append([]string{"-test.coverprofile=" + getCoveragePath("mysql-initdb.out"), "-test.v"}, args...) + } + tmpProcess := exec.Command( + mysqlctl.Binary, + args...) return tmpProcess.Run() } // Start executes mysqlctl command to start mysql instance func (mysqlctl *MysqlctlProcess) Start() (err error) { + tmpProcess, err := mysqlctl.StartProcess() + if err != nil { + return err + } + return tmpProcess.Wait() +} + +// StartProcess starts the mysqlctl and returns the process reference +func (mysqlctl *MysqlctlProcess) StartProcess() (*exec.Cmd, error) { tmpProcess := exec.Command( mysqlctl.Binary, "-log_dir", mysqlctl.LogDirectory, "-tablet_uid", fmt.Sprintf("%d", mysqlctl.TabletUID), "-mysql_port", fmt.Sprintf("%d", mysqlctl.MySQLPort), - "init", - "-init_db_sql_file", mysqlctl.InitDBFile, ) - return tmpProcess.Run() + if *isCoverage { + tmpProcess.Args = append(tmpProcess.Args, []string{"-test.coverprofile=" + getCoveragePath("mysql-start.out")}...) + } + + if len(mysqlctl.ExtraArgs) > 0 { + tmpProcess.Args = append(tmpProcess.Args, mysqlctl.ExtraArgs...) + } + if mysqlctl.InitMysql { + tmpProcess.Args = append(tmpProcess.Args, "init", + "-init_db_sql_file", mysqlctl.InitDBFile) + } + tmpProcess.Args = append(tmpProcess.Args, "start") + + return tmpProcess, tmpProcess.Start() } // Stop executes mysqlctl command to stop mysql instance func (mysqlctl *MysqlctlProcess) Stop() (err error) { + tmpProcess, err := mysqlctl.StopProcess() + if err != nil { + return err + } + return tmpProcess.Wait() +} + +// StopProcess executes mysqlctl command to stop mysql instance and returns process reference +func (mysqlctl *MysqlctlProcess) StopProcess() (*exec.Cmd, error) { tmpProcess := exec.Command( mysqlctl.Binary, "-tablet_uid", fmt.Sprintf("%d", mysqlctl.TabletUID), - "shutdown", ) - return tmpProcess.Start() + if *isCoverage { + tmpProcess.Args = append(tmpProcess.Args, []string{"-test.coverprofile=" + getCoveragePath("mysql-stop.out")}...) + } + if len(mysqlctl.ExtraArgs) > 0 { + tmpProcess.Args = append(tmpProcess.Args, mysqlctl.ExtraArgs...) + } + tmpProcess.Args = append(tmpProcess.Args, "shutdown") + return tmpProcess, tmpProcess.Start() +} + +// CleanupFiles clean the mysql files to make sure we can start the same process again +func (mysqlctl *MysqlctlProcess) CleanupFiles(tabletUID int) { + os.RemoveAll(path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("/vt_%010d/data", tabletUID))) + os.RemoveAll(path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("/vt_%010d/relay-logs", tabletUID))) + os.RemoveAll(path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("/vt_%010d/tmp", tabletUID))) + os.RemoveAll(path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("/vt_%010d/bin-logs", tabletUID))) + os.RemoveAll(path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("/vt_%010d/innodb", tabletUID))) } // MysqlCtlProcessInstance returns a Mysqlctl handle for mysqlctl process @@ -81,5 +135,38 @@ func MysqlCtlProcessInstance(tabletUID int, mySQLPort int, tmpDirectory string) } mysqlctl.MySQLPort = mySQLPort mysqlctl.TabletUID = tabletUID + mysqlctl.InitMysql = true return mysqlctl } + +// StartMySQL starts mysqlctl process +func StartMySQL(ctx context.Context, tablet *Vttablet, username string, tmpDirectory string) error { + tablet.MysqlctlProcess = *MysqlCtlProcessInstance(tablet.TabletUID, tablet.MySQLPort, tmpDirectory) + return tablet.MysqlctlProcess.Start() +} + +// StartMySQLAndGetConnection create a connection to tablet mysql +func StartMySQLAndGetConnection(ctx context.Context, tablet *Vttablet, username string, tmpDirectory string) (*mysql.Conn, error) { + tablet.MysqlctlProcess = *MysqlCtlProcessInstance(tablet.TabletUID, tablet.MySQLPort, tmpDirectory) + err := tablet.MysqlctlProcess.Start() + if err != nil { + return nil, err + } + params := mysql.ConnParams{ + Uname: username, + UnixSocket: path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("/vt_%010d", tablet.TabletUID), "/mysql.sock"), + } + + return mysql.Connect(ctx, ¶ms) +} + +// ExecuteCommandWithOutput executes any mysqlctl command and returns output +func (mysqlctl *MysqlctlProcess) ExecuteCommandWithOutput(args ...string) (result string, err error) { + tmpProcess := exec.Command( + mysqlctl.Binary, + args..., + ) + log.Info(fmt.Sprintf("Executing mysqlctl with arguments %v", strings.Join(tmpProcess.Args, " "))) + resultByte, err := tmpProcess.CombinedOutput() + return string(resultByte), err +} diff --git a/go/test/endtoend/cluster/mysqlctld_process.go b/go/test/endtoend/cluster/mysqlctld_process.go new file mode 100644 index 00000000000..08abb7027d3 --- /dev/null +++ b/go/test/endtoend/cluster/mysqlctld_process.go @@ -0,0 +1,166 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package cluster + +import ( + "context" + "fmt" + "os" + "os/exec" + "path" + "strings" + "time" + + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/vt/log" +) + +// MysqlctldProcess is a generic handle for a running mysqlctld command . +// It can be spawned manually +type MysqlctldProcess struct { + Name string + Binary string + LogDirectory string + Password string + TabletUID int + MySQLPort int + InitDBFile string + ExtraArgs []string + process *exec.Cmd + exit chan error + InitMysql bool + exitSignalReceived bool +} + +// InitDb executes mysqlctld command to add cell info +func (mysqlctld *MysqlctldProcess) InitDb() (err error) { + tmpProcess := exec.Command( + mysqlctld.Binary, + "-log_dir", mysqlctld.LogDirectory, + "-tablet_uid", fmt.Sprintf("%d", mysqlctld.TabletUID), + "-mysql_port", fmt.Sprintf("%d", mysqlctld.MySQLPort), + "-init_db_sql_file", mysqlctld.InitDBFile, + ) + return tmpProcess.Run() +} + +// Start starts the mysqlctld and returns the error. +func (mysqlctld *MysqlctldProcess) Start() error { + if mysqlctld.process != nil { + return fmt.Errorf("process is already running") + } + _ = createDirectory(mysqlctld.LogDirectory, 0700) + tempProcess := exec.Command( + mysqlctld.Binary, + "-log_dir", mysqlctld.LogDirectory, + "-tablet_uid", fmt.Sprintf("%d", mysqlctld.TabletUID), + "-mysql_port", fmt.Sprintf("%d", mysqlctld.MySQLPort), + ) + + tempProcess.Args = append(tempProcess.Args, mysqlctld.ExtraArgs...) + + if mysqlctld.InitMysql { + tempProcess.Args = append(tempProcess.Args, + "-init_db_sql_file", mysqlctld.InitDBFile) + } + + errFile, _ := os.Create(path.Join(mysqlctld.LogDirectory, "mysqlctld-stderr.txt")) + tempProcess.Stderr = errFile + + tempProcess.Env = append(tempProcess.Env, os.Environ()...) + tempProcess.Stdout = os.Stdout + tempProcess.Stderr = os.Stderr + + log.Infof("%v %v", strings.Join(tempProcess.Args, " ")) + + err := tempProcess.Start() + if err != nil { + return err + } + + mysqlctld.process = tempProcess + + mysqlctld.exit = make(chan error) + go func(mysqlctld *MysqlctldProcess) { + err := mysqlctld.process.Wait() + if !mysqlctld.exitSignalReceived { + fmt.Printf("mysqlctld stopped unexpectedly, tabletUID %v, mysql port %v, PID %v\n", mysqlctld.TabletUID, mysqlctld.MySQLPort, mysqlctld.process.Process.Pid) + } + mysqlctld.process = nil + mysqlctld.exitSignalReceived = false + mysqlctld.exit <- err + }(mysqlctld) + + timeout := time.Now().Add(60 * time.Second) + for time.Now().Before(timeout) { + if mysqlctld.IsHealthy() { + return nil + } + select { + case err := <-mysqlctld.exit: + return fmt.Errorf("process '%s' exited prematurely (err: %s)", mysqlctld.Name, err) + default: + time.Sleep(300 * time.Millisecond) + } + } + + return fmt.Errorf("process '%s' timed out after 60s (err: %s)", mysqlctld.Name, mysqlctld.Stop()) + +} + +// Stop executes mysqlctld command to stop mysql instance +func (mysqlctld *MysqlctldProcess) Stop() error { + // if mysqlctld.process == nil || mysqlctld.exit == nil { + // return nil + // } + mysqlctld.exitSignalReceived = true + tmpProcess := exec.Command( + "mysqlctl", + "-tablet_uid", fmt.Sprintf("%d", mysqlctld.TabletUID), + ) + tmpProcess.Args = append(tmpProcess.Args, mysqlctld.ExtraArgs...) + tmpProcess.Args = append(tmpProcess.Args, "shutdown") + return tmpProcess.Run() +} + +// CleanupFiles clean the mysql files to make sure we can start the same process again +func (mysqlctld *MysqlctldProcess) CleanupFiles(tabletUID int) { + os.RemoveAll(path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("/vt_%010d", tabletUID))) +} + +// MysqlCtldProcessInstance returns a Mysqlctld handle for mysqlctld process +// configured with the given Config. +func MysqlCtldProcessInstance(tabletUID int, mySQLPort int, tmpDirectory string) *MysqlctldProcess { + mysqlctld := &MysqlctldProcess{ + Name: "mysqlctld", + Binary: "mysqlctld", + LogDirectory: tmpDirectory, + InitDBFile: path.Join(os.Getenv("VTROOT"), "/config/init_db.sql"), + } + mysqlctld.MySQLPort = mySQLPort + mysqlctld.TabletUID = tabletUID + mysqlctld.InitMysql = true + return mysqlctld +} + +// IsHealthy gives the health status of mysql. +func (mysqlctld *MysqlctldProcess) IsHealthy() bool { + socketFile := path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("/vt_%010d", mysqlctld.TabletUID), "/mysql.sock") + params := NewConnParams(0, mysqlctld.Password, socketFile, "") + _, err := mysql.Connect(context.Background(), ¶ms) + return err == nil +} diff --git a/go/test/endtoend/cluster/topo_process.go b/go/test/endtoend/cluster/topo_process.go new file mode 100644 index 00000000000..7e2a063b1c4 --- /dev/null +++ b/go/test/endtoend/cluster/topo_process.go @@ -0,0 +1,316 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package cluster + +import ( + "fmt" + "io/ioutil" + "net/http" + "os" + "os/exec" + "path" + "strings" + "syscall" + "time" + + "vitess.io/vitess/go/vt/log" +) + +// TopoProcess is a generic handle for a running Topo service . +// It can be spawned manually +type TopoProcess struct { + Name string + Binary string + DataDirectory string + LogDirectory string + ListenClientURL string + AdvertiseClientURL string + Port int + Host string + VerifyURL string + PeerURL string + ZKPorts string + + proc *exec.Cmd + exit chan error +} + +// Setup starts a new topo service +func (topo *TopoProcess) Setup(topoFlavor string, cluster *LocalProcessCluster) (err error) { + switch topoFlavor { + case "zk2": + return topo.SetupZookeeper(cluster) + case "consul": + return topo.SetupConsul(cluster) + default: + return topo.SetupEtcd() + } +} + +// SetupEtcd spawns a new etcd service and initializes it with the defaults. +// The service is kept running in the background until TearDown() is called. +func (topo *TopoProcess) SetupEtcd() (err error) { + topo.proc = exec.Command( + topo.Binary, + "--name", topo.Name, + "--data-dir", topo.DataDirectory, + "--listen-client-urls", topo.ListenClientURL, + "--advertise-client-urls", topo.AdvertiseClientURL, + "--initial-advertise-peer-urls", topo.PeerURL, + "--listen-peer-urls", topo.PeerURL, + "--initial-cluster", fmt.Sprintf("%s=%s", topo.Name, topo.PeerURL), + ) + + err = createDirectory(topo.DataDirectory, 0700) + if err != nil && !os.IsExist(err) { + return err + } + errFile, err := os.Create(path.Join(topo.DataDirectory, "topo-stderr.txt")) + if err != nil { + return err + } + + topo.proc.Stderr = errFile + + topo.proc.Env = append(topo.proc.Env, os.Environ()...) + + log.Infof("%v %v", strings.Join(topo.proc.Args, " ")) + println("Starting topo with args " + strings.Join(topo.proc.Args, " ")) + err = topo.proc.Start() + if err != nil { + return + } + + topo.exit = make(chan error) + go func() { + topo.exit <- topo.proc.Wait() + }() + + timeout := time.Now().Add(60 * time.Second) + for time.Now().Before(timeout) { + if topo.IsHealthy() { + return + } + select { + case err := <-topo.exit: + return fmt.Errorf("process '%s' exited prematurely (err: %s)", topo.Binary, err) + default: + time.Sleep(300 * time.Millisecond) + } + } + + return fmt.Errorf("process '%s' timed out after 60s (err: %s)", topo.Binary, <-topo.exit) +} + +// SetupZookeeper spawns a new zookeeper topo service and initializes it with the defaults. +// The service is kept running in the background until TearDown() is called. +func (topo *TopoProcess) SetupZookeeper(cluster *LocalProcessCluster) (err error) { + + host, err := os.Hostname() + if err != nil { + return + } + + topo.ZKPorts = fmt.Sprintf("%d:%d:%d", cluster.GetAndReservePort(), cluster.GetAndReservePort(), topo.Port) + + topo.proc = exec.Command( + topo.Binary, + "-log_dir", topo.LogDirectory, + "-zk.cfg", fmt.Sprintf("1@%v:%s", host, topo.ZKPorts), + "init", + ) + + errFile, _ := os.Create(path.Join(topo.DataDirectory, "topo-stderr.txt")) + topo.proc.Stderr = errFile + topo.proc.Env = append(topo.proc.Env, os.Environ()...) + + log.Infof("%v %v", strings.Join(topo.proc.Args, " ")) + fmt.Println(strings.Join(topo.proc.Args, " ")) + err = topo.proc.Run() + if err != nil { + return + } + return +} + +// SetupConsul spawns a new consul service and initializes it with the defaults. +// The service is kept running in the background until TearDown() is called. +func (topo *TopoProcess) SetupConsul(cluster *LocalProcessCluster) (err error) { + + topo.VerifyURL = fmt.Sprintf("http://%s:%d/v1/kv/?keys", topo.Host, topo.Port) + + configFile := path.Join(os.Getenv("VTDATAROOT"), "consul.json") + + config := fmt.Sprintf(`{"ports":{"dns":%d,"http":%d,"serf_lan":%d,"serf_wan":%d}}`, + cluster.GetAndReservePort(), topo.Port, cluster.GetAndReservePort(), cluster.GetAndReservePort()) + + err = ioutil.WriteFile(configFile, []byte(config), 0666) + if err != nil { + return + } + + topo.proc = exec.Command( + topo.Binary, "agent", + "-dev", + "-config-file", configFile, + ) + + errFile, _ := os.Create(path.Join(topo.DataDirectory, "topo-stderr.txt")) + topo.proc.Stderr = errFile + + topo.proc.Env = append(topo.proc.Env, os.Environ()...) + + log.Infof("%v %v", strings.Join(topo.proc.Args, " ")) + println("Starting consul with args " + strings.Join(topo.proc.Args, " ")) + err = topo.proc.Start() + if err != nil { + return + } + + topo.exit = make(chan error) + go func() { + topo.exit <- topo.proc.Wait() + }() + + timeout := time.Now().Add(60 * time.Second) + for time.Now().Before(timeout) { + if topo.IsHealthy() { + return + } + select { + case err := <-topo.exit: + return fmt.Errorf("process '%s' exited prematurely (err: %s)", topo.Binary, err) + default: + time.Sleep(300 * time.Millisecond) + } + } + + return fmt.Errorf("process '%s' timed out after 60s (err: %s)", topo.Binary, <-topo.exit) +} + +// TearDown shutdowns the running topo service +func (topo *TopoProcess) TearDown(Cell string, originalVtRoot string, currentRoot string, keepdata bool, topoFlavor string) error { + + if topoFlavor == "zk2" { + cmd := "shutdown" + if keepdata { + cmd = "teardown" + } + topo.proc = exec.Command( + topo.Binary, + "-log_dir", topo.LogDirectory, + "-zk.cfg", fmt.Sprintf("1@%v:%s", topo.Host, topo.ZKPorts), + cmd, + ) + + err := topo.proc.Run() + if err != nil { + return err + } + } else { + if topo.proc == nil || topo.exit == nil { + return nil + } + + topo.removeTopoDirectories(Cell) + + // Attempt graceful shutdown with SIGTERM first + _ = topo.proc.Process.Signal(syscall.SIGTERM) + + if !*keepData { + _ = os.RemoveAll(topo.DataDirectory) + _ = os.RemoveAll(currentRoot) + } + _ = os.Setenv("VTDATAROOT", originalVtRoot) + + select { + case <-topo.exit: + topo.proc = nil + return nil + + case <-time.After(10 * time.Second): + topo.proc.Process.Kill() + topo.proc = nil + return <-topo.exit + } + } + + return nil +} + +// IsHealthy function checks if topo server is up and running +func (topo *TopoProcess) IsHealthy() bool { + resp, err := http.Get(topo.VerifyURL) + if err != nil { + return false + } + if resp.StatusCode == 200 { + return true + } + return false +} + +func (topo *TopoProcess) removeTopoDirectories(Cell string) { + _ = topo.ManageTopoDir("rmdir", "/vitess/global") + _ = topo.ManageTopoDir("rmdir", "/vitess/"+Cell) +} + +// ManageTopoDir creates global and zone in etcd2 +func (topo *TopoProcess) ManageTopoDir(command string, directory string) (err error) { + url := topo.VerifyURL + directory + payload := strings.NewReader(`{"dir":"true"}`) + if command == "mkdir" { + req, _ := http.NewRequest("PUT", url, payload) + req.Header.Add("content-type", "application/json") + _, err = http.DefaultClient.Do(req) + return err + } else if command == "rmdir" { + req, _ := http.NewRequest("DELETE", url+"?dir=true", payload) + _, err = http.DefaultClient.Do(req) + return err + } else { + return nil + } +} + +// TopoProcessInstance returns a TopoProcess handle for a etcd sevice, +// configured with the given Config. +// The process must be manually started by calling setup() +func TopoProcessInstance(port int, peerPort int, hostname string, flavor string, name string) *TopoProcess { + binary := "etcd" + if flavor == "zk2" { + binary = "zkctl" + } + if flavor == "consul" { + binary = "consul" + } + + topo := &TopoProcess{ + Name: name, + Binary: binary, + Port: port, + Host: hostname, + } + + topo.AdvertiseClientURL = fmt.Sprintf("http://%s:%d", topo.Host, topo.Port) + topo.ListenClientURL = fmt.Sprintf("http://%s:%d", topo.Host, topo.Port) + topo.DataDirectory = path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("%s_%d", "topo", port)) + topo.LogDirectory = path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("%s_%d", "topo", port), "logs") + topo.VerifyURL = fmt.Sprintf("http://%s:%d/v2/keys", topo.Host, topo.Port) + topo.PeerURL = fmt.Sprintf("http://%s:%d", hostname, peerPort) + return topo +} diff --git a/go/test/endtoend/cluster/vtbackup_process.go b/go/test/endtoend/cluster/vtbackup_process.go new file mode 100644 index 00000000000..01f93e67be3 --- /dev/null +++ b/go/test/endtoend/cluster/vtbackup_process.go @@ -0,0 +1,143 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package cluster + +import ( + "fmt" + "os" + "os/exec" + "path" + "strings" + "syscall" + "time" + + "vitess.io/vitess/go/vt/log" +) + +// VtbackupProcess is a generic handle for a running Vtbackup. +// It can be spawned manually +type VtbackupProcess struct { + Name string + Binary string + CommonArg VtctlProcess + LogDir string + MysqlPort int + Directory string + + Cell string + Keyspace string + Shard string + TabletAlias string + Server string + + ExtraArgs []string + initialBackup bool + initDBfile string + dbPassword string + dbName string + + proc *exec.Cmd + exit chan error +} + +// Setup starts vtbackup process with required arguements +func (vtbackup *VtbackupProcess) Setup() (err error) { + + vtbackup.proc = exec.Command( + vtbackup.Binary, + "-topo_implementation", vtbackup.CommonArg.TopoImplementation, + "-topo_global_server_address", vtbackup.CommonArg.TopoGlobalAddress, + "-topo_global_root", vtbackup.CommonArg.TopoGlobalRoot, + "-log_dir", vtbackup.LogDir, + + //initDBfile is required to run vtbackup + "-mysql_port", fmt.Sprintf("%d", vtbackup.MysqlPort), + "-init_db_sql_file", vtbackup.initDBfile, + "-init_keyspace", vtbackup.Keyspace, + "-init_shard", vtbackup.Shard, + + //Backup Arguments are not optional + "-backup_storage_implementation", "file", + "-file_backup_storage_root", + path.Join(os.Getenv("VTDATAROOT"), "tmp", "backupstorage"), + ) + + if vtbackup.initialBackup { + vtbackup.proc.Args = append(vtbackup.proc.Args, "-initial_backup") + } + if vtbackup.ExtraArgs != nil { + vtbackup.proc.Args = append(vtbackup.proc.Args, vtbackup.ExtraArgs...) + } + + vtbackup.proc.Stderr = os.Stderr + vtbackup.proc.Stdout = os.Stdout + + vtbackup.proc.Env = append(vtbackup.proc.Env, os.Environ()...) + log.Infof("%v", strings.Join(vtbackup.proc.Args, " ")) + fmt.Println(vtbackup.proc.Args) + + err = vtbackup.proc.Run() + if err != nil { + return + } + + return nil +} + +// TearDown shutdowns the running vtbackup process +func (vtbackup *VtbackupProcess) TearDown() error { + if vtbackup.proc == nil || vtbackup.exit == nil { + return nil + } + + // Attempt graceful shutdown with SIGTERM first + vtbackup.proc.Process.Signal(syscall.SIGTERM) + + select { + case err := <-vtbackup.exit: + vtbackup.proc = nil + return err + + case <-time.After(10 * time.Second): + vtbackup.proc.Process.Kill() + vtbackup.proc = nil + return <-vtbackup.exit + } +} + +// VtbackupProcessInstance returns a vtbackup handle +// configured with the given Config. +// The process must be manually started by calling Setup() +func VtbackupProcessInstance(tabletUID int, mysqlPort int, newInitDBFile string, keyspace string, shard string, + cell string, hostname string, tmpDirectory string, topoPort int, initialBackup bool) *VtbackupProcess { + vtctl := VtctlProcessInstance(topoPort, hostname) + vtbackup := &VtbackupProcess{ + Name: "vtbackup", + Binary: "vtbackup", + CommonArg: *vtctl, + LogDir: tmpDirectory, + Directory: os.Getenv("VTDATAROOT"), + TabletAlias: fmt.Sprintf("%s-%010d", cell, tabletUID), + initDBfile: newInitDBFile, + Keyspace: keyspace, + Shard: shard, + Cell: cell, + MysqlPort: mysqlPort, + initialBackup: initialBackup, + } + return vtbackup +} diff --git a/go/test/endtoend/cluster/vtctl_process.go b/go/test/endtoend/cluster/vtctl_process.go index 74511b5c70f..cf75e24cd15 100644 --- a/go/test/endtoend/cluster/vtctl_process.go +++ b/go/test/endtoend/cluster/vtctl_process.go @@ -33,6 +33,7 @@ type VtctlProcess struct { TopoGlobalAddress string TopoGlobalRoot string TopoServerAddress string + TopoRootPath string } // AddCellInfo executes vtctl command to add cell info @@ -42,11 +43,17 @@ func (vtctl *VtctlProcess) AddCellInfo(Cell string) (err error) { "-topo_implementation", vtctl.TopoImplementation, "-topo_global_server_address", vtctl.TopoGlobalAddress, "-topo_global_root", vtctl.TopoGlobalRoot, + ) + if *isCoverage { + tmpProcess.Args = append(tmpProcess.Args, "-test.coverprofile="+getCoveragePath("vtctl-addcell.out")) + } + tmpProcess.Args = append(tmpProcess.Args, "AddCellInfo", - "-root", "/vitess/"+Cell, + "-root", vtctl.TopoRootPath+Cell, "-server_address", vtctl.TopoServerAddress, - Cell, - ) + Cell) + log.Info(fmt.Sprintf("Adding Cell into Keyspace with arguments %v", strings.Join(tmpProcess.Args, " "))) + fmt.Println(fmt.Sprintf("Adding Cell into Keyspace with arguments %v", strings.Join(tmpProcess.Args, " "))) return tmpProcess.Run() } @@ -57,23 +64,82 @@ func (vtctl *VtctlProcess) CreateKeyspace(keyspace string) (err error) { "-topo_implementation", vtctl.TopoImplementation, "-topo_global_server_address", vtctl.TopoGlobalAddress, "-topo_global_root", vtctl.TopoGlobalRoot, - "CreateKeyspace", keyspace, ) + if *isCoverage { + tmpProcess.Args = append(tmpProcess.Args, "-test.coverprofile="+getCoveragePath("vtctl-create-ks.out")) + } + tmpProcess.Args = append(tmpProcess.Args, + "CreateKeyspace", keyspace) log.Info(fmt.Sprintf("Starting CreateKeyspace with arguments %v", strings.Join(tmpProcess.Args, " "))) return tmpProcess.Run() } +// ExecuteCommandWithOutput executes any vtctlclient command and returns output +func (vtctl *VtctlProcess) ExecuteCommandWithOutput(args ...string) (result string, err error) { + args = append([]string{ + "-enable_queries", + "-topo_implementation", vtctl.TopoImplementation, + "-topo_global_server_address", vtctl.TopoGlobalAddress, + "-topo_global_root", vtctl.TopoGlobalRoot}, args...) + if *isCoverage { + args = append([]string{"-test.coverprofile=" + getCoveragePath("vtctl-o-"+args[0]+".out"), "-test.v"}, args...) + } + tmpProcess := exec.Command( + vtctl.Binary, + args..., + ) + log.Info(fmt.Sprintf("Executing vtctlclient with arguments %v", strings.Join(tmpProcess.Args, " "))) + resultByte, err := tmpProcess.CombinedOutput() + return filterResultWhenRunsForCoverage(string(resultByte)), err +} + +// ExecuteCommand executes any vtctlclient command +func (vtctl *VtctlProcess) ExecuteCommand(args ...string) (err error) { + args = append([]string{ + "-enable_queries", + "-topo_implementation", vtctl.TopoImplementation, + "-topo_global_server_address", vtctl.TopoGlobalAddress, + "-topo_global_root", vtctl.TopoGlobalRoot}, args...) + if *isCoverage { + args = append([]string{"-test.coverprofile=" + getCoveragePath("vtctl-"+args[0]+".out"), "-test.v"}, args...) + } + tmpProcess := exec.Command( + vtctl.Binary, + args..., + ) + log.Info(fmt.Sprintf("Executing vtctlclient with arguments %v", strings.Join(tmpProcess.Args, " "))) + return tmpProcess.Run() +} + // VtctlProcessInstance returns a VtctlProcess handle for vtctl process // configured with the given Config. // The process must be manually started by calling setup() func VtctlProcessInstance(topoPort int, hostname string) *VtctlProcess { + + // Default values for etcd2 topo server. + topoImplementation := "etcd2" + topoGlobalRoot := "/vitess/global" + topoRootPath := "/" + + // Checking and resetting the parameters for required topo server. + switch *topoFlavor { + case "zk2": + topoImplementation = "zk2" + case "consul": + topoImplementation = "consul" + topoGlobalRoot = "global" + // For consul we do not need "/" in the path + topoRootPath = "" + } + vtctl := &VtctlProcess{ Name: "vtctl", Binary: "vtctl", - TopoImplementation: "etcd2", + TopoImplementation: topoImplementation, TopoGlobalAddress: fmt.Sprintf("%s:%d", hostname, topoPort), - TopoGlobalRoot: "/vitess/global", + TopoGlobalRoot: topoGlobalRoot, TopoServerAddress: fmt.Sprintf("%s:%d", hostname, topoPort), + TopoRootPath: topoRootPath, } return vtctl } diff --git a/go/test/endtoend/cluster/vtctlclient_process.go b/go/test/endtoend/cluster/vtctlclient_process.go index 982f0fd6a70..6b9f41619ac 100644 --- a/go/test/endtoend/cluster/vtctlclient_process.go +++ b/go/test/endtoend/cluster/vtctlclient_process.go @@ -62,10 +62,15 @@ func (vtctlclient *VtctlClientProcess) ApplyVSchema(Keyspace string, JSON string // ExecuteCommand executes any vtctlclient command func (vtctlclient *VtctlClientProcess) ExecuteCommand(args ...string) (err error) { - args = append([]string{"-server", vtctlclient.Server}, args...) + pArgs := []string{"-server", vtctlclient.Server} + + if *isCoverage { + pArgs = append(pArgs, "-test.coverprofile="+getCoveragePath("vtctlclient-"+args[0]+".out"), "-test.v") + } + pArgs = append(pArgs, args...) tmpProcess := exec.Command( vtctlclient.Binary, - args..., + pArgs..., ) println(fmt.Sprintf("Executing vtctlclient with arguments %v", strings.Join(tmpProcess.Args, " "))) log.Info(fmt.Sprintf("Executing vtctlclient with arguments %v", strings.Join(tmpProcess.Args, " "))) @@ -74,15 +79,19 @@ func (vtctlclient *VtctlClientProcess) ExecuteCommand(args ...string) (err error // ExecuteCommandWithOutput executes any vtctlclient command and returns output func (vtctlclient *VtctlClientProcess) ExecuteCommandWithOutput(args ...string) (result string, err error) { - args = append([]string{"-server", vtctlclient.Server}, args...) + pArgs := []string{"-server", vtctlclient.Server} + if *isCoverage { + pArgs = append(pArgs, "-test.coverprofile="+getCoveragePath("vtctlclient-"+args[0]+".out"), "-test.v") + } + pArgs = append(pArgs, args...) tmpProcess := exec.Command( vtctlclient.Binary, - args..., + pArgs..., ) println(fmt.Sprintf("Executing vtctlclient with arguments %v", strings.Join(tmpProcess.Args, " "))) log.Info(fmt.Sprintf("Executing vtctlclient with arguments %v", strings.Join(tmpProcess.Args, " "))) resultByte, err := tmpProcess.CombinedOutput() - return string(resultByte), err + return filterResultWhenRunsForCoverage(string(resultByte)), err } // VtctlClientProcessInstance returns a VtctlProcess handle for vtctlclient process @@ -96,3 +105,23 @@ func VtctlClientProcessInstance(hostname string, grpcPort int, tmpDirectory stri } return vtctlclient } + +// InitTablet initializes a tablet +func (vtctlclient *VtctlClientProcess) InitTablet(tablet *Vttablet, cell string, keyspaceName string, hostname string, shardName string) error { + tabletType := "replica" + if tablet.Type == "rdonly" { + tabletType = "rdonly" + } + args := []string{"InitTablet", "-hostname", hostname, + "-port", fmt.Sprintf("%d", tablet.HTTPPort), "-allow_update", "-parent", + "-keyspace", keyspaceName, + "-shard", shardName} + if tablet.MySQLPort > 0 { + args = append(args, "-mysql_port", fmt.Sprintf("%d", tablet.MySQLPort)) + } + if tablet.GrpcPort > 0 { + args = append(args, "-grpc_port", fmt.Sprintf("%d", tablet.GrpcPort)) + } + args = append(args, fmt.Sprintf("%s-%010d", cell, tablet.TabletUID), tabletType) + return vtctlclient.ExecuteCommand(args...) +} diff --git a/go/test/endtoend/cluster/vtctld_process.go b/go/test/endtoend/cluster/vtctld_process.go index d8666b40912..28690cfd1e6 100644 --- a/go/test/endtoend/cluster/vtctld_process.go +++ b/go/test/endtoend/cluster/vtctld_process.go @@ -35,8 +35,6 @@ type VtctldProcess struct { Name string Binary string CommonArg VtctlProcess - WebDir string - WebDir2 string ServiceMap string BackupStorageImplementation string FileBackupStorageRoot string @@ -52,7 +50,7 @@ type VtctldProcess struct { } // Setup starts vtctld process with required arguements -func (vtctld *VtctldProcess) Setup(Cell string) (err error) { +func (vtctld *VtctldProcess) Setup(cell string, extraArgs ...string) (err error) { _ = createDirectory(vtctld.LogDir, 0700) _ = createDirectory(path.Join(vtctld.Directory, "backups"), 0700) vtctld.proc = exec.Command( @@ -61,9 +59,7 @@ func (vtctld *VtctldProcess) Setup(Cell string) (err error) { "-topo_implementation", vtctld.CommonArg.TopoImplementation, "-topo_global_server_address", vtctld.CommonArg.TopoGlobalAddress, "-topo_global_root", vtctld.CommonArg.TopoGlobalRoot, - "-cell", Cell, - "-web_dir", vtctld.WebDir, - "-web_dir2", vtctld.WebDir2, + "-cell", cell, "-workflow_manager_init", "-workflow_manager_use_election", "-service_map", vtctld.ServiceMap, @@ -74,9 +70,13 @@ func (vtctld *VtctldProcess) Setup(Cell string) (err error) { "-grpc_port", fmt.Sprintf("%d", vtctld.GrpcPort), "-pid_file", vtctld.PidFile, ) + if *isCoverage { + vtctld.proc.Args = append(vtctld.proc.Args, "-test.coverprofile="+getCoveragePath("vtctld.out")) + } + vtctld.proc.Args = append(vtctld.proc.Args, extraArgs...) - vtctld.proc.Stderr = os.Stderr - vtctld.proc.Stdout = os.Stdout + errFile, _ := os.Create(path.Join(vtctld.LogDir, "vtctld-stderr.txt")) + vtctld.proc.Stderr = errFile vtctld.proc.Env = append(vtctld.proc.Env, os.Environ()...) @@ -157,8 +157,6 @@ func VtctldProcessInstance(httpPort int, grpcPort int, topoPort int, hostname st Name: "vtctld", Binary: "vtctld", CommonArg: *vtctl, - WebDir: path.Join(os.Getenv("VTROOT"), "/web/vtctld"), - WebDir2: path.Join(os.Getenv("VTROOT"), "/web/vtctld2/app"), ServiceMap: "grpc-vtctl", BackupStorageImplementation: "file", FileBackupStorageRoot: path.Join(os.Getenv("VTDATAROOT"), "/backups"), diff --git a/go/test/endtoend/cluster/vtgate_process.go b/go/test/endtoend/cluster/vtgate_process.go index e2b771735ad..1c8a830bc13 100644 --- a/go/test/endtoend/cluster/vtgate_process.go +++ b/go/test/endtoend/cluster/vtgate_process.go @@ -25,6 +25,7 @@ import ( "os/exec" "path" "reflect" + "strconv" "strings" "syscall" "time" @@ -82,10 +83,14 @@ func (vtgate *VtgateProcess) Setup() (err error) { "-mysql_auth_server_impl", vtgate.MySQLAuthServerImpl, "-pid_file", vtgate.PidFile, ) + if *isCoverage { + vtgate.proc.Args = append(vtgate.proc.Args, "-test.coverprofile="+getCoveragePath("vtgate.out")) + } + vtgate.proc.Args = append(vtgate.proc.Args, vtgate.ExtraArgs...) - vtgate.proc.Stderr = os.Stderr - vtgate.proc.Stdout = os.Stdout + errFile, _ := os.Create(path.Join(vtgate.LogDir, "vtgate-stderr.txt")) + vtgate.proc.Stderr = errFile vtgate.proc.Env = append(vtgate.proc.Env, os.Environ()...) @@ -95,10 +100,11 @@ func (vtgate *VtgateProcess) Setup() (err error) { if err != nil { return } - vtgate.exit = make(chan error) go func() { - vtgate.exit <- vtgate.proc.Wait() + if vtgate.proc != nil { + vtgate.exit <- vtgate.proc.Wait() + } }() timeout := time.Now().Add(60 * time.Second) @@ -119,6 +125,19 @@ func (vtgate *VtgateProcess) Setup() (err error) { // WaitForStatus function checks if vtgate process is up and running func (vtgate *VtgateProcess) WaitForStatus() bool { + resp, err := http.Get(vtgate.VerifyURL) + if err != nil { + return false + } + if resp.StatusCode == 200 { + return true + } + return false +} + +// GetStatusForTabletOfShard function gets status for a specific tablet of a shard in keyspace +// endPointsCount : number of endpoints +func (vtgate *VtgateProcess) GetStatusForTabletOfShard(name string, endPointsCount int) bool { resp, err := http.Get(vtgate.VerifyURL) if err != nil { return false @@ -134,9 +153,10 @@ func (vtgate *VtgateProcess) WaitForStatus() bool { masterConnectionExist := false if object.Kind() == reflect.Map { for _, key := range object.MapKeys() { - - if strings.Contains(key.String(),"master") { - masterConnectionExist = true + if key.String() == name { + value := fmt.Sprintf("%v", object.MapIndex(key)) + countStr := strconv.Itoa(endPointsCount) + return value == countStr } } } @@ -145,6 +165,24 @@ func (vtgate *VtgateProcess) WaitForStatus() bool { return false } +// WaitForStatusOfTabletInShard function waits till status of a tablet in shard is 1 +// endPointsCount: how many endpoints to wait for +func (vtgate *VtgateProcess) WaitForStatusOfTabletInShard(name string, endPointsCount int) error { + timeout := time.Now().Add(10 * time.Second) + for time.Now().Before(timeout) { + if vtgate.GetStatusForTabletOfShard(name, endPointsCount) { + return nil + } + select { + case err := <-vtgate.exit: + return fmt.Errorf("process '%s' exited prematurely (err: %s)", vtgate.Name, err) + default: + time.Sleep(300 * time.Millisecond) + } + } + return fmt.Errorf("wait for %s failed", name) +} + // TearDown shuts down the running vtgate service func (vtgate *VtgateProcess) TearDown() error { if vtgate.proc == nil || vtgate.exit == nil { @@ -175,7 +213,7 @@ func VtgateProcessInstance(port int, grpcPort int, mySQLServerPort int, cell str Binary: "vtgate", FileToLogQueries: path.Join(tmpDirectory, "/vtgate_querylog.txt"), Directory: os.Getenv("VTDATAROOT"), - ServiceMap: "grpc-vtgateservice", + ServiceMap: "grpc-tabletmanager,grpc-throttler,grpc-queryservice,grpc-updatestream,grpc-vtctl,grpc-vtworker,grpc-vtgateservice", LogDir: tmpDirectory, Port: port, GrpcPort: grpcPort, @@ -195,3 +233,21 @@ func VtgateProcessInstance(port int, grpcPort int, mySQLServerPort int, cell str return vtgate } + +// GetVars returns map of vars +func (vtgate *VtgateProcess) GetVars() (map[string]interface{}, error) { + resultMap := make(map[string]interface{}) + resp, err := http.Get(vtgate.VerifyURL) + if err != nil { + return nil, fmt.Errorf("error getting response from %s", vtgate.VerifyURL) + } + if resp.StatusCode == 200 { + respByte, _ := ioutil.ReadAll(resp.Body) + err := json.Unmarshal(respByte, &resultMap) + if err != nil { + return nil, fmt.Errorf("not able to parse response body") + } + return resultMap, nil + } + return nil, fmt.Errorf("unsuccessful response") +} diff --git a/go/test/endtoend/cluster/vttablet_process.go b/go/test/endtoend/cluster/vttablet_process.go index f3ced054d00..b5477499bad 100644 --- a/go/test/endtoend/cluster/vttablet_process.go +++ b/go/test/endtoend/cluster/vttablet_process.go @@ -12,11 +12,13 @@ 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. + */ package cluster import ( + "context" "encoding/json" "fmt" "io/ioutil" @@ -24,10 +26,13 @@ import ( "os" "os/exec" "path" + "reflect" "strings" "syscall" "time" + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/log" ) @@ -56,6 +61,11 @@ type VttabletProcess struct { VtctldAddress string Directory string VerifyURL string + EnableSemiSync bool + SupportsBackup bool + ServingStatus string + DbPassword string + DbPort int //Extra Args to be set before starting the vttablet process ExtraArgs []string @@ -82,18 +92,27 @@ func (vttablet *VttabletProcess) Setup() (err error) { "-init_keyspace", vttablet.Keyspace, "-init_tablet_type", vttablet.TabletType, "-health_check_interval", fmt.Sprintf("%ds", vttablet.HealthCheckInterval), - "-enable_semi_sync", "-enable_replication_reporter", "-backup_storage_implementation", vttablet.BackupStorageImplementation, "-file_backup_storage_root", vttablet.FileBackupStorageRoot, - "-restore_from_backup", "-service_map", vttablet.ServiceMap, "-vtctld_addr", vttablet.VtctldAddress, ) + if *isCoverage { + vttablet.proc.Args = append(vttablet.proc.Args, "-test.coverprofile="+getCoveragePath("vttablet.out")) + } + + if vttablet.SupportsBackup { + vttablet.proc.Args = append(vttablet.proc.Args, "-restore_from_backup") + } + if vttablet.EnableSemiSync { + vttablet.proc.Args = append(vttablet.proc.Args, "-enable_semi_sync") + } + vttablet.proc.Args = append(vttablet.proc.Args, vttablet.ExtraArgs...) - vttablet.proc.Stderr = os.Stderr - vttablet.proc.Stdout = os.Stdout + errFile, _ := os.Create(path.Join(vttablet.LogDir, vttablet.TabletPath+"-vttablet-stderr.txt")) + vttablet.proc.Stderr = errFile vttablet.proc.Env = append(vttablet.proc.Env, os.Environ()...) @@ -106,48 +125,151 @@ func (vttablet *VttabletProcess) Setup() (err error) { vttablet.exit = make(chan error) go func() { - vttablet.exit <- vttablet.proc.Wait() + if vttablet.proc != nil { + vttablet.exit <- vttablet.proc.Wait() + } }() - timeout := time.Now().Add(60 * time.Second) - for time.Now().Before(timeout) { - if vttablet.WaitForStatus("NOT_SERVING") { - return nil - } - select { - case err := <-vttablet.exit: - return fmt.Errorf("process '%s' exited prematurely (err: %s)", vttablet.Name, err) - default: - time.Sleep(300 * time.Millisecond) + if vttablet.ServingStatus != "" { + if err = vttablet.WaitForTabletType(vttablet.ServingStatus); err != nil { + return fmt.Errorf("process '%s' timed out after 10s (err: %s)", vttablet.Name, err) } } + return nil +} - return fmt.Errorf("process '%s' timed out after 60s (err: %s)", vttablet.Name, <-vttablet.exit) +// GetStatus returns /debug/status endpoint result +func (vttablet *VttabletProcess) GetStatus() string { + URL := fmt.Sprintf("http://%s:%d/debug/status", vttablet.TabletHostname, vttablet.Port) + resp, err := http.Get(URL) + if err != nil { + return "" + } + if resp.StatusCode == 200 { + respByte, _ := ioutil.ReadAll(resp.Body) + defer resp.Body.Close() + return string(respByte) + } + return "" } -// WaitForStatus function checks if vttablet process is up and running -func (vttablet *VttabletProcess) WaitForStatus(status string) bool { +// GetVars gets the debug vars as map +func (vttablet *VttabletProcess) GetVars() map[string]interface{} { resp, err := http.Get(vttablet.VerifyURL) if err != nil { - return false + return nil } if resp.StatusCode == 200 { resultMap := make(map[string]interface{}) respByte, _ := ioutil.ReadAll(resp.Body) err := json.Unmarshal(respByte, &resultMap) if err != nil { - panic(err) + return nil + } + return resultMap + } + return nil +} + +// WaitForStatus waits till desired status of tablet is reached +func (vttablet *VttabletProcess) WaitForStatus(status string) bool { + return vttablet.GetTabletStatus() == status +} + +// GetTabletStatus returns the tablet state as seen in /debug/vars TabletStateName +func (vttablet *VttabletProcess) GetTabletStatus() string { + resultMap := vttablet.GetVars() + if resultMap != nil { + return reflect.ValueOf(resultMap["TabletStateName"]).String() + } + return "" +} + +// WaitForTabletType waits for 10 second till expected type reached +func (vttablet *VttabletProcess) WaitForTabletType(expectedType string) error { + return vttablet.WaitForTabletTypesForTimeout([]string{expectedType}, 10*time.Second) +} + +// WaitForTabletTypes waits for 10 second till expected type reached +func (vttablet *VttabletProcess) WaitForTabletTypes(expectedTypes []string) error { + return vttablet.WaitForTabletTypesForTimeout(expectedTypes, 10*time.Second) +} + +// WaitForTabletTypesForTimeout waits till the tablet reaches to any of the provided status +func (vttablet *VttabletProcess) WaitForTabletTypesForTimeout(expectedTypes []string, timeout time.Duration) error { + timeToWait := time.Now().Add(timeout) + var status string + for time.Now().Before(timeToWait) { + status = vttablet.GetTabletStatus() + if contains(expectedTypes, status) { + return nil + } + select { + case err := <-vttablet.exit: + return fmt.Errorf("process '%s' exited prematurely (err: %s)", vttablet.Name, err) + default: + time.Sleep(300 * time.Millisecond) + } + } + return fmt.Errorf("Vttablet %s, current status = %s, expected status [%s] not reached ", + vttablet.TabletPath, status, strings.Join(expectedTypes, ",")) +} + +func contains(arr []string, str string) bool { + for _, a := range arr { + if a == str { + return true } - return resultMap["TabletStateName"] == status } return false } +// WaitForBinLogPlayerCount waits till binlog player count var matches +func (vttablet *VttabletProcess) WaitForBinLogPlayerCount(expectedCount int) error { + timeout := time.Now().Add(10 * time.Second) + for time.Now().Before(timeout) { + if vttablet.getVReplStreamCount() == fmt.Sprintf("%d", expectedCount) { + return nil + } + select { + case err := <-vttablet.exit: + return fmt.Errorf("process '%s' exited prematurely (err: %s)", vttablet.Name, err) + default: + time.Sleep(300 * time.Millisecond) + } + } + return fmt.Errorf("vttablet %s, expected status not reached", vttablet.TabletPath) +} + +// WaitForBinlogServerState wait for the tablet's binlog server to be in the provided state. +func (vttablet *VttabletProcess) WaitForBinlogServerState(expectedStatus string) error { + timeout := time.Now().Add(10 * time.Second) + for time.Now().Before(timeout) { + if vttablet.getVarValue("UpdateStreamState") == expectedStatus { + return nil + } + select { + case err := <-vttablet.exit: + return fmt.Errorf("process '%s' exited prematurely (err: %s)", vttablet.Name, err) + default: + time.Sleep(300 * time.Millisecond) + } + } + return fmt.Errorf("vttablet %s, expected status not reached", vttablet.TabletPath) +} + +func (vttablet *VttabletProcess) getVReplStreamCount() string { + return vttablet.getVarValue("VReplicationStreamCount") +} + +func (vttablet *VttabletProcess) getVarValue(keyname string) string { + resultMap := vttablet.GetVars() + object := reflect.ValueOf(resultMap[keyname]) + return fmt.Sprintf("%v", object) +} + // TearDown shuts down the running vttablet service func (vttablet *VttabletProcess) TearDown() error { - if vttablet.proc == nil { - fmt.Printf("No process found for vttablet %d", vttablet.TabletUID) - } if vttablet.proc == nil || vttablet.exit == nil { return nil } @@ -166,10 +288,70 @@ func (vttablet *VttabletProcess) TearDown() error { } } +// CreateDB creates the database for keyspace +func (vttablet *VttabletProcess) CreateDB(keyspace string) error { + _, _ = vttablet.QueryTablet(fmt.Sprintf("drop database IF EXISTS vt_%s", keyspace), keyspace, false) + _, err := vttablet.QueryTablet(fmt.Sprintf("create database IF NOT EXISTS vt_%s", keyspace), keyspace, false) + return err +} + +// QueryTablet lets you execute a query in this tablet and get the result +func (vttablet *VttabletProcess) QueryTablet(query string, keyspace string, useDb bool) (*sqltypes.Result, error) { + if !useDb { + keyspace = "" + } + dbParams := NewConnParams(vttablet.DbPort, vttablet.DbPassword, path.Join(vttablet.Directory, "mysql.sock"), keyspace) + return executeQuery(dbParams, query) +} + +// QueryTabletWithDB lets you execute query on a specific DB in this tablet and get the result +func (vttablet *VttabletProcess) QueryTabletWithDB(query string, dbname string) (*sqltypes.Result, error) { + dbParams := mysql.ConnParams{ + Uname: "vt_dba", + UnixSocket: path.Join(vttablet.Directory, "mysql.sock"), + DbName: dbname, + } + if vttablet.DbPassword != "" { + dbParams.Pass = vttablet.DbPassword + } + return executeQuery(dbParams, query) +} + +func executeQuery(dbParams mysql.ConnParams, query string) (*sqltypes.Result, error) { + ctx := context.Background() + dbConn, err := mysql.Connect(ctx, &dbParams) + if err != nil { + return nil, err + } + defer dbConn.Close() + return dbConn.ExecuteFetch(query, 10000, true) +} + +// GetDBVar returns first matching database variable's value +func (vttablet *VttabletProcess) GetDBVar(varName string, ksName string) (string, error) { + return vttablet.getDBSystemValues("variables", varName, ksName) +} + +// GetDBStatus returns first matching database variable's value +func (vttablet *VttabletProcess) GetDBStatus(status string, ksName string) (string, error) { + return vttablet.getDBSystemValues("status", status, ksName) +} + +func (vttablet *VttabletProcess) getDBSystemValues(placeholder string, value string, ksName string) (string, error) { + output, err := vttablet.QueryTablet(fmt.Sprintf("show %s like '%s'", placeholder, value), ksName, true) + if err != nil || output.Rows == nil { + return "", err + } + if len(output.Rows) > 0 { + return fmt.Sprintf("%s", output.Rows[0][1].ToBytes()), nil + } + return "", nil +} + // VttabletProcessInstance returns a VttabletProcess handle for vttablet process // configured with the given Config. // The process must be manually started by calling setup() -func VttabletProcessInstance(port int, grpcPort int, tabletUID int, cell string, shard string, keyspace string, vtctldPort int, tabletType string, topoPort int, hostname string, tmpDirectory string, extraArgs []string) *VttabletProcess { +func VttabletProcessInstance(port int, grpcPort int, tabletUID int, cell string, shard string, keyspace string, vtctldPort int, tabletType string, topoPort int, hostname string, tmpDirectory string, extraArgs []string, enableSemiSync bool) *VttabletProcess { vtctl := VtctlProcessInstance(topoPort, hostname) vttablet := &VttabletProcess{ Name: "vttablet", @@ -177,7 +359,7 @@ func VttabletProcessInstance(port int, grpcPort int, tabletUID int, cell string, FileToLogQueries: path.Join(tmpDirectory, fmt.Sprintf("/vt_%010d/querylog.txt", tabletUID)), Directory: path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("/vt_%010d", tabletUID)), TabletPath: fmt.Sprintf("%s-%010d", cell, tabletUID), - ServiceMap: "grpc-queryservice,grpc-tabletmanager,grpc-updatestream", + ServiceMap: "grpc-queryservice,grpc-tabletmanager,grpc-updatestream,grpc-throttler", LogDir: tmpDirectory, Shard: shard, TabletHostname: hostname, @@ -185,13 +367,16 @@ func VttabletProcessInstance(port int, grpcPort int, tabletUID int, cell string, TabletType: "replica", CommonArg: *vtctl, HealthCheckInterval: 5, - BackupStorageImplementation: "file", - FileBackupStorageRoot: path.Join(os.Getenv("VTDATAROOT"), "/backups"), Port: port, GrpcPort: grpcPort, PidFile: path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("/vt_%010d/vttablet.pid", tabletUID)), VtctldAddress: fmt.Sprintf("http://%s:%d", hostname, vtctldPort), ExtraArgs: extraArgs, + EnableSemiSync: enableSemiSync, + SupportsBackup: true, + ServingStatus: "NOT_SERVING", + BackupStorageImplementation: "file", + FileBackupStorageRoot: path.Join(os.Getenv("VTDATAROOT"), "/backups"), } if tabletType == "rdonly" { diff --git a/go/test/endtoend/cluster/vtworker_process.go b/go/test/endtoend/cluster/vtworker_process.go new file mode 100644 index 00000000000..ab14eaab5ef --- /dev/null +++ b/go/test/endtoend/cluster/vtworker_process.go @@ -0,0 +1,233 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package cluster + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "os" + "os/exec" + "strings" + "syscall" + "time" + + "vitess.io/vitess/go/vt/log" +) + +// VtworkerProcess is a generic handle for a running vtworker . +// It can be spawned manually +type VtworkerProcess struct { + Name string + Binary string + CommonArg VtctlProcess + ServiceMap string + LogDir string + Port int + GrpcPort int + VerifyURL string + Directory string + ExecuteRetryTime string + Cell string + Server string + CommandDisplayInterval string + ExtraArgs []string + + proc *exec.Cmd + exit chan error +} + +// Setup starts vtworker process with required arguements +func (vtworker *VtworkerProcess) Setup(cell string) (err error) { + + vtworker.proc = exec.Command( + vtworker.Binary, + "-log_dir", vtworker.LogDir, + "-port", fmt.Sprintf("%d", vtworker.Port), + "-executefetch_retry_time", vtworker.ExecuteRetryTime, + "-tablet_manager_protocol", "grpc", + "-tablet_protocol", "grpc", + "-topo_implementation", vtworker.CommonArg.TopoImplementation, + "-topo_global_server_address", vtworker.CommonArg.TopoGlobalAddress, + "-topo_global_root", vtworker.CommonArg.TopoGlobalRoot, + "-service_map", vtworker.ServiceMap, + "-grpc_port", fmt.Sprintf("%d", vtworker.GrpcPort), + "-cell", cell, + "-command_display_interval", "10ms", + ) + if *isCoverage { + vtworker.proc.Args = append(vtworker.proc.Args, "-test.coverprofile=vtworker.out", "-test.v") + } + vtworker.proc.Args = append(vtworker.proc.Args, vtworker.ExtraArgs...) + + vtworker.proc.Stderr = os.Stderr + vtworker.proc.Stdout = os.Stdout + + vtworker.proc.Env = append(vtworker.proc.Env, os.Environ()...) + + log.Infof("%v", strings.Join(vtworker.proc.Args, " ")) + + err = vtworker.proc.Start() + if err != nil { + return + } + + vtworker.exit = make(chan error) + go func() { + vtworker.exit <- vtworker.proc.Wait() + }() + + timeout := time.Now().Add(60 * time.Second) + for time.Now().Before(timeout) { + if vtworker.IsHealthy() { + return nil + } + select { + case err := <-vtworker.exit: + return fmt.Errorf("process '%s' exited prematurely (err: %s)", vtworker.Name, err) + default: + time.Sleep(300 * time.Millisecond) + } + } + + return fmt.Errorf("process '%s' timed out after 60s (err: %s)", vtworker.Name, <-vtworker.exit) +} + +// IsHealthy function checks if vtworker process is up and running +func (vtworker *VtworkerProcess) IsHealthy() bool { + resp, err := http.Get(vtworker.VerifyURL) + if err != nil { + return false + } + if resp.StatusCode == 200 { + return true + } + return false +} + +// TearDown shutdowns the running vtworker process +func (vtworker *VtworkerProcess) TearDown() error { + if vtworker.proc == nil || vtworker.exit == nil { + return nil + } + + // Attempt graceful shutdown with SIGTERM first + vtworker.proc.Process.Signal(syscall.SIGTERM) + + select { + case err := <-vtworker.exit: + vtworker.proc = nil + return err + + case <-time.After(10 * time.Second): + vtworker.proc.Process.Kill() + vtworker.proc = nil + return <-vtworker.exit + } +} + +// ExecuteCommand executes any vtworker command +func (vtworker *VtworkerProcess) ExecuteCommand(args ...string) (err error) { + args = append([]string{"-vtworker_client_protocol", "grpc", + "-server", vtworker.Server, "-log_dir", vtworker.LogDir, "-stderrthreshold", "info"}, args...) + if *isCoverage { + args = append([]string{"-test.coverprofile=" + getCoveragePath("vtworkerclient-exec-cmd.out")}, args...) + } + tmpProcess := exec.Command( + "vtworkerclient", + args..., + ) + log.Info(fmt.Sprintf("Executing vtworkerclient with arguments %v", strings.Join(tmpProcess.Args, " "))) + return tmpProcess.Run() +} + +func (vtworker *VtworkerProcess) ExecuteCommandInBg(args ...string) (*exec.Cmd, error) { + args = append([]string{"-vtworker_client_protocol", "grpc", + "-server", vtworker.Server, "-log_dir", vtworker.LogDir, "-stderrthreshold", "info"}, args...) + tmpProcess := exec.Command( + "vtworkerclient", + args..., + ) + log.Info(fmt.Sprintf("Executing vtworkerclient with arguments %v", strings.Join(tmpProcess.Args, " "))) + return tmpProcess, tmpProcess.Start() +} + +// ExecuteVtworkerCommand executes any vtworker command +func (vtworker *VtworkerProcess) ExecuteVtworkerCommand(port int, grpcPort int, args ...string) (err error) { + args = append([]string{ + "-port", fmt.Sprintf("%d", port), + "-executefetch_retry_time", vtworker.ExecuteRetryTime, + "-tablet_manager_protocol", "grpc", + "-tablet_protocol", "grpc", + "-topo_implementation", vtworker.CommonArg.TopoImplementation, + "-topo_global_server_address", vtworker.CommonArg.TopoGlobalAddress, + "-topo_global_root", vtworker.CommonArg.TopoGlobalRoot, + "-service_map", vtworker.ServiceMap, + "-grpc_port", fmt.Sprintf("%d", grpcPort), + "-cell", vtworker.Cell, + "-log_dir", vtworker.LogDir, "-stderrthreshold", "1"}, args...) + if *isCoverage { + args = append([]string{"-test.coverprofile=" + getCoveragePath("vtworker-exec-cmd.out")}, args...) + } + tmpProcess := exec.Command( + "vtworker", + args..., + ) + log.Info(fmt.Sprintf("Executing vtworker with arguments %v", strings.Join(tmpProcess.Args, " "))) + return tmpProcess.Run() +} + +// VtworkerProcessInstance returns a vtworker handle +// configured with the given Config. +// The process must be manually started by calling Setup() +func VtworkerProcessInstance(httpPort int, grpcPort int, topoPort int, hostname string, tmpDirectory string) *VtworkerProcess { + vtctl := VtctlProcessInstance(topoPort, hostname) + vtworker := &VtworkerProcess{ + Name: "vtworker", + Binary: "vtworker", + CommonArg: *vtctl, + ServiceMap: "grpc-tabletmanager,grpc-throttler,grpc-queryservice,grpc-updatestream,grpc-vtctl,grpc-vtworker,grpc-vtgateservice", + LogDir: tmpDirectory, + Port: httpPort, + GrpcPort: grpcPort, + ExecuteRetryTime: "1s", + CommandDisplayInterval: "10ms", + Directory: os.Getenv("VTDATAROOT"), + Server: fmt.Sprintf("%s:%d", hostname, grpcPort), + } + vtworker.VerifyURL = fmt.Sprintf("http://%s:%d/debug/vars", hostname, vtworker.Port) + return vtworker +} + +// GetVars returns map of vars +func (vtworker *VtworkerProcess) GetVars() (map[string]interface{}, error) { + resultMap := make(map[string]interface{}) + resp, err := http.Get(vtworker.VerifyURL) + if err != nil { + return nil, fmt.Errorf("error getting response from %s", vtworker.VerifyURL) + } + if resp.StatusCode == 200 { + respByte, _ := ioutil.ReadAll(resp.Body) + err := json.Unmarshal(respByte, &resultMap) + if err != nil { + return nil, fmt.Errorf("not able to parse response body") + } + return resultMap, nil + } + return nil, fmt.Errorf("unsuccessful response") +} diff --git a/go/test/endtoend/clustertest/add_keyspace_test.go b/go/test/endtoend/clustertest/add_keyspace_test.go index e305866b752..b16b5893941 100644 --- a/go/test/endtoend/clustertest/add_keyspace_test.go +++ b/go/test/endtoend/clustertest/add_keyspace_test.go @@ -57,6 +57,7 @@ primary key (id) ) func TestAddKeyspace(t *testing.T) { + defer cluster.PanicHandler(t) if err := clusterInstance.StartKeyspace(*testKeyspace, []string{"-80", "80-"}, 1, true); err != nil { println(err.Error()) t.Fatal(err) @@ -64,6 +65,7 @@ func TestAddKeyspace(t *testing.T) { // Restart vtgate process _ = clusterInstance.VtgateProcess.TearDown() _ = clusterInstance.VtgateProcess.Setup() + clusterInstance.WaitForTabletsToHealthyInVtgate() ctx := context.Background() vtParams := mysql.ConnParams{ diff --git a/go/test/endtoend/clustertest/etcd_test.go b/go/test/endtoend/clustertest/etcd_test.go index cb0138b0d5e..1f5e548696f 100644 --- a/go/test/endtoend/clustertest/etcd_test.go +++ b/go/test/endtoend/clustertest/etcd_test.go @@ -19,9 +19,12 @@ package clustertest import ( "fmt" "testing" + + "vitess.io/vitess/go/test/endtoend/cluster" ) func TestEtcdServer(t *testing.T) { + defer cluster.PanicHandler(t) etcdURL := fmt.Sprintf("http://%s:%d/v2/keys", clusterInstance.Hostname, clusterInstance.TopoPort) testURL(t, etcdURL, "generic etcd url") testURL(t, etcdURL+"/vitess/global", "vitess global key") diff --git a/go/test/endtoend/clustertest/main_test.go b/go/test/endtoend/clustertest/main_test.go index 11c48433ac3..025ee77800f 100644 --- a/go/test/endtoend/clustertest/main_test.go +++ b/go/test/endtoend/clustertest/main_test.go @@ -60,6 +60,7 @@ var ( ) func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) flag.Parse() exitCode := func() int { diff --git a/go/test/endtoend/clustertest/vtcltd_test.go b/go/test/endtoend/clustertest/vtcltd_test.go index 4704fd7f99a..4b195de82d0 100644 --- a/go/test/endtoend/clustertest/vtcltd_test.go +++ b/go/test/endtoend/clustertest/vtcltd_test.go @@ -18,11 +18,119 @@ limitations under the License. package clustertest import ( + "encoding/json" "fmt" + "io/ioutil" + "net/http" + "reflect" + "regexp" + "strings" "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/test/endtoend/cluster" +) + +var ( + oneTableOutput = `+---+ +| a | ++---+ +| 1 | ++---+ +` ) func TestVtctldProcess(t *testing.T) { - url := fmt.Sprintf("http://localhost:%d/api/keyspaces/", clusterInstance.VtctldHTTPPort) + defer cluster.PanicHandler(t) + url := fmt.Sprintf("http://%s:%d/api/keyspaces/", clusterInstance.Hostname, clusterInstance.VtctldHTTPPort) testURL(t, url, "keyspace url") + + healthCheckURL := fmt.Sprintf("http://%s:%d/debug/health/", clusterInstance.Hostname, clusterInstance.VtctldHTTPPort) + testURL(t, healthCheckURL, "vtctld health check url") + + url = fmt.Sprintf("http://%s:%d/api/topodata/", clusterInstance.Hostname, clusterInstance.VtctldHTTPPort) + + testTopoDataAPI(t, url) + testListAllTablets(t) + testTabletStatus(t) + testExecuteAsDba(t) + testExecuteAsApp(t) +} + +func testTopoDataAPI(t *testing.T, url string) { + resp, err := http.Get(url) + require.Nil(t, err) + assert.Equal(t, resp.StatusCode, 200) + + resultMap := make(map[string]interface{}) + respByte, _ := ioutil.ReadAll(resp.Body) + err = json.Unmarshal(respByte, &resultMap) + require.Nil(t, err) + + errorValue := reflect.ValueOf(resultMap["Error"]) + assert.Empty(t, errorValue.String()) + + assert.Contains(t, resultMap, "Children") + children := reflect.ValueOf(resultMap["Children"]) + childrenGot := fmt.Sprintf("%s", children) + assert.Contains(t, childrenGot, "global") + assert.Contains(t, childrenGot, clusterInstance.Cell) +} + +func testListAllTablets(t *testing.T) { + result, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("ListAllTablets", clusterInstance.Cell) + require.Nil(t, err) + + tablets := getAllTablets() + + tabletsFromCMD := strings.Split(result, "\n") + tabletCountFromCMD := 0 + + for _, line := range tabletsFromCMD { + if len(line) > 0 { + tabletCountFromCMD = tabletCountFromCMD + 1 + assert.Contains(t, tablets, strings.Split(line, " ")[0]) + } + } + assert.Equal(t, tabletCountFromCMD, len(tablets)) +} + +func testTabletStatus(t *testing.T) { + resp, err := http.Get(fmt.Sprintf("http://%s:%d", clusterInstance.Hostname, clusterInstance.Keyspaces[0].Shards[0].Vttablets[0].HTTPPort)) + require.Nil(t, err) + respByte, err := ioutil.ReadAll(resp.Body) + require.Nil(t, err) + result := string(respByte) + println(result) + println(strings.Contains(result, "Polling health information from.")) + matched, err := regexp.Match(`Polling health information from.+MySQLReplicationLag`, []byte(result)) + require.Nil(t, err) + assert.True(t, matched) + assert.True(t, strings.Contains(result, `Alias: vttablet +vtgate vttablet server CA vtgate -> vttablet + +vtgate vtgate client CA client -> vtgate +client vtgate server CA client -> vtgate + +Additionally, we have the following constraints: +- the client certificate common name is used as immediate +caller ID by vtgate, and forwarded to vttablet. This allows us to use +table ACLs on the vttablet side. +- the vtgate server certificate common name is set to 'localhost' so it matches +the hostname dialed by the vtgate clients. This is not a requirement for the +go client, that can set its expected server name. However, the python gRPC +client doesn't have the ability to set the server name, so they must match. +- the python client needs to have the full chain for the server validation +(that is 'vtgate server CA' + 'root CA'). A go client doesn't. So we read both +below when using the python client, but we only pass the intermediate cert +to the go clients (for vtgate -> vttablet link). */ + +package encryptedtransport + +import ( + "flag" + "fmt" + "io/ioutil" + "os" + "os/exec" + "path" + "testing" + + "vitess.io/vitess/go/test/endtoend/encryption" + + "vitess.io/vitess/go/vt/proto/vtrpc" + "vitess.io/vitess/go/vt/vterrors" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/net/context" + "vitess.io/vitess/go/test/endtoend/cluster" + "vitess.io/vitess/go/vt/grpcclient" + "vitess.io/vitess/go/vt/log" + querypb "vitess.io/vitess/go/vt/proto/query" + vtgatepb "vitess.io/vitess/go/vt/proto/vtgate" + vtgateservicepb "vitess.io/vitess/go/vt/proto/vtgateservice" +) + +var ( + clusterInstance *cluster.LocalProcessCluster + createVtInsertTest = `create table vt_insert_test ( + id bigint auto_increment, + msg varchar(64), + keyspace_id bigint(20) unsigned NOT NULL, + primary key (id) + ) Engine = InnoDB` + keyspace = "test_keyspace" + hostname = "localhost" + shardName = "0" + cell = "zone1" + certDirectory string + grpcCert = "" + grpcKey = "" + grpcCa = "" + grpcName = "" +) + +func TestSecureTransport(t *testing.T) { + defer cluster.PanicHandler(t) + flag.Parse() + + // initialize cluster + _, err := clusterSetUp(t) + require.Nil(t, err, "setup failed") + + masterTablet := *clusterInstance.Keyspaces[0].Shards[0].Vttablets[0] + replicaTablet := *clusterInstance.Keyspaces[0].Shards[0].Vttablets[1] + + for _, tablet := range []cluster.Vttablet{masterTablet, replicaTablet} { + err = clusterInstance.VtctlclientProcess.InitTablet(&tablet, clusterInstance.Cell, keyspace, hostname, shardName) + require.Nil(t, err) + // create database so vttablet can start behaving normally + err = tablet.VttabletProcess.CreateDB(keyspace) + require.Nil(t, err) + } + + // creating table_acl_config.json file + tableACLConfigJSON := path.Join(certDirectory, "table_acl_config.json") + f, err := os.Create(tableACLConfigJSON) + require.Nil(t, err) + + _, err = f.WriteString(`{ + "table_groups": [ + { + "table_names_or_prefixes": ["vt_insert_test"], + "readers": ["vtgate client 1"], + "writers": ["vtgate client 1"], + "admins": ["vtgate client 1"] + } + ] +}`) + require.Nil(t, err) + err = f.Close() + require.Nil(t, err) + + // start the tablets + for _, tablet := range []cluster.Vttablet{masterTablet, replicaTablet} { + tablet.VttabletProcess.ExtraArgs = append(tablet.VttabletProcess.ExtraArgs, "-table-acl-config", tableACLConfigJSON, "-queryserver-config-strict-table-acl") + tablet.VttabletProcess.ExtraArgs = append(tablet.VttabletProcess.ExtraArgs, serverExtraArguments("vttablet-server-instance", "vttablet-client")...) + err = tablet.VttabletProcess.Setup() + require.Nil(t, err) + } + + // setup replication + var vtctlClientArgs []string + + vtctlClientTmArgs := append(vtctlClientArgs, tmclientExtraArgs("vttablet-client-1")...) + + // Reparenting + vtctlClientArgs = append(vtctlClientTmArgs, "InitShardMaster", "-force", "test_keyspace/0", masterTablet.Alias) + err = clusterInstance.VtctlProcess.ExecuteCommand(vtctlClientArgs...) + require.Nil(t, err) + + // Apply schema + var vtctlApplySchemaArgs = append(vtctlClientTmArgs, "ApplySchema", "-sql", createVtInsertTest, "test_keyspace") + err = clusterInstance.VtctlProcess.ExecuteCommand(vtctlApplySchemaArgs...) + require.Nil(t, err) + + for _, tablet := range []cluster.Vttablet{masterTablet, replicaTablet} { + var vtctlTabletArgs []string + vtctlTabletArgs = append(vtctlTabletArgs, tmclientExtraArgs("vttablet-client-1")...) + vtctlTabletArgs = append(vtctlTabletArgs, "RunHealthCheck", tablet.Alias) + _, err = clusterInstance.VtctlProcess.ExecuteCommandWithOutput(vtctlTabletArgs...) + require.Nil(t, err) + } + + // start vtgate + clusterInstance.VtGateExtraArgs = append(clusterInstance.VtGateExtraArgs, tabletConnExtraArgs("vttablet-client-1")...) + clusterInstance.VtGateExtraArgs = append(clusterInstance.VtGateExtraArgs, serverExtraArguments("vtgate-server-instance", "vtgate-client")...) + err = clusterInstance.StartVtgate() + require.Nil(t, err) + + grpcAddress := fmt.Sprintf("%s:%d", "localhost", clusterInstance.VtgateProcess.GrpcPort) + + // 'vtgate client 1' is authorized to access vt_insert_test + setCreds(t, "vtgate-client-1", "vtgate-server") + ctx := context.Background() + request := getRequest("select * from vt_insert_test") + vc, err := getVitessClient(grpcAddress) + require.Nil(t, nil) + + qr, err := vc.Execute(ctx, request) + err = vterrors.FromVTRPC(qr.Error) + require.Nil(t, err) + + // 'vtgate client 2' is not authorized to access vt_insert_test + setCreds(t, "vtgate-client-2", "vtgate-server") + request = getRequest("select * from vt_insert_test") + vc, err = getVitessClient(grpcAddress) + require.Nil(t, err) + qr, err = vc.Execute(ctx, request) + err = vterrors.FromVTRPC(qr.Error) + require.Error(t, err) + assert.Contains(t, err.Error(), "table acl error") + assert.Contains(t, err.Error(), "cannot run PASS_SELECT on table") + + // now restart vtgate in the mode where we don't use SSL + // for client connections, but we copy effective caller id + // into immediate caller id. + clusterInstance.VtGateExtraArgs = []string{"-grpc_use_effective_callerid"} + clusterInstance.VtGateExtraArgs = append(clusterInstance.VtGateExtraArgs, tabletConnExtraArgs("vttablet-client-1")...) + err = clusterInstance.ReStartVtgate() + require.Nil(t, err) + + grpcAddress = fmt.Sprintf("%s:%d", "localhost", clusterInstance.VtgateProcess.GrpcPort) + + setSSLInfoEmpty() + + // get vitess client + vc, err = getVitessClient(grpcAddress) + require.Nil(t, err) + + // test with empty effective caller Id + request = getRequest("select * from vt_insert_test") + qr, err = vc.Execute(ctx, request) + err = vterrors.FromVTRPC(qr.Error) + require.Error(t, err) + assert.Contains(t, err.Error(), "table acl error") + assert.Contains(t, err.Error(), "cannot run PASS_SELECT on table") + + // 'vtgate client 1' is authorized to access vt_insert_test + callerID := &vtrpc.CallerID{ + Principal: "vtgate client 1", + } + request = getRequestWithCallerID(callerID, "select * from vt_insert_test") + qr, err = vc.Execute(ctx, request) + err = vterrors.FromVTRPC(qr.Error) + require.Nil(t, err) + + // 'vtgate client 2' is not authorized to access vt_insert_test + callerID = &vtrpc.CallerID{ + Principal: "vtgate client 2", + } + request = getRequestWithCallerID(callerID, "select * from vt_insert_test") + qr, err = vc.Execute(ctx, request) + err = vterrors.FromVTRPC(qr.Error) + require.Error(t, err) + assert.Contains(t, err.Error(), "table acl error") + assert.Contains(t, err.Error(), "cannot run PASS_SELECT on table") + + clusterInstance.Teardown() +} + +func clusterSetUp(t *testing.T) (int, error) { + var mysqlProcesses []*exec.Cmd + clusterInstance = cluster.NewCluster(cell, hostname) + + // Start topo server + if err := clusterInstance.StartTopo(); err != nil { + return 1, err + } + + // create all certs + log.Info("Creating certificates") + certDirectory = path.Join(clusterInstance.TmpDirectory, "certs") + _ = encryption.CreateDirectory(certDirectory, 0700) + + err := encryption.ExecuteVttlstestCommand("-root", certDirectory, "CreateCA") + require.Nil(t, err) + + err = createSignedCert("ca", "01", "vttablet-server", "vttablet server CA") + require.Nil(t, err) + + err = createSignedCert("ca", "02", "vttablet-client", "vttablet client CA") + require.Nil(t, err) + + err = createSignedCert("ca", "03", "vtgate-server", "vtgate server CA") + require.Nil(t, err) + + err = createSignedCert("ca", "04", "vtgate-client", "vtgate client CA") + require.Nil(t, err) + + err = createSignedCert("vttablet-server", "01", "vttablet-server-instance", "vttablet server instance") + require.Nil(t, err) + + err = createSignedCert("vttablet-client", "01", "vttablet-client-1", "vttablet client 1") + require.Nil(t, err) + + err = createSignedCert("vtgate-server", "01", "vtgate-server-instance", "localhost") + require.Nil(t, err) + + err = createSignedCert("vtgate-client", "01", "vtgate-client-1", "vtgate client 1") + require.Nil(t, err) + + err = createSignedCert("vtgate-client", "02", "vtgate-client-2", "vtgate client 2") + require.Nil(t, err) + + for _, keyspaceStr := range []string{keyspace} { + KeyspacePtr := &cluster.Keyspace{Name: keyspaceStr} + keyspace := *KeyspacePtr + if err := clusterInstance.VtctlProcess.CreateKeyspace(keyspace.Name); err != nil { + return 1, err + } + shard := &cluster.Shard{ + Name: shardName, + } + for i := 0; i < 2; i++ { + // instantiate vttablet object with reserved ports + tablet := clusterInstance.GetVttabletInstance("replica", 0, cell) + + // Start Mysqlctl process + tablet.MysqlctlProcess = *cluster.MysqlCtlProcessInstance(tablet.TabletUID, tablet.MySQLPort, clusterInstance.TmpDirectory) + if proc, err := tablet.MysqlctlProcess.StartProcess(); err != nil { + return 1, err + } else { + mysqlProcesses = append(mysqlProcesses, proc) + } + // start vttablet process + tablet.VttabletProcess = cluster.VttabletProcessInstance(tablet.HTTPPort, + tablet.GrpcPort, + tablet.TabletUID, + clusterInstance.Cell, + shardName, + keyspace.Name, + clusterInstance.VtctldProcess.Port, + tablet.Type, + clusterInstance.TopoProcess.Port, + clusterInstance.Hostname, + clusterInstance.TmpDirectory, + clusterInstance.VtTabletExtraArgs, + clusterInstance.EnableSemiSync) + tablet.Alias = tablet.VttabletProcess.TabletPath + shard.Vttablets = append(shard.Vttablets, tablet) + } + keyspace.Shards = append(keyspace.Shards, *shard) + clusterInstance.Keyspaces = append(clusterInstance.Keyspaces, keyspace) + } + for _, proc := range mysqlProcesses { + err := proc.Wait() + if err != nil { + return 1, err + } + } + return 0, nil +} + +func createSignedCert(ca string, serial string, name string, commonName string) error { + log.Info("Creating signed cert and key %s", commonName) + tmpProcess := exec.Command( + "vttlstest", + "-root", certDirectory, + "CreateSignedCert", + "-parent", ca, + "-serial", serial, + "-common_name", commonName, + name) + return tmpProcess.Run() +} + +func serverExtraArguments(name string, ca string) []string { + args := []string{"-grpc_cert", certDirectory + "/" + name + "-cert.pem", + "-grpc_key", certDirectory + "/" + name + "-key.pem", + "-grpc_ca", certDirectory + "/" + ca + "-cert.pem"} + return args +} + +func tmclientExtraArgs(name string) []string { + ca := "vttablet-server" + var args = []string{"-tablet_manager_grpc_cert", certDirectory + "/" + name + "-cert.pem", + "-tablet_manager_grpc_key", certDirectory + "/" + name + "-key.pem", + "-tablet_manager_grpc_ca", certDirectory + "/" + ca + "-cert.pem", + "-tablet_manager_grpc_server_name", "vttablet server instance"} + return args +} + +func tabletConnExtraArgs(name string) []string { + ca := "vttablet-server" + args := []string{"-tablet_grpc_cert", certDirectory + "/" + name + "-cert.pem", + "-tablet_grpc_key", certDirectory + "/" + name + "-key.pem", + "-tablet_grpc_ca", certDirectory + "/" + ca + "-cert.pem", + "-tablet_grpc_server_name", "vttablet server instance"} + return args +} + +func getVitessClient(addr string) (vtgateservicepb.VitessClient, error) { + opt, err := grpcclient.SecureDialOption(grpcCert, grpcKey, grpcCa, grpcName) + if err != nil { + return nil, err + } + cc, err := grpcclient.Dial(addr, grpcclient.FailFast(false), opt) + if err != nil { + return nil, err + } + c := vtgateservicepb.NewVitessClient(cc) + return c, nil +} + +func setCreds(t *testing.T, name string, ca string) { + f1, err := os.Open(path.Join(certDirectory, "ca-cert.pem")) + require.Nil(t, err) + b1, err := ioutil.ReadAll(f1) + require.Nil(t, err) + + f2, err := os.Open(path.Join(certDirectory, ca+"-cert.pem")) + require.Nil(t, err) + b2, err := ioutil.ReadAll(f2) + require.Nil(t, err) + + caContent := append(b1, b2...) + fileName := "ca-" + name + ".pem" + caVtgateClient := path.Join(certDirectory, fileName) + f, err := os.Create(caVtgateClient) + require.Nil(t, err) + _, err = f.Write(caContent) + require.Nil(t, err) + + grpcCa = caVtgateClient + grpcKey = path.Join(certDirectory, name+"-key.pem") + grpcCert = path.Join(certDirectory, name+"-cert.pem") + + err = f.Close() + require.Nil(t, err) + err = f2.Close() + require.Nil(t, err) + err = f1.Close() + require.Nil(t, err) +} + +func setSSLInfoEmpty() { + grpcCa = "" + grpcCert = "" + grpcKey = "" + grpcName = "" +} + +func getSession() *vtgatepb.Session { + return &vtgatepb.Session{ + TargetString: "test_keyspace:0@master", + } +} + +func getRequestWithCallerID(callerID *vtrpc.CallerID, sql string) *vtgatepb.ExecuteRequest { + session := getSession() + return &vtgatepb.ExecuteRequest{ + CallerId: callerID, + Session: session, + Query: &querypb.BoundQuery{ + Sql: sql, + }, + } +} + +func getRequest(sql string) *vtgatepb.ExecuteRequest { + session := getSession() + return &vtgatepb.ExecuteRequest{ + Session: session, + Query: &querypb.BoundQuery{ + Sql: sql, + }, + } +} diff --git a/go/test/endtoend/keyspace/keyspace_test.go b/go/test/endtoend/keyspace/keyspace_test.go new file mode 100644 index 00000000000..0bcff99b6cb --- /dev/null +++ b/go/test/endtoend/keyspace/keyspace_test.go @@ -0,0 +1,400 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package sequence + +import ( + "bytes" + "encoding/binary" + "encoding/json" + "flag" + "os" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/test/endtoend/cluster" + "vitess.io/vitess/go/vt/proto/topodata" +) + +var ( + clusterForKSTest *cluster.LocalProcessCluster + keyspaceShardedName = "test_ks_sharded" + keyspaceUnshardedName = "test_ks_unsharded" + cell = "zone1" + cell2 = "zone2" + hostname = "localhost" + servedTypes = map[topodata.TabletType]bool{topodata.TabletType_MASTER: true, topodata.TabletType_REPLICA: true, topodata.TabletType_RDONLY: true} + sqlSchema = `create table vt_insert_test ( + id bigint auto_increment, + msg varchar(64), + keyspace_id bigint(20) unsigned NOT NULL, + primary key (id) + ) Engine=InnoDB` + vSchema = `{ + "sharded": true, + "vindexes": { + "hash_index": { + "type": "hash" + } + }, + "tables": { + "vt_insert_test": { + "column_vindexes": [ + { + "column": "keyspace_id", + "name": "hash_index" + } + ] + } + } + }` + shardKIdMap = map[string][]uint64{ + "-80": {527875958493693904, 626750931627689502, + 345387386794260318, 332484755310826578, + 1842642426274125671, 1326307661227634652, + 1761124146422844620, 1661669973250483744, + 3361397649937244239, 2444880764308344533}, + "80-": {9767889778372766922, 9742070682920810358, + 10296850775085416642, 9537430901666854108, + 10440455099304929791, 11454183276974683945, + 11185910247776122031, 10460396697869122981, + 13379616110062597001, 12826553979133932576}, + } +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitCode := func() int { + clusterForKSTest = cluster.NewCluster(cell, hostname) + defer clusterForKSTest.Teardown() + + // Start topo server + if err := clusterForKSTest.StartTopo(); err != nil { + return 1 + } + + if err := clusterForKSTest.TopoProcess.ManageTopoDir("mkdir", "/vitess/"+cell2); err != nil { + return 1 + } + + if err := clusterForKSTest.VtctlProcess.AddCellInfo(cell2); err != nil { + return 1 + } + + // Start sharded keyspace + keyspaceSharded := &cluster.Keyspace{ + Name: keyspaceShardedName, + SchemaSQL: sqlSchema, + VSchema: vSchema, + } + if err := clusterForKSTest.StartKeyspace(*keyspaceSharded, []string{"-80", "80-"}, 1, false); err != nil { + return 1 + } + if err := clusterForKSTest.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", keyspaceShardedName); err != nil { + return 1 + } + + // Start unsharded keyspace + keyspaceUnsharded := &cluster.Keyspace{ + Name: keyspaceUnshardedName, + SchemaSQL: sqlSchema, + } + if err := clusterForKSTest.StartKeyspace(*keyspaceUnsharded, []string{keyspaceUnshardedName}, 1, false); err != nil { + return 1 + } + if err := clusterForKSTest.VtctlclientProcess.ExecuteCommand("SetKeyspaceShardingInfo", "-force", keyspaceUnshardedName, "keyspace_id", "uint64"); err != nil { + return 1 + } + if err := clusterForKSTest.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", keyspaceUnshardedName); err != nil { + return 1 + } + + // Start vtgate + if err := clusterForKSTest.StartVtgate(); err != nil { + return 1 + } + + return m.Run() + }() + os.Exit(exitCode) +} + +func TestGetSrvKeyspaceNames(t *testing.T) { + defer cluster.PanicHandler(t) + output, err := clusterForKSTest.VtctlclientProcess.ExecuteCommandWithOutput("GetSrvKeyspaceNames", cell) + require.Nil(t, err) + assert.Contains(t, strings.Split(output, "\n"), keyspaceUnshardedName) + assert.Contains(t, strings.Split(output, "\n"), keyspaceShardedName) +} + +func TestGetSrvKeyspacePartitions(t *testing.T) { + defer cluster.PanicHandler(t) + shardedSrvKeyspace := getSrvKeyspace(t, cell, keyspaceShardedName) + otherShardRefFound := false + for _, partition := range shardedSrvKeyspace.Partitions { + if servedTypes[partition.ServedType] { + for _, shardRef := range partition.ShardReferences { + assert.True(t, shardRef.Name == "-80" || shardRef.Name == "80-") + } + } else { + otherShardRefFound = true + } + } + assert.True(t, !otherShardRefFound) + + unShardedSrvKeyspace := getSrvKeyspace(t, cell, keyspaceUnshardedName) + otherShardRefFound = false + for _, partition := range unShardedSrvKeyspace.Partitions { + if servedTypes[partition.ServedType] { + for _, shardRef := range partition.ShardReferences { + assert.True(t, shardRef.Name == keyspaceUnshardedName) + } + } else { + otherShardRefFound = true + } + } + assert.True(t, !otherShardRefFound) +} + +func TestShardNames(t *testing.T) { + defer cluster.PanicHandler(t) + output, err := clusterForKSTest.VtctlclientProcess.ExecuteCommandWithOutput("GetSrvKeyspace", cell, keyspaceShardedName) + require.Nil(t, err) + var srvKeyspace topodata.SrvKeyspace + + err = json.Unmarshal([]byte(output), &srvKeyspace) + require.Nil(t, err) +} + +func TestGetKeyspace(t *testing.T) { + defer cluster.PanicHandler(t) + output, err := clusterForKSTest.VtctlclientProcess.ExecuteCommandWithOutput("GetKeyspace", keyspaceUnshardedName) + require.Nil(t, err) + + var keyspace topodata.Keyspace + + err = json.Unmarshal([]byte(output), &keyspace) + require.Nil(t, err) + + assert.Equal(t, keyspace.ShardingColumnName, "keyspace_id") + assert.Equal(t, keyspace.ShardingColumnType, topodata.KeyspaceIdType(1)) +} + +func TestDeleteKeyspace(t *testing.T) { + defer cluster.PanicHandler(t) + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("CreateKeyspace", "test_delete_keyspace") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("CreateShard", "test_delete_keyspace/0") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("InitTablet", "-keyspace=test_delete_keyspace", "-shard=0", "zone1-0000000100", "master") + + // Can't delete keyspace if there are shards present. + err := clusterForKSTest.VtctlclientProcess.ExecuteCommand("DeleteKeyspace", "test_delete_keyspace") + require.Error(t, err) + + // Can't delete shard if there are tablets present. + err = clusterForKSTest.VtctlclientProcess.ExecuteCommand("DeleteShard", "-even_if_serving", "test_delete_keyspace/0") + require.Error(t, err) + + // Use recursive DeleteShard to remove tablets. + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("DeleteShard", "-even_if_serving", "-recursive", "test_delete_keyspace/0") + // Now non-recursive DeleteKeyspace should work. + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("DeleteKeyspace", "test_delete_keyspace") + + // Start over and this time use recursive DeleteKeyspace to do everything. + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("CreateKeyspace", "test_delete_keyspace") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("CreateShard", "test_delete_keyspace/0") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("InitTablet", "-port=1234", "-keyspace=test_delete_keyspace", "-shard=0", "zone1-0000000100", "master") + + // Create the serving/replication entries and check that they exist, + // so we can later check they're deleted. + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", "test_delete_keyspace") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetShardReplication", cell, "test_delete_keyspace/0") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetSrvKeyspace", cell, "test_delete_keyspace") + + // Recursive DeleteKeyspace + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("DeleteKeyspace", "-recursive", "test_delete_keyspace") + + // Check that everything is gone. + err = clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetKeyspace", "test_delete_keyspace") + require.Error(t, err) + err = clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetShard", "test_delete_keyspace/0") + require.Error(t, err) + err = clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetTablet", "zone1-0000000100") + require.Error(t, err) + err = clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetShardReplication", cell, "test_delete_keyspace/0") + require.Error(t, err) + err = clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetSrvKeyspace", cell, "test_delete_keyspace") + require.Error(t, err) +} + +// TODO: Fix this test, not running in CI +// tells that in zone2 after deleting shard, there is no shard #264 and in zone1 there is only 1 #269 +func RemoveKeyspaceCell(t *testing.T) { + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("CreateKeyspace", "test_delete_keyspace_removekscell") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("CreateShard", "test_delete_keyspace_removekscell/0") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("CreateShard", "test_delete_keyspace_removekscell/1") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("InitTablet", "-port=1234", "-keyspace=test_delete_keyspace_removekscell", "-shard=0", "zone1-0000000100", "master") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("InitTablet", "-port=1234", "-keyspace=test_delete_keyspace_removekscell", "-shard=1", "zone1-0000000101", "master") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("InitTablet", "-port=1234", "-keyspace=test_delete_keyspace_removekscell", "-shard=0", "zone2-0000000100", "replica") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("InitTablet", "-port=1234", "-keyspace=test_delete_keyspace_removekscell", "-shard=1", "zone2-0000000101", "replica") + + // Create the serving/replication entries and check that they exist, so we can later check they're deleted. + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", "test_delete_keyspace_removekscell") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetShardReplication", "zone2", "test_delete_keyspace_removekscell/0") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetShardReplication", "zone2", "test_delete_keyspace_removekscell/1") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetSrvKeyspace", "zone2", "test_delete_keyspace_removekscell") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetSrvKeyspace", "zone1", "test_delete_keyspace_removekscell") + + // Just remove the shard from one cell (including tablets), + // but leaving the global records and other cells/shards alone. + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("RemoveShardCell", "-recursive", "test_delete_keyspace_removekscell/0", "zone2") + + //Check that the shard is gone from zone2. + srvKeyspaceZone2 := getSrvKeyspace(t, cell2, "test_delete_keyspace_removekscell") + + for _, partition := range srvKeyspaceZone2.Partitions { + assert.Equal(t, len(partition.ShardReferences), 1) + } + + srvKeyspaceZone1 := getSrvKeyspace(t, cell, "test_delete_keyspace_removekscell") + for _, partition := range srvKeyspaceZone1.Partitions { + assert.Equal(t, len(partition.ShardReferences), 2) + } + + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", "test_delete_keyspace_removekscell") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetKeyspace", "test_delete_keyspace_removekscell") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetShard", "test_delete_keyspace_removekscell/0") + + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetTablet", "zone1-0000000100") + + err := clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetTablet", "zone2-0000000100") + require.Error(t, err) + + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetTablet", "zone2-0000000101") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetShardReplication", "zone1", "test_delete_keyspace_removekscell/0") + + err = clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetShardReplication", "zone2", "test_delete_keyspace_removekscell/0") + require.Error(t, err) + + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetShardReplication", "zone2", "test_delete_keyspace_removekscell/1") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetSrvKeyspace", "zone2", "test_delete_keyspace_removekscell") + + // Add it back to do another test. + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("InitTablet", "-port=1234", "-keyspace=test_delete_keyspace_removekscell", "-shard=0", "zone2-0000000100", "replica") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", "test_delete_keyspace_removekscell") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetShardReplication", "zone2", "test_delete_keyspace_removekscell/0") + + // Now use RemoveKeyspaceCell to remove all shards. + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("RemoveKeyspaceCell", "-recursive", "test_delete_keyspace_removekscell", "zone2") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", "test_delete_keyspace_removekscell") + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetShardReplication", "zone1", "test_delete_keyspace_removekscell/0") + + err = clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetShardReplication", "zone2", "test_delete_keyspace_removekscell/0") + require.Error(t, err) + + err = clusterForKSTest.VtctlclientProcess.ExecuteCommand("GetShardReplication", "zone2", "test_delete_keyspace_removekscell/1") + require.Error(t, err) + + // Clean up + _ = clusterForKSTest.VtctlclientProcess.ExecuteCommand("DeleteKeyspace", "-recursive", "test_delete_keyspace_removekscell") +} + +func TestShardCountForAllKeyspaces(t *testing.T) { + defer cluster.PanicHandler(t) + testShardCountForKeyspace(t, keyspaceUnshardedName, 1) + testShardCountForKeyspace(t, keyspaceShardedName, 2) +} + +func testShardCountForKeyspace(t *testing.T, keyspace string, count int) { + srvKeyspace := getSrvKeyspace(t, cell, keyspace) + + // for each served type MASTER REPLICA RDONLY, the shard ref count should match + for _, partition := range srvKeyspace.Partitions { + if servedTypes[partition.ServedType] { + assert.Equal(t, len(partition.ShardReferences), count) + } + } +} + +func TestShardNameForAllKeyspaces(t *testing.T) { + defer cluster.PanicHandler(t) + testShardNameForKeyspace(t, keyspaceUnshardedName, []string{"test_ks_unsharded"}) + testShardNameForKeyspace(t, keyspaceShardedName, []string{"-80", "80-"}) +} + +func testShardNameForKeyspace(t *testing.T, keyspace string, shardNames []string) { + srvKeyspace := getSrvKeyspace(t, cell, keyspace) + + // for each served type MASTER REPLICA RDONLY, the shard ref count should match + for _, partition := range srvKeyspace.Partitions { + if servedTypes[partition.ServedType] { + for _, shardRef := range partition.ShardReferences { + assert.Contains(t, shardNames, shardRef.Name) + } + } + } +} + +func TestKeyspaceToShardName(t *testing.T) { + defer cluster.PanicHandler(t) + var id []byte + srvKeyspace := getSrvKeyspace(t, cell, keyspaceShardedName) + + // for each served type MASTER REPLICA RDONLY, the shard ref count should match + for _, partition := range srvKeyspace.Partitions { + if partition.ServedType == topodata.TabletType_MASTER { + for _, shardRef := range partition.ShardReferences { + shardKIDs := shardKIdMap[shardRef.Name] + for _, kid := range shardKIDs { + id = packKeyspaceID(kid) + assert.True(t, bytes.Compare(shardRef.KeyRange.Start, id) <= 0 && + (len(shardRef.KeyRange.End) == 0 || bytes.Compare(id, shardRef.KeyRange.End) < 0)) + } + } + } + } + + srvKeyspace = getSrvKeyspace(t, cell, keyspaceUnshardedName) + + for _, partition := range srvKeyspace.Partitions { + if partition.ServedType == topodata.TabletType_MASTER { + for _, shardRef := range partition.ShardReferences { + assert.Equal(t, shardRef.Name, keyspaceUnshardedName) + } + } + } +} + +// packKeyspaceID packs this into big-endian and returns byte[] to do a byte-wise comparison. +func packKeyspaceID(keyspaceID uint64) []byte { + var keybytes [8]byte + binary.BigEndian.PutUint64(keybytes[:], keyspaceID) + return (keybytes[:]) +} + +func getSrvKeyspace(t *testing.T, cell string, ksname string) *topodata.SrvKeyspace { + output, err := clusterForKSTest.VtctlclientProcess.ExecuteCommandWithOutput("GetSrvKeyspace", cell, ksname) + require.Nil(t, err) + var srvKeyspace topodata.SrvKeyspace + + err = json.Unmarshal([]byte(output), &srvKeyspace) + require.Nil(t, err) + return &srvKeyspace +} diff --git a/go/test/endtoend/messaging/main_test.go b/go/test/endtoend/messaging/main_test.go new file mode 100644 index 00000000000..b6660fe4f7a --- /dev/null +++ b/go/test/endtoend/messaging/main_test.go @@ -0,0 +1,144 @@ +/* +Copyright 2020 The Vitess Authors. + +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. +*/ + +package messaging + +import ( + "flag" + "fmt" + "os" + "testing" + + _ "vitess.io/vitess/go/vt/vtgate/grpcvtgateconn" + + "vitess.io/vitess/go/test/endtoend/cluster" +) + +var ( + clusterInstance *cluster.LocalProcessCluster + shard0Master *cluster.Vttablet + shard0Replica *cluster.Vttablet + shard1Master *cluster.Vttablet + lookupMaster *cluster.Vttablet + hostname = "localhost" + cell = "zone1" + userKeyspace = "user" + lookupKeyspace = "lookup" + createShardedMessage = `create table sharded_message( + time_scheduled bigint, + id bigint, + time_next bigint, + epoch bigint, + time_created bigint, + time_acked bigint, + message varchar(128), + primary key(time_scheduled, id), + unique index id_idx(id), + index next_idx(time_next, epoch) + ) comment 'vitess_message,vt_ack_wait=1,vt_purge_after=3,vt_batch_size=2,vt_cache_size=10,vt_poller_interval=1'` + createUnshardedMessage = `create table unsharded_message( + time_scheduled bigint, + id bigint, + time_next bigint, + epoch bigint, + time_created bigint, + time_acked bigint, + message varchar(128), + primary key(time_scheduled, id), + unique index id_idx(id), + index next_idx(time_next, epoch) + ) comment 'vitess_message,vt_ack_wait=1,vt_purge_after=3,vt_batch_size=2,vt_cache_size=10,vt_poller_interval=1'` + userVschema = `{ + "sharded": true, + "vindexes": { + "hash_index": { + "type": "hash" + } + }, + "tables": { + "sharded_message": { + "column_vindexes": [ + { + "column": "id", + "name": "hash_index" + } + ] + } + } + }` + lookupVschema = `{ + "sharded": false, + "tables": { + "unsharded_message": { + "type": "sequence" + } + } + }` +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitcode, err := func() (int, error) { + clusterInstance = cluster.NewCluster(cell, hostname) + defer clusterInstance.Teardown() + + // Start topo server + if err := clusterInstance.StartTopo(); err != nil { + return 1, err + } + + // Start unsharded keyspace + keyspace := cluster.Keyspace{ + Name: lookupKeyspace, + SchemaSQL: createUnshardedMessage, + VSchema: lookupVschema, + } + if err := clusterInstance.StartUnshardedKeyspace(keyspace, 1, false); err != nil { + return 1, err + } + + // Start sharded keyspace + keyspace = cluster.Keyspace{ + Name: userKeyspace, + SchemaSQL: createShardedMessage, + VSchema: userVschema, + } + if err := clusterInstance.StartKeyspace(keyspace, []string{"-80", "80-"}, 1, false); err != nil { + return 1, err + } + + // Start vtgate + if err := clusterInstance.StartVtgate(); err != nil { + return 1, err + } + + shard0Master = clusterInstance.Keyspaces[1].Shards[0].MasterTablet() + shard1Master = clusterInstance.Keyspaces[1].Shards[1].MasterTablet() + lookupMaster = clusterInstance.Keyspaces[0].Shards[0].MasterTablet() + shard0Replica = clusterInstance.Keyspaces[1].Shards[0].Vttablets[1] + + return m.Run(), nil + }() + if err != nil { + fmt.Printf("%v\n", err) + os.Exit(1) + } else { + os.Exit(exitcode) + } + +} diff --git a/go/test/endtoend/messaging/messaging_test.go b/go/test/endtoend/messaging/messaging_test.go new file mode 100644 index 00000000000..5281490c1d8 --- /dev/null +++ b/go/test/endtoend/messaging/messaging_test.go @@ -0,0 +1,330 @@ +/* +Copyright 2020 The Vitess Authors. + +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. +*/ + +package messaging + +import ( + "context" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "strconv" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/test/endtoend/cluster" + "vitess.io/vitess/go/vt/proto/query" + "vitess.io/vitess/go/vt/proto/topodata" + "vitess.io/vitess/go/vt/vtgate/vtgateconn" +) + +func TestSharded(t *testing.T) { + // validate the messaging for sharded keyspace(user) + testMessaging(t, "sharded_message", userKeyspace) +} + +func TestUnsharded(t *testing.T) { + // validate messaging for unsharded keyspace(lookup) + testMessaging(t, "unsharded_message", lookupKeyspace) +} + +// TestRepareting checks the client connection count after reparenting. +func TestRepareting(t *testing.T) { + defer cluster.PanicHandler(t) + name := "sharded_message" + + ctx := context.Background() + // start grpc connection with vtgate and validate client + // connection counts in tablets + stream, err := VtgateGrpcConn(ctx, clusterInstance) + require.Nil(t, err) + defer stream.Close() + _, err = stream.MessageStream(userKeyspace, "", nil, name) + require.Nil(t, err) + + assert.Equal(t, 1, getClientCount(shard0Master)) + assert.Equal(t, 0, getClientCount(shard0Replica)) + assert.Equal(t, 1, getClientCount(shard1Master)) + + // do planned reparenting, make one replica as master + // and validate client connection count in correspond tablets + clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput( + "PlannedReparentShard", + "-keyspace_shard", userKeyspace+"/-80", + "-new_master", shard0Replica.Alias) + // validate topology + err = clusterInstance.VtctlclientProcess.ExecuteCommand("Validate") + require.Nil(t, err) + + // Verify connection has migrated. + // The wait must be at least 6s which is how long vtgate will + // wait before retrying: that is 30s/5 where 30s is the default + // message_stream_grace_period. + time.Sleep(10 * time.Second) + assert.Equal(t, 0, getClientCount(shard0Master)) + assert.Equal(t, 1, getClientCount(shard0Replica)) + assert.Equal(t, 1, getClientCount(shard1Master)) + session := stream.Session("@master", nil) + cluster.ExecuteQueriesUsingVtgate(t, session, "insert into sharded_message (id, message) values (3,'hello world 3')") + + // validate that we have received inserted message + stream.Next() + + // make old master again as new master + clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput( + "PlannedReparentShard", + "-keyspace_shard", userKeyspace+"/-80", + "-new_master", shard0Master.Alias) + // validate topology + err = clusterInstance.VtctlclientProcess.ExecuteCommand("Validate") + require.Nil(t, err) + time.Sleep(10 * time.Second) + assert.Equal(t, 1, getClientCount(shard0Master)) + assert.Equal(t, 0, getClientCount(shard0Replica)) + assert.Equal(t, 1, getClientCount(shard1Master)) + + _, err = stream.MessageAck(ctx, userKeyspace, name, keyRange(3)) + require.Nil(t, err) +} + +// TestConnection validate the connection count and message streaming. +func TestConnection(t *testing.T) { + defer cluster.PanicHandler(t) + + name := "sharded_message" + + // 1 sec sleep added to avoid invalid connection count + time.Sleep(time.Second) + + // create two grpc connection with vtgate and verify + // client connection count in vttablet of the master + assert.Equal(t, 0, getClientCount(shard0Master)) + assert.Equal(t, 0, getClientCount(shard1Master)) + + ctx := context.Background() + // first connection with vtgate + stream, err := VtgateGrpcConn(ctx, clusterInstance) + require.Nil(t, err) + _, err = stream.MessageStream(userKeyspace, "", nil, name) + require.Nil(t, err) + // validate client count of vttablet + assert.Equal(t, 1, getClientCount(shard0Master)) + assert.Equal(t, 1, getClientCount(shard1Master)) + // second connection with vtgate, secont connection + // will only be used for client connection counts + stream1, err := VtgateGrpcConn(ctx, clusterInstance) + require.Nil(t, err) + _, err = stream1.MessageStream(userKeyspace, "", nil, name) + require.Nil(t, err) + // validate client count of vttablet + assert.Equal(t, 2, getClientCount(shard0Master)) + assert.Equal(t, 2, getClientCount(shard1Master)) + + // insert data in master and validate that we receive this + // in message stream + session := stream.Session("@master", nil) + // insert data in master + cluster.ExecuteQueriesUsingVtgate(t, session, "insert into sharded_message (id, message) values (2,'hello world 2')") + cluster.ExecuteQueriesUsingVtgate(t, session, "insert into sharded_message (id, message) values (5,'hello world 5')") + // validate in msg stream + _, err = stream.Next() + require.Nil(t, err) + _, err = stream.Next() + require.Nil(t, err) + + _, err = stream.MessageAck(ctx, userKeyspace, name, keyRange(2, 5)) + require.Nil(t, err) + // After closing one stream, ensure vttablets have dropped it. + stream.Close() + time.Sleep(time.Second) + assert.Equal(t, 1, getClientCount(shard0Master)) + assert.Equal(t, 1, getClientCount(shard1Master)) + + stream1.Close() +} + +func testMessaging(t *testing.T, name, ks string) { + defer cluster.PanicHandler(t) + ctx := context.Background() + stream, err := VtgateGrpcConn(ctx, clusterInstance) + require.Nil(t, err) + defer stream.Close() + + session := stream.Session("@master", nil) + cluster.ExecuteQueriesUsingVtgate(t, session, "insert into "+name+" (id, message) values (1,'hello world 1')") + cluster.ExecuteQueriesUsingVtgate(t, session, "insert into "+name+" (id, message) values (4,'hello world 4')") + + // validate fields + res, err := stream.MessageStream(ks, "", nil, name) + require.Nil(t, err) + require.Equal(t, 3, len(res.Fields)) + validateField(t, res.Fields[0], "id", query.Type_INT64) + validateField(t, res.Fields[1], "time_scheduled", query.Type_INT64) + validateField(t, res.Fields[2], "message", query.Type_VARCHAR) + + // validate recieved msgs + resMap := make(map[string]string) + res, err = stream.Next() + require.Nil(t, err) + for _, row := range res.Rows { + resMap[row[0].ToString()] = row[2].ToString() + } + + res, err = stream.Next() + require.Nil(t, err) + for _, row := range res.Rows { + resMap[row[0].ToString()] = row[2].ToString() + } + + assert.Equal(t, "hello world 1", resMap["1"]) + assert.Equal(t, "hello world 4", resMap["4"]) + + resMap = make(map[string]string) + // validate message ack with id 4 + count, err := stream.MessageAck(ctx, ks, name, keyRange(4)) + require.Nil(t, err) + assert.Equal(t, int64(1), count) + res, err = stream.Next() + require.Nil(t, err) + for _, row := range res.Rows { + resMap[row[0].ToString()] = row[2].ToString() + } + + res, err = stream.Next() + require.Nil(t, err) + for _, row := range res.Rows { + resMap[row[0].ToString()] = row[2].ToString() + } + + assert.Equal(t, "hello world 1", resMap["1"]) + + // validate message ack with 1 and 4, only 1 should be ack + count, err = stream.MessageAck(ctx, ks, name, keyRange(1, 4)) + require.Nil(t, err) + assert.Equal(t, int64(1), count) +} + +func validateField(t *testing.T, field *query.Field, name string, _type query.Type) { + assert.Equal(t, name, field.Name) + assert.Equal(t, _type, field.Type) +} + +// MsgStream handles all meta required for grpc connection with vtgate. +type VTGateStream struct { + ctx context.Context + host string + respChan chan *sqltypes.Result + *vtgateconn.VTGateConn +} + +// VtgateGrpcConn create new msg stream for grpc connection with vtgate. +func VtgateGrpcConn(ctx context.Context, cluster *cluster.LocalProcessCluster) (*VTGateStream, error) { + stream := new(VTGateStream) + stream.ctx = ctx + stream.host = fmt.Sprintf("%s:%d", cluster.Hostname, cluster.VtgateProcess.GrpcPort) + conn, err := vtgateconn.Dial(ctx, stream.host) + // init components + stream.respChan = make(chan *sqltypes.Result) + stream.VTGateConn = conn + + return stream, err +} + +// MessageStream strarts the stream for the corresponding connection. +func (stream *VTGateStream) MessageStream(ks, shard string, keyRange *topodata.KeyRange, name string) (*sqltypes.Result, error) { + // start message stream which send received message to the respChan + go stream.VTGateConn.MessageStream(stream.ctx, ks, shard, keyRange, name, func(s *sqltypes.Result) error { + stream.respChan <- s + return nil + }) + // wait for field details + return stream.Next() +} + +// Next reads the new msg available in stream. +func (stream *VTGateStream) Next() (*sqltypes.Result, error) { + ticker := time.Tick(10 * time.Second) + select { + case s := <-stream.respChan: + return s, nil + case <-ticker: + return nil, fmt.Errorf("time limit exceeded") + } +} + +// getClientCount read connected client count from the vttablet debug vars. +func getClientCount(vttablet *cluster.Vttablet) int { + vars, err := getVar(vttablet) + if err != nil { + return 0 + } + + msg, ok := vars["Messages"] + if !ok { + return 0 + } + + v, ok := msg.(map[string]interface{}) + if !ok { + return 0 + } + + countStr, ok := v["sharded_message.ClientCount"] + if !ok { + return 0 + } + + i, err := strconv.ParseInt(fmt.Sprint(countStr), 10, 16) + if err != nil { + return 0 + } + + return int(i) +} + +// getVar read debug vars from the vttablet. +func getVar(vttablet *cluster.Vttablet) (map[string]interface{}, error) { + resp, err := http.Get(fmt.Sprintf("http://%s:%d/debug/vars", vttablet.VttabletProcess.TabletHostname, vttablet.HTTPPort)) + if err != nil { + return nil, err + } + if resp.StatusCode == 200 { + resultMap := make(map[string]interface{}) + respByte, _ := ioutil.ReadAll(resp.Body) + err := json.Unmarshal(respByte, &resultMap) + return resultMap, err + } + return nil, nil +} + +// keyRange created keyRange array for correponding ids +func keyRange(s ...int) []*query.Value { + out := make([]*query.Value, 0, len(s)) + + for _, v := range s { + q := new(query.Value) + q.Type = query.Type_INT64 + q.Value = []byte(fmt.Sprint(v)) + + out = append(out, q) + } + + return out +} diff --git a/go/test/endtoend/mysqlctl/mysqlctl_test.go b/go/test/endtoend/mysqlctl/mysqlctl_test.go new file mode 100644 index 00000000000..986e4ef1e24 --- /dev/null +++ b/go/test/endtoend/mysqlctl/mysqlctl_test.go @@ -0,0 +1,171 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package mysqlctl + +import ( + "flag" + "fmt" + "os" + "os/exec" + "testing" + + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/vt/log" + + "vitess.io/vitess/go/test/endtoend/cluster" +) + +var ( + clusterInstance *cluster.LocalProcessCluster + masterTablet cluster.Vttablet + replicaTablet cluster.Vttablet + hostname = "localhost" + keyspaceName = "test_keyspace" + shardName = "0" + cell = "zone1" +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitCode := func() int { + clusterInstance = cluster.NewCluster(cell, hostname) + defer clusterInstance.Teardown() + + // Start topo server + err := clusterInstance.StartTopo() + if err != nil { + return 1 + } + + if err := clusterInstance.VtctlProcess.CreateKeyspace(keyspaceName); err != nil { + return 1 + } + + initCluster([]string{"0"}, 2) + + // Collect tablet paths and ports + tablets := clusterInstance.Keyspaces[0].Shards[0].Vttablets + for _, tablet := range tablets { + if tablet.Type == "master" { + masterTablet = *tablet + } else if tablet.Type != "rdonly" { + replicaTablet = *tablet + } + } + + return m.Run() + }() + os.Exit(exitCode) +} + +func initCluster(shardNames []string, totalTabletsRequired int) { + keyspace := cluster.Keyspace{ + Name: keyspaceName, + } + for _, shardName := range shardNames { + shard := &cluster.Shard{ + Name: shardName, + } + var mysqlCtlProcessList []*exec.Cmd + for i := 0; i < totalTabletsRequired; i++ { + // instantiate vttablet object with reserved ports + tabletUID := clusterInstance.GetAndReserveTabletUID() + tablet := &cluster.Vttablet{ + TabletUID: tabletUID, + HTTPPort: clusterInstance.GetAndReservePort(), + GrpcPort: clusterInstance.GetAndReservePort(), + MySQLPort: clusterInstance.GetAndReservePort(), + Alias: fmt.Sprintf("%s-%010d", clusterInstance.Cell, tabletUID), + } + if i == 0 { // Make the first one as master + tablet.Type = "master" + } + // Start Mysqlctl process + tablet.MysqlctlProcess = *cluster.MysqlCtlProcessInstance(tablet.TabletUID, tablet.MySQLPort, clusterInstance.TmpDirectory) + proc, err := tablet.MysqlctlProcess.StartProcess() + if err != nil { + return + } + mysqlCtlProcessList = append(mysqlCtlProcessList, proc) + + // start vttablet process + tablet.VttabletProcess = cluster.VttabletProcessInstance(tablet.HTTPPort, + tablet.GrpcPort, + tablet.TabletUID, + clusterInstance.Cell, + shardName, + keyspaceName, + clusterInstance.VtctldProcess.Port, + tablet.Type, + clusterInstance.TopoProcess.Port, + clusterInstance.Hostname, + clusterInstance.TmpDirectory, + clusterInstance.VtTabletExtraArgs, + clusterInstance.EnableSemiSync) + tablet.Alias = tablet.VttabletProcess.TabletPath + + shard.Vttablets = append(shard.Vttablets, tablet) + } + for _, proc := range mysqlCtlProcessList { + if err := proc.Wait(); err != nil { + return + } + } + + for _, tablet := range shard.Vttablets { + if _, err := tablet.VttabletProcess.QueryTablet(fmt.Sprintf("create database vt_%s", keyspace.Name), keyspace.Name, false); err != nil { + log.Error(err.Error()) + return + } + } + + keyspace.Shards = append(keyspace.Shards, *shard) + } + clusterInstance.Keyspaces = append(clusterInstance.Keyspaces, keyspace) +} + +func TestRestart(t *testing.T) { + defer cluster.PanicHandler(t) + err := masterTablet.MysqlctlProcess.Stop() + require.Nil(t, err) + masterTablet.MysqlctlProcess.CleanupFiles(masterTablet.TabletUID) + err = masterTablet.MysqlctlProcess.Start() + require.Nil(t, err) +} + +func TestAutoDetect(t *testing.T) { + defer cluster.PanicHandler(t) + + // Start up tablets with an empty MYSQL_FLAVOR, which means auto-detect + sqlFlavor := os.Getenv("MYSQL_FLAVOR") + os.Setenv("MYSQL_FLAVOR", "") + + err := clusterInstance.Keyspaces[0].Shards[0].Vttablets[0].VttabletProcess.Setup() + require.Nil(t, err, "error should be nil") + err = clusterInstance.Keyspaces[0].Shards[0].Vttablets[1].VttabletProcess.Setup() + require.Nil(t, err, "error should be nil") + + // Reparent tablets, which requires flavor detection + err = clusterInstance.VtctlclientProcess.InitShardMaster(keyspaceName, shardName, cell, masterTablet.TabletUID) + require.Nil(t, err, "error should be nil") + + //Reset flavor + os.Setenv("MYSQL_FLAVOR", sqlFlavor) + +} diff --git a/go/test/endtoend/mysqlctld/mysqlctld_test.go b/go/test/endtoend/mysqlctld/mysqlctld_test.go new file mode 100644 index 00000000000..3967190c9ca --- /dev/null +++ b/go/test/endtoend/mysqlctld/mysqlctld_test.go @@ -0,0 +1,167 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package mysqlctld + +import ( + "flag" + "fmt" + "os" + "testing" + + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/vt/log" + + "vitess.io/vitess/go/test/endtoend/cluster" +) + +var ( + clusterInstance *cluster.LocalProcessCluster + masterTablet *cluster.Vttablet + replicaTablet *cluster.Vttablet + hostname = "localhost" + keyspaceName = "test_keyspace" + shardName = "0" + cell = "zone1" +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitCode := func() int { + clusterInstance = cluster.NewCluster(cell, hostname) + defer clusterInstance.Teardown() + + // Start topo server + err := clusterInstance.StartTopo() + if err != nil { + return 1 + } + + if err := clusterInstance.VtctlProcess.CreateKeyspace(keyspaceName); err != nil { + return 1 + } + + if err := initCluster([]string{"0"}, 2); err != nil { + return 1 + } + + // Collect tablet paths and ports + tablets := clusterInstance.Keyspaces[0].Shards[0].Vttablets + for _, tablet := range tablets { + if tablet.Type == "master" { + masterTablet = tablet + } else if tablet.Type != "rdonly" { + replicaTablet = tablet + } + } + + return m.Run() + }() + os.Exit(exitCode) +} + +func initCluster(shardNames []string, totalTabletsRequired int) error { + keyspace := cluster.Keyspace{ + Name: keyspaceName, + } + for _, shardName := range shardNames { + shard := &cluster.Shard{ + Name: shardName, + } + for i := 0; i < totalTabletsRequired; i++ { + // instantiate vttablet object with reserved ports + tabletUID := clusterInstance.GetAndReserveTabletUID() + tablet := &cluster.Vttablet{ + TabletUID: tabletUID, + HTTPPort: clusterInstance.GetAndReservePort(), + GrpcPort: clusterInstance.GetAndReservePort(), + MySQLPort: clusterInstance.GetAndReservePort(), + Alias: fmt.Sprintf("%s-%010d", clusterInstance.Cell, tabletUID), + } + if i == 0 { // Make the first one as master + tablet.Type = "master" + } + // Start Mysqlctld process + tablet.MysqlctldProcess = *cluster.MysqlCtldProcessInstance(tablet.TabletUID, tablet.MySQLPort, clusterInstance.TmpDirectory) + err := tablet.MysqlctldProcess.Start() + if err != nil { + return err + } + + // start vttablet process + tablet.VttabletProcess = cluster.VttabletProcessInstance(tablet.HTTPPort, + tablet.GrpcPort, + tablet.TabletUID, + clusterInstance.Cell, + shardName, + keyspaceName, + clusterInstance.VtctldProcess.Port, + tablet.Type, + clusterInstance.TopoProcess.Port, + clusterInstance.Hostname, + clusterInstance.TmpDirectory, + clusterInstance.VtTabletExtraArgs, + clusterInstance.EnableSemiSync) + tablet.Alias = tablet.VttabletProcess.TabletPath + + shard.Vttablets = append(shard.Vttablets, tablet) + } + + for _, tablet := range shard.Vttablets { + if _, err := tablet.VttabletProcess.QueryTablet(fmt.Sprintf("create database vt_%s", keyspace.Name), "", false); err != nil { + log.Error(err.Error()) + return err + } + } + + keyspace.Shards = append(keyspace.Shards, *shard) + } + clusterInstance.Keyspaces = append(clusterInstance.Keyspaces, keyspace) + + return nil +} + +func TestRestart(t *testing.T) { + defer cluster.PanicHandler(t) + err := masterTablet.MysqlctldProcess.Stop() + require.Nil(t, err) + masterTablet.MysqlctldProcess.CleanupFiles(masterTablet.TabletUID) + err = masterTablet.MysqlctldProcess.Start() + require.Nil(t, err) +} + +func TestAutoDetect(t *testing.T) { + defer cluster.PanicHandler(t) + + // Start up tablets with an empty MYSQL_FLAVOR, which means auto-detect + sqlFlavor := os.Getenv("MYSQL_FLAVOR") + os.Setenv("MYSQL_FLAVOR", "") + + err := clusterInstance.Keyspaces[0].Shards[0].Vttablets[0].VttabletProcess.Setup() + require.Nil(t, err, "error should be nil") + err = clusterInstance.Keyspaces[0].Shards[0].Vttablets[1].VttabletProcess.Setup() + require.Nil(t, err, "error should be nil") + + // Reparent tablets, which requires flavor detection + err = clusterInstance.VtctlclientProcess.InitShardMaster(keyspaceName, shardName, cell, masterTablet.TabletUID) + require.Nil(t, err, "error should be nil") + + //Reset flavor + os.Setenv("MYSQL_FLAVOR", sqlFlavor) + +} diff --git a/go/test/endtoend/mysqlserver/main_test.go b/go/test/endtoend/mysqlserver/main_test.go new file mode 100644 index 00000000000..e26f1962630 --- /dev/null +++ b/go/test/endtoend/mysqlserver/main_test.go @@ -0,0 +1,137 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package mysqlserver + +import ( + "flag" + "fmt" + "os" + "testing" + + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/test/endtoend/cluster" +) + +var ( + clusterInstance *cluster.LocalProcessCluster + vtParams mysql.ConnParams + hostname = "localhost" + keyspaceName = "test_keyspace" + tableACLConfig = "/table_acl_config.json" + mysqlAuthServerStatic = "/mysql_auth_server_static.json" + cell = "zone1" + sqlSchema = `create table vt_insert_test ( + id bigint auto_increment, + msg varchar(64), + keyspace_id bigint(20) unsigned NOT NULL, + data longblob, + primary key (id) + ) Engine=InnoDB` +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + // setting grpc max size + if os.Getenv("grpc_max_massage_size") == "" { + os.Setenv("grpc_max_message_size", fmt.Sprint(16*1024*1024)) + } + + exitcode, err := func() (int, error) { + clusterInstance = cluster.NewCluster(cell, hostname) + defer clusterInstance.Teardown() + + // Start topo server + if err := clusterInstance.StartTopo(); err != nil { + return 1, err + } + + // create acl config + ACLConfig := `{ + "table_groups": [ + { + "table_names_or_prefixes": ["vt_insert_test", "dual"], + "readers": ["vtgate client 1"], + "writers": ["vtgate client 1"], + "admins": ["vtgate client 1"] + } + ] + }` + if err := createConfig(tableACLConfig, ACLConfig); err != nil { + return 1, err + } + + // create auth server config + SQLConfig := `{ + "testuser1": { + "Password": "testpassword1", + "UserData": "vtgate client 1" + }, + "testuser2": { + "Password": "testpassword2", + "UserData": "vtgate client 2" + } + }` + if err := createConfig(mysqlAuthServerStatic, SQLConfig); err != nil { + return 1, err + } + + clusterInstance.VtGateExtraArgs = []string{ + "-vschema_ddl_authorized_users=%", + "-mysql_server_query_timeout", "1s", + "-mysql_auth_server_impl", "static", + "-mysql_auth_server_static_file", clusterInstance.TmpDirectory + mysqlAuthServerStatic, + "-mysql_server_version", "8.0.16-7", + } + + clusterInstance.VtTabletExtraArgs = []string{ + "-table-acl-config", clusterInstance.TmpDirectory + tableACLConfig, + "-queryserver-config-strict-table-acl", + } + + // Start keyspace + keyspace := &cluster.Keyspace{ + Name: keyspaceName, + SchemaSQL: sqlSchema, + } + if err := clusterInstance.StartUnshardedKeyspace(*keyspace, 1, false); err != nil { + return 1, err + } + + // Start vtgate + if err := clusterInstance.StartVtgate(); err != nil { + return 1, err + } + + vtParams = mysql.ConnParams{ + Host: clusterInstance.Hostname, + Port: clusterInstance.VtgateMySQLPort, + Uname: "testuser1", + Pass: "testpassword1", + } + + return m.Run(), nil + }() + if err != nil { + fmt.Printf("%v\n", err) + os.Exit(1) + } else { + os.Exit(exitcode) + } + +} diff --git a/go/test/endtoend/mysqlserver/mysql_server_test.go b/go/test/endtoend/mysqlserver/mysql_server_test.go new file mode 100644 index 00000000000..656e0b509f5 --- /dev/null +++ b/go/test/endtoend/mysqlserver/mysql_server_test.go @@ -0,0 +1,222 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +R442 +*/ + +package mysqlserver + +import ( + "context" + "fmt" + "os" + "strconv" + "strings" + "testing" + + "github.com/icrowley/fake" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/test/endtoend/cluster" + + "database/sql" + + _ "github.com/go-sql-driver/mysql" +) + +// TestMultiStmt checks that multiStatements=True and multiStatements=False work properly. +func TestMultiStatement(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + + // connect database with multiStatements=True + db := connectDB(t, vtParams, "multiStatements=True", "timeout=90s", "collation=utf8mb4_unicode_ci") + + rows, err := db.QueryContext(ctx, "SELECT 1; SELECT 2; SELECT 3") + require.Nilf(t, err, "multiple statements should be executed without error, got %v", err) + var count int + for rows.Next() || (rows.NextResultSet() && rows.Next()) { + var i int + rows.Scan(&i) + count++ + assert.Equalf(t, count, i, "result of query %v query should be %v, got %v", count, count, i) + } + assert.Equalf(t, 3, count, "this query should affect 3 row, got %v", count) + db.Close() + + // connect database with multiStatements=False + db = connectDB(t, vtParams, "multiStatements=False", "timeout=90s", "collation=utf8mb4_unicode_ci") + + _, err = db.QueryContext(ctx, "SELECT 1; SELECT 2; SELECT 3") + require.NotNilf(t, err, "error expected, got nil error") + assert.Containsf(t, err.Error(), "syntax error", "expected syntax error, got %v", err) +} + +// TestLargeComment add large comment in insert stmt and validate the insert process. +func TestLargeComment(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + + conn, err := mysql.Connect(ctx, &vtParams) + require.Nilf(t, err, "unable to connect mysql: %v", err) + defer conn.Close() + + // insert data with large comment + _, err = conn.ExecuteFetch("insert into vt_insert_test (id, msg, keyspace_id, data) values(1, 'large blob', 123, 'LLL') /* "+fake.CharactersN(4*1024*1024)+" */", 1, false) + require.Nilf(t, err, "insertion error: %v", err) + + qr, err := conn.ExecuteFetch("select * from vt_insert_test where id = 1", 1, false) + require.Nilf(t, err, "select error: %v", err) + assert.Equal(t, uint64(1), qr.RowsAffected) + assert.Equal(t, "BLOB(\"LLL\")", qr.Rows[0][3].String()) +} + +// TestInsertLargerThenGrpcLimit insert blob larger then grpc limit and verify the error. +func TestInsertLargerThenGrpcLimit(t *testing.T) { + defer cluster.PanicHandler(t) + + ctx := context.Background() + + conn, err := mysql.Connect(ctx, &vtParams) + require.Nilf(t, err, "unable to connect mysql: %v", err) + defer conn.Close() + + grpcLimit := os.Getenv("grpc_max_message_size") + limit, err := strconv.Atoi(grpcLimit) + require.Nilf(t, err, "int parsing error: %v", err) + + // insert data with large blob + _, err = conn.ExecuteFetch("insert into vt_insert_test (id, msg, keyspace_id, data) values(2, 'huge blob', 123, '"+fake.CharactersN(limit+1)+"')", 1, false) + require.NotNil(t, err, "error expected on insert") + assert.Contains(t, err.Error(), "trying to send message larger than max") +} + +// TestTimeout executes sleep(5) with query_timeout of 1 second, and verifies the error. +func TestTimeout(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + + conn, err := mysql.Connect(ctx, &vtParams) + require.Nilf(t, err, "unable to connect mysql: %v", err) + defer conn.Close() + + _, err = conn.ExecuteFetch("SELECT SLEEP(5);", 1, false) + require.NotNilf(t, err, "quiry timeout error expected") + mysqlErr, ok := err.(*mysql.SQLError) + require.Truef(t, ok, "invalid error type") + assert.Equal(t, 1317, mysqlErr.Number(), err) +} + +// TestInvalidField tries to fetch invalid column and verifies the error. +func TestInvalidField(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + + conn, err := mysql.Connect(ctx, &vtParams) + require.Nilf(t, err, "unable to connect mysql: %v", err) + defer conn.Close() + + _, err = conn.ExecuteFetch("SELECT invalid_field from vt_insert_test;", 1, false) + require.NotNil(t, err, "invalid field error expected") + mysqlErr, ok := err.(*mysql.SQLError) + require.Truef(t, ok, "invalid error type") + assert.Equal(t, 1054, mysqlErr.Number(), err) +} + +// TestWarnings validates the behaviour of SHOW WARNINGS. +func TestWarnings(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + + conn, err := mysql.Connect(ctx, &vtParams) + require.Nilf(t, err, "unable to connect mysql: %v", err) + defer conn.Close() + + // validate warning with invalid_field error as warning + qr, err := conn.ExecuteFetch("SELECT /*vt+ SCATTER_ERRORS_AS_WARNINGS */ invalid_field from vt_insert_test;", 1, false) + require.Nilf(t, err, "select error : %v", err) + assert.Equalf(t, uint64(0), qr.RowsAffected, "query should return 0 rows, got %v", qr.RowsAffected) + + qr, err = conn.ExecuteFetch("SHOW WARNINGS;", 1, false) + require.Nilf(t, err, "SHOW WARNINGS; execution failed: %v", err) + assert.Equalf(t, uint64(1), qr.RowsAffected, "1 warning expected, got %v ", qr.RowsAffected) + assert.Contains(t, qr.Rows[0][0].String(), "VARCHAR(\"Warning\")", qr.Rows) + assert.Contains(t, qr.Rows[0][1].String(), "UINT16(1054)", qr.Rows) + assert.Contains(t, qr.Rows[0][2].String(), "Unknown column", qr.Rows) + + // validate warning with query_timeout error as warning + qr, err = conn.ExecuteFetch("SELECT /*vt+ SCATTER_ERRORS_AS_WARNINGS QUERY_TIMEOUT_MS=1 */ sleep(1) from vt_insert_test;", 1, false) + require.Nilf(t, err, "insertion error : %v", err) + assert.Equalf(t, uint64(0), qr.RowsAffected, "should return 0 rows, got %v", qr.RowsAffected) + + qr, err = conn.ExecuteFetch("SHOW WARNINGS;", 1, false) + require.Nilf(t, err, "SHOW WARNINGS; execution failed: %v", err) + assert.Equalf(t, uint64(1), qr.RowsAffected, "1 warning expected, got %v ", qr.RowsAffected) + assert.Contains(t, qr.Rows[0][0].String(), "VARCHAR(\"Warning\")", qr.Rows) + assert.Contains(t, qr.Rows[0][1].String(), "UINT16(1317)", qr.Rows) + assert.Contains(t, qr.Rows[0][2].String(), "context deadline exceeded", qr.Rows) + + // validate with 0 warnings + _, err = conn.ExecuteFetch("SELECT 1 from vt_insert_test limit 1", 1, false) + require.Nilf(t, err, "select error: %v", err) + + qr, err = conn.ExecuteFetch("SHOW WARNINGS;", 1, false) + require.Nilf(t, err, "SHOW WARNINGS; execution failed: %v", err) + assert.Equalf(t, uint64(0), qr.RowsAffected, "0 warning expected, got %v ", qr.RowsAffected) +} + +// TestSelectWithUnauthorizedUser verifies that an unauthorized user +// is not able to read from the table. +func TestSelectWithUnauthorizedUser(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + + tmpVtParam := vtParams + tmpVtParam.Uname = "testuser2" + tmpVtParam.Pass = "testpassword2" + + conn, err := mysql.Connect(ctx, &tmpVtParam) + require.Nilf(t, err, "unable to connect to mysql: %v", err) + defer conn.Close() + + _, err = conn.ExecuteFetch("SELECT * from vt_insert_test limit 1", 1, false) + require.NotNilf(t, err, "error expected, got nil") + assert.Contains(t, err.Error(), "table acl error") + assert.Contains(t, err.Error(), "cannot run PASS_SELECT on table") +} + +func connectDB(t *testing.T, vtParams mysql.ConnParams, params ...string) *sql.DB { + connectionStr := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?%s", vtParams.Uname, vtParams.Pass, vtParams.Host, vtParams.Port, keyspaceName, strings.Join(params, "&")) + db, err := sql.Open("mysql", connectionStr) + require.Nil(t, err) + return db +} + +// createConfig create file in to Tmp dir in vtdataroot and write the given data. +func createConfig(name, data string) error { + // creating new file + f, err := os.Create(clusterInstance.TmpDirectory + name) + if err != nil { + return err + } + + if data == "" { + return nil + } + + // write the given data + _, err = fmt.Fprint(f, data) + return err +} diff --git a/go/test/endtoend/preparestmt/main_test.go b/go/test/endtoend/preparestmt/main_test.go new file mode 100644 index 00000000000..1fa24bf62a3 --- /dev/null +++ b/go/test/endtoend/preparestmt/main_test.go @@ -0,0 +1,278 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package preparestmt + +import ( + "database/sql" + "flag" + "fmt" + "os" + "strings" + "testing" + "time" + + "vitess.io/vitess/go/test/endtoend/cluster" + + "github.com/go-sql-driver/mysql" + "github.com/stretchr/testify/require" +) + +// tableData is a temporary structure to hold selected data. +type tableData struct { + Msg string + Data string + TextCol string + DateTime time.Time + DateTimeMicros time.Time +} + +// DBInfo information about the database. +type DBInfo struct { + Username string + Password string + Host string + Port uint + KeyspaceName string + Params []string +} + +func init() { + dbInfo.KeyspaceName = keyspaceName + dbInfo.Username = "testuser1" + dbInfo.Password = "testpassword1" + dbInfo.Params = []string{ + "charset=utf8", + "parseTime=True", + "loc=Local", + } +} + +var ( + clusterInstance *cluster.LocalProcessCluster + dbInfo DBInfo + hostname = "localhost" + keyspaceName = "test_keyspace" + testingID = 1 + tableName = "vt_prepare_stmt_test" + cell = "zone1" + mysqlAuthServerStatic = "mysql_auth_server_static.json" + jsonExample = `{ + "quiz": { + "sport": { + "q1": { + "question": "Which one is correct team name in NBA?", + "options": [ + "New York Bulls", + "Los Angeles Kings", + "Golden State Warriors", + "Huston Rocket" + ], + "answer": "Huston Rocket" + } + }, + "maths": { + "q1": { + "question": "5 + 7 = ?", + "options": [ + "10", + "11", + "12", + "13" + ], + "answer": "12" + }, + "q2": { + "question": "12 - 8 = ?", + "options": [ + "1", + "2", + "3", + "4" + ], + "answer": "4" + } + } + } + }` + sqlSchema = `create table ` + tableName + ` ( + id bigint auto_increment, + msg varchar(64), + keyspace_id bigint(20) unsigned NOT NULL, + tinyint_unsigned TINYINT, + bool_signed BOOL, + smallint_unsigned SMALLINT, + mediumint_unsigned MEDIUMINT, + int_unsigned INT, + float_unsigned FLOAT(10,2), + double_unsigned DOUBLE(16,2), + decimal_unsigned DECIMAL, + t_date DATE, + t_datetime DATETIME, + t_datetime_micros DATETIME(6), + t_time TIME, + t_timestamp TIMESTAMP, + c8 bit(8) DEFAULT NULL, + c16 bit(16) DEFAULT NULL, + c24 bit(24) DEFAULT NULL, + c32 bit(32) DEFAULT NULL, + c40 bit(40) DEFAULT NULL, + c48 bit(48) DEFAULT NULL, + c56 bit(56) DEFAULT NULL, + c63 bit(63) DEFAULT NULL, + c64 bit(64) DEFAULT NULL, + json_col JSON, + text_col TEXT, + data longblob, + primary key (id) + ) Engine=InnoDB` +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitcode, err := func() (int, error) { + clusterInstance = cluster.NewCluster(cell, hostname) + defer clusterInstance.Teardown() + + // Start topo server + if err := clusterInstance.StartTopo(); err != nil { + return 1, err + } + + // create auth server config + SQLConfig := `{ + "testuser1": { + "Password": "testpassword1", + "UserData": "vtgate client 1" + } + }` + if err := createConfig(mysqlAuthServerStatic, SQLConfig); err != nil { + return 1, err + } + + // add extra arguments + clusterInstance.VtGateExtraArgs = []string{ + "-mysql_auth_server_impl", "static", + "-mysql_server_query_timeout", "1s", + "-mysql_auth_server_static_file", clusterInstance.TmpDirectory + "/" + mysqlAuthServerStatic, + "-mysql_server_version", "8.0.16-7", + } + + // Start keyspace + keyspace := &cluster.Keyspace{ + Name: keyspaceName, + SchemaSQL: sqlSchema, + } + if err := clusterInstance.StartUnshardedKeyspace(*keyspace, 1, false); err != nil { + return 1, err + } + + // Start vtgate + if err := clusterInstance.StartVtgate(); err != nil { + return 1, err + } + + dbInfo.Host = clusterInstance.Hostname + dbInfo.Port = uint(clusterInstance.VtgateMySQLPort) + + return m.Run(), nil + }() + if err != nil { + fmt.Printf("%v\n", err) + os.Exit(1) + } else { + os.Exit(exitcode) + } + +} + +// ConnectionString generates the connection string using dbinfo. +func (db DBInfo) ConnectionString(params ...string) string { + return fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?%s", db.Username, db.Password, db.Host, + db.Port, db.KeyspaceName, strings.Join(append(db.Params, params...), "&")) +} + +// createConfig creates a config file in TmpDir in vtdataroot and writes the given data. +func createConfig(name, data string) error { + // creating new file + f, err := os.Create(clusterInstance.TmpDirectory + "/" + name) + if err != nil { + return err + } + + if data == "" { + return nil + } + + // write the given data + _, err = fmt.Fprint(f, data) + return err +} + +// Connect will connect the vtgate through mysql protocol. +func Connect(t *testing.T, params ...string) *sql.DB { + dbo, err := sql.Open("mysql", dbInfo.ConnectionString(params...)) + require.Nil(t, err) + return dbo +} + +// execWithError executes the prepared query, and validates the error_code. +func execWithError(t *testing.T, dbo *sql.DB, errorCodes []uint16, stmt string, params ...interface{}) { + _, err := dbo.Exec(stmt, params...) + require.NotNilf(t, err, "error expected, got nil") + mysqlErr, ok := err.(*mysql.MySQLError) + require.Truef(t, ok, "invalid error type") + require.Contains(t, errorCodes, mysqlErr.Number) +} + +// exec executes the query using the params. +func exec(t *testing.T, dbo *sql.DB, stmt string, params ...interface{}) { + require.Nil(t, execErr(dbo, stmt, params...)) +} + +// execErr executes the query and returns an error if one occurs. +func execErr(dbo *sql.DB, stmt string, params ...interface{}) *mysql.MySQLError { + if _, err := dbo.Exec(stmt, params...); err != nil { + // TODO : need to handle + mysqlErr, _ := err.(*mysql.MySQLError) + return mysqlErr + } + return nil +} + +// selectWhere select the row corresponding to the where condition. +func selectWhere(t *testing.T, dbo *sql.DB, where string, params ...interface{}) []tableData { + var out []tableData + // prepare query + qry := "SELECT msg, data, text_col, t_datetime, t_datetime_micros FROM " + tableName + if where != "" { + qry += " WHERE (" + where + ")" + } + + // execute query + r, err := dbo.Query(qry, params...) + require.Nil(t, err) + + // prepare result + for r.Next() { + var t tableData + r.Scan(&t.Msg, &t.Data, &t.TextCol, &t.DateTime, &t.DateTimeMicros) + out = append(out, t) + } + return out +} diff --git a/go/test/endtoend/preparestmt/stmt_methods_test.go b/go/test/endtoend/preparestmt/stmt_methods_test.go new file mode 100644 index 00000000000..d631b904068 --- /dev/null +++ b/go/test/endtoend/preparestmt/stmt_methods_test.go @@ -0,0 +1,184 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package preparestmt + +import ( + "database/sql" + "fmt" + "testing" + "time" + + "github.com/icrowley/fake" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/test/endtoend/cluster" +) + +// TestSelect simple select the data without any condition. +func TestSelect(t *testing.T) { + defer cluster.PanicHandler(t) + dbo := Connect(t) + defer dbo.Close() + selectWhere(t, dbo, "") +} + +// TestInsertUpdateDelete validates all insert, update and +// delete method on prepared statements. +func TestInsertUpdateDelete(t *testing.T) { + defer cluster.PanicHandler(t) + dbo := Connect(t) + defer dbo.Close() + // prepare insert statement + insertStmt := `insert into ` + tableName + ` values( ?, ?, ?, ?, ?, ?, ?, ?, + ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);` + + textValue := fake.FullName() + largeComment := fake.Paragraph() + + location, _ := time.LoadLocation("Local") + // inserting multiple rows into test table + for i := 1; i <= 100; i++ { + // preparing value for the insert testing + insertValue := []interface{}{ + i, fmt.Sprint(i) + "21", i * 100, + 127, 1, 32767, 8388607, 2147483647, 2.55, 64.9, 55.5, + time.Date(2009, 5, 5, 0, 0, 0, 50000, time.UTC), + time.Date(2009, 5, 5, 0, 0, 0, 50000, location), + time.Date(2009, 5, 5, 0, 0, 0, 50000, location), + time.Now(), + time.Date(2009, 5, 5, 0, 0, 0, 50000, time.UTC), + 1, 1, 1, 1, 1, 1, 1, 1, 1, jsonExample, textValue, largeComment, + } + exec(t, dbo, insertStmt, insertValue...) + + } + // validate inserted data count + testcount(t, dbo, 100) + + // select data with id 1 and validate the data accordingly + // validate row count + data := selectWhere(t, dbo, "id = ?", testingID) + assert.Equal(t, 1, len(data)) + + // validate value of msg column in data + assert.Equal(t, fmt.Sprintf("%d21", testingID), data[0].Msg) + + // Validate a datetime field (without micros) + // The 50 microsecs we inserted should have been truncated + assert.Equal(t, time.Date(2009, 5, 5, 0, 0, 0, 0, location), data[0].DateTime) + + // Validate a datetime field (with micros) + assert.Equal(t, time.Date(2009, 5, 5, 0, 0, 0, 50000, location), data[0].DateTimeMicros) + + // testing record update + updateRecord(t, dbo) + + // testing record deletion + deleteRecord(t, dbo) + + // testing recontion and deleted data validation + reconnectAndTest(t) +} + +// testcount validates inserted rows count with expected count. +func testcount(t *testing.T, dbo *sql.DB, except int) { + defer cluster.PanicHandler(t) + r, err := dbo.Query("SELECT count(1) FROM " + tableName) + require.Nil(t, err) + + r.Next() + var i int + err = r.Scan(&i) + require.Nil(t, err) + assert.Equal(t, except, i) +} + +// TestAutoIncColumns test insertion of row without passing +// the value of auto increment columns (here it is id). +func TestAutoIncColumns(t *testing.T) { + defer cluster.PanicHandler(t) + dbo := Connect(t) + defer dbo.Close() + // insert a row without id + insertStmt := "INSERT INTO " + tableName + ` ( + msg,keyspace_id,tinyint_unsigned,bool_signed,smallint_unsigned, + mediumint_unsigned,int_unsigned,float_unsigned,double_unsigned, + decimal_unsigned,t_date,t_datetime,t_datetime_micros,t_time,t_timestamp,c8,c16,c24, + c32,c40,c48,c56,c63,c64,json_col,text_col,data) VALUES (?, ?, ?, ?, ?, ?, + ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);` + insertValue := []interface{}{ + "21", 0, + 127, 1, 32767, 8388607, 2147483647, 2.55, 64.9, 55.5, + time.Date(2009, 5, 5, 0, 0, 0, 50000, time.UTC), + time.Date(2009, 5, 5, 0, 0, 0, 50000, time.UTC), + time.Date(2009, 5, 5, 0, 0, 0, 50000, time.UTC), + time.Now(), + time.Date(2009, 5, 5, 0, 0, 0, 50000, time.UTC), + 1, 1, 1, 1, 1, 1, 1, 1, 1, jsonExample, fake.DomainName(), fake.Paragraph(), + } + + exec(t, dbo, insertStmt, insertValue...) +} + +// deleteRecord test deletion operation corresponds to the testingID. +func deleteRecord(t *testing.T, dbo *sql.DB) { + // delete the record with id 1 + exec(t, dbo, "DELETE FROM "+tableName+" WHERE id = ?;", testingID) + + data := selectWhere(t, dbo, "id = ?", testingID) + assert.Equal(t, 0, len(data)) + +} + +// updateRecord test update operation corresponds to the testingID. +func updateRecord(t *testing.T, dbo *sql.DB) { + // update the record with id 1 + updateData := "new data value" + updateTextCol := "new text col value" + updateQuery := "update " + tableName + " set data = ? , text_col = ? where id = ?;" + + exec(t, dbo, updateQuery, updateData, updateTextCol, testingID) + + // validate the updated value + // validate row count + data := selectWhere(t, dbo, "id = ?", testingID) + assert.Equal(t, 1, len(data)) + + // validate value of msg column in data + assert.Equal(t, updateData, data[0].Data) + assert.Equal(t, updateTextCol, data[0].TextCol) + +} + +// reconnectAndTest creates new connection with database and validate. +func reconnectAndTest(t *testing.T) { + // reconnect and try to select the record with id 1 + dbo := Connect(t) + defer dbo.Close() + data := selectWhere(t, dbo, "id = ?", testingID) + assert.Equal(t, 0, len(data)) + +} + +// TestWrongTableName query database using invalid +// tablename and validate error. +func TestWrongTableName(t *testing.T) { + defer cluster.PanicHandler(t) + dbo := Connect(t) + defer dbo.Close() + execWithError(t, dbo, []uint16{1105}, "select * from teseting_table;") +} diff --git a/go/test/endtoend/recovery/recovery_util.go b/go/test/endtoend/recovery/recovery_util.go new file mode 100644 index 00000000000..cd6c82e8a3b --- /dev/null +++ b/go/test/endtoend/recovery/recovery_util.go @@ -0,0 +1,82 @@ +/* +Copyright 2020 The Vitess Authors. + +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. +*/ + +package recovery + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/test/endtoend/cluster" + "vitess.io/vitess/go/vt/vtgate/vtgateconn" +) + +var ( + dbPassword = "VtDbaPass" + + // UseXb flag to use extra backup for recovery teseting. + UseXb = false + XbArgs = []string{ + "-backup_engine_implementation", "xtrabackup", + "-xtrabackup_stream_mode=xbstream", + "-xtrabackup_user=vt_dba", + "-xtrabackup_backup_flags", fmt.Sprintf("--password=%s", dbPassword), + } +) + +func VerifyQueriesUsingVtgate(t *testing.T, session *vtgateconn.VTGateSession, query string, value string) { + qr, err := session.Execute(context.Background(), query, nil) + require.Nil(t, err) + assert.Equal(t, value, fmt.Sprintf("%v", qr.Rows[0][0])) +} + +func RestoreTablet(t *testing.T, localCluster *cluster.LocalProcessCluster, tablet *cluster.Vttablet, restoreKSName string, shardName string, keyspaceName string, commonTabletArg []string) { + tablet.ValidateTabletRestart(t) + tm := time.Now().UTC() + tm.Format(time.RFC3339) + _, err := localCluster.VtctlProcess.ExecuteCommandWithOutput("CreateKeyspace", + "-keyspace_type=SNAPSHOT", "-base_keyspace="+keyspaceName, + "-snapshot_time", tm.Format(time.RFC3339), restoreKSName) + require.Nil(t, err) + + replicaTabletArgs := commonTabletArg + if UseXb { + replicaTabletArgs = append(replicaTabletArgs, XbArgs...) + } + replicaTabletArgs = append(replicaTabletArgs, "-disable_active_reparents", + "-enable_replication_reporter=false", + "-init_tablet_type", "replica", + "-init_keyspace", restoreKSName, + "-init_shard", shardName) + tablet.VttabletProcess.SupportsBackup = true + tablet.VttabletProcess.ExtraArgs = replicaTabletArgs + + tablet.VttabletProcess.ServingStatus = "" + err = tablet.VttabletProcess.Setup() + require.Nil(t, err) + + err = tablet.VttabletProcess.WaitForTabletTypesForTimeout([]string{"SERVING"}, 20*time.Second) + require.Nil(t, err) +} + +func InsertData(t *testing.T, tablet *cluster.Vttablet, index int, keyspaceName string) { + _, err := tablet.VttabletProcess.QueryTablet(fmt.Sprintf("insert into vt_insert_test (id, msg) values (%d, 'test %d')", index, index), keyspaceName, true) + require.Nil(t, err) +} diff --git a/go/test/endtoend/recovery/shardedrecovery/sharded_recovery_test.go b/go/test/endtoend/recovery/shardedrecovery/sharded_recovery_test.go new file mode 100644 index 00000000000..9d9fc00756c --- /dev/null +++ b/go/test/endtoend/recovery/shardedrecovery/sharded_recovery_test.go @@ -0,0 +1,581 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package shardedrecovery + +import ( + "context" + "fmt" + "os/exec" + "strconv" + "strings" + "testing" + + "vitess.io/vitess/go/test/endtoend/recovery" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/test/endtoend/cluster" + _ "vitess.io/vitess/go/vt/vtgate/grpcvtgateconn" + "vitess.io/vitess/go/vt/vtgate/vtgateconn" +) + +var ( + master *cluster.Vttablet + replica1 *cluster.Vttablet + rdOnly *cluster.Vttablet + replica2 *cluster.Vttablet + replica3 *cluster.Vttablet + + shard0Master *cluster.Vttablet + shard0Replica *cluster.Vttablet + shard0RdOnly *cluster.Vttablet + + shard1Master *cluster.Vttablet + shard1Replica *cluster.Vttablet + shard1RdOnly *cluster.Vttablet + + localCluster *cluster.LocalProcessCluster + cell = cluster.DefaultCell + hostname = "localhost" + keyspaceName = "test_keyspace" + shardName = "0" + shard0Name = "-80" + shard1Name = "80-" + commonTabletArg = []string{ + "-vreplication_healthcheck_topology_refresh", "1s", + "-vreplication_healthcheck_retry_delay", "1s", + "-vreplication_retry_delay", "1s", + "-degraded_threshold", "5s", + "-lock_tables_timeout", "5s", + "-watch_replication_stream", + "-serving_state_grace_period", "1s"} + recoveryKS = "recovery_keyspace" + vtInsertTest = `create table vt_insert_test ( + id bigint auto_increment, + msg varchar(64), + primary key (id) + ) Engine=InnoDB` + vSchema = `{ + "sharded": true, + "vindexes": { + "hash": { + "type": "hash" + } + }, + "tables": { + "vt_insert_test": { + "column_vindexes": [ + { + "column": "id", + "name": "hash" + } + ] + } + } +}` +) + +// Test recovery from backup flow. + +// test_recovery will: +// - create a shard with master and replica1 only +// - run InitShardMaster +// - insert some data +// - take a backup +// - insert more data on the master +// - perform a resharding +// - create a recovery keyspace +// - bring up tablet_replica2 in the new keyspace +// - check that new tablet does not have data created after backup +// - check that vtgate queries work correctly + +func TestUnShardedRecoveryAfterSharding(t *testing.T) { + defer cluster.PanicHandler(t) + _, err := initializeCluster(t) + defer localCluster.Teardown() + require.Nil(t, err) + err = localCluster.VtctlclientProcess.ApplySchema(keyspaceName, vtInsertTest) + require.Nil(t, err) + recovery.InsertData(t, master, 1, keyspaceName) + cluster.VerifyRowsInTablet(t, replica1, keyspaceName, 1) + + // insert more data on the master + recovery.InsertData(t, master, 2, keyspaceName) + + // backup the replica + err = localCluster.VtctlclientProcess.ExecuteCommand("Backup", replica1.Alias) + require.Nil(t, err) + + // check that the backup shows up in the listing + output, err := localCluster.ListBackups("test_keyspace/0") + require.Nil(t, err) + assert.Equal(t, 1, len(output)) + assert.True(t, strings.HasSuffix(output[0], replica1.Alias)) + + // insert more data on the master + recovery.InsertData(t, master, 3, keyspaceName) + + err = localCluster.VtctlclientProcess.ApplyVSchema(keyspaceName, vSchema) + require.Nil(t, err) + + // create the split shards + for _, tablet := range []*cluster.Vttablet{shard0Master, shard0Replica, shard0RdOnly} { + err = localCluster.VtctlclientProcess.InitTablet(tablet, cell, keyspaceName, hostname, shard0Name) + require.Nil(t, err) + } + + for _, tablet := range []*cluster.Vttablet{shard1Master, shard1Replica, shard1RdOnly} { + err = localCluster.VtctlclientProcess.InitTablet(tablet, cell, keyspaceName, hostname, shard1Name) + require.Nil(t, err) + } + + for _, tablet := range []*cluster.Vttablet{shard0Master, shard0Replica, shard0RdOnly, shard1Master, shard1Replica, shard1RdOnly} { + tablet.VttabletProcess.ExtraArgs = []string{"-binlog_use_v3_resharding_mode=true"} + err = tablet.VttabletProcess.Setup() + require.Nil(t, err) + } + + err = localCluster.VtctlProcess.ExecuteCommand("InitShardMaster", "-force", "test_keyspace/-80", shard0Master.Alias) + require.Nil(t, err) + + err = localCluster.VtctlProcess.ExecuteCommand("InitShardMaster", "-force", "test_keyspace/80-", shard1Master.Alias) + require.Nil(t, err) + + shardedTablets := []*cluster.Vttablet{shard0Master, shard0Replica, shard0RdOnly, shard1Master, shard1Replica, shard1RdOnly} + + for _, tablet := range shardedTablets { + _ = tablet.VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + } + + for _, tablet := range shardedTablets { + assert.Equal(t, tablet.VttabletProcess.GetTabletStatus(), "SERVING") + } + + // we need to create the schema, and the worker will do data copying + for _, keyspaceShard := range []string{"test_keyspace/-80", "test_keyspace/80-"} { + err = localCluster.VtctlclientProcess.ExecuteCommand("CopySchemaShard", "test_keyspace/0", keyspaceShard) + require.Nil(t, err) + } + + err = localCluster.VtctlclientProcess.ExecuteCommand("SplitClone", "test_keyspace", "0", "-80,80-") + require.Nil(t, err) + + err = localCluster.VtctlclientProcess.ExecuteCommand("MigrateServedTypes", "test_keyspace/0", "rdonly") + require.Nil(t, err) + + err = localCluster.VtctlclientProcess.ExecuteCommand("MigrateServedTypes", "test_keyspace/0", "replica") + require.Nil(t, err) + + // then serve master from the split shards + err = localCluster.VtctlclientProcess.ExecuteCommand("MigrateServedTypes", "test_keyspace/0", "master") + require.Nil(t, err) + + // remove the original tablets in the original shard + removeTablets(t, []*cluster.Vttablet{master, replica1, rdOnly}) + + for _, tablet := range []*cluster.Vttablet{replica1, rdOnly} { + err = localCluster.VtctlclientProcess.ExecuteCommand("DeleteTablet", tablet.Alias) + require.Nil(t, err) + } + err = localCluster.VtctlclientProcess.ExecuteCommand("DeleteTablet", "-allow_master", master.Alias) + require.Nil(t, err) + + // rebuild the serving graph, all mentions of the old shards should be gone + err = localCluster.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", "test_keyspace") + require.Nil(t, err) + + // delete the original shard + err = localCluster.VtctlclientProcess.ExecuteCommand("DeleteShard", "test_keyspace/0") + require.Nil(t, err) + + // now bring up the recovery keyspace and a tablet, letting it restore from backup. + recovery.RestoreTablet(t, localCluster, replica2, recoveryKS, "0", keyspaceName, commonTabletArg) + + // check the new replica does not have the data + cluster.VerifyRowsInTablet(t, replica2, keyspaceName, 2) + + vtgateInstance := localCluster.GetVtgateInstance() + vtgateInstance.TabletTypesToWait = "REPLICA" + err = vtgateInstance.Setup() + localCluster.VtgateGrpcPort = vtgateInstance.GrpcPort + require.Nil(t, err) + err = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.master", keyspaceName, shard0Name), 1) + require.Nil(t, err) + err = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.replica", keyspaceName, shard1Name), 1) + require.Nil(t, err) + err = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.master", keyspaceName, shard0Name), 1) + require.Nil(t, err) + err = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.replica", keyspaceName, shard1Name), 1) + require.Nil(t, err) + err = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.replica", recoveryKS, shardName), 1) + require.Nil(t, err) + + // Build vtgate grpc connection + // check that vtgate doesn't route queries to new tablet + grpcAddress := fmt.Sprintf("%s:%d", localCluster.Hostname, localCluster.VtgateGrpcPort) + vtgateConn, err := vtgateconn.Dial(context.Background(), grpcAddress) + require.Nil(t, err) + + session := vtgateConn.Session("@replica", nil) + recovery.VerifyQueriesUsingVtgate(t, session, "select count(*) from vt_insert_test", "INT64(3)") + + // check that new tablet is accessible by using ks.table + recovery.VerifyQueriesUsingVtgate(t, session, "select count(*) from recovery_keyspace.vt_insert_test", "INT64(2)") + + // check that new tablet is accessible with 'use ks' + cluster.ExecuteQueriesUsingVtgate(t, session, "use `recovery_keyspace@replica`") + recovery.VerifyQueriesUsingVtgate(t, session, "select count(*) from vt_insert_test", "INT64(2)") + + // check that new tablet is accessible with `use ks:shard` + cluster.ExecuteQueriesUsingVtgate(t, session, "use `recovery_keyspace:0@replica`") + recovery.VerifyQueriesUsingVtgate(t, session, "select count(*) from vt_insert_test", "INT64(2)") + + vtgateConn.Close() + err = vtgateInstance.TearDown() + require.Nil(t, err) +} + +// Test recovery from backup flow. + +// test_recovery will: +// - create a shard with master and replica1 only +// - run InitShardMaster +// - insert some data +// - perform a resharding +// - take a backup of both new shards +// - insert more data on the masters of both shards +// - create a recovery keyspace +// - bring up tablet_replica2 and tablet_replica3 in the new keyspace +// - check that new tablets do not have data created after backup +// - check that vtgate queries work correctly + +func TestShardedRecovery(t *testing.T) { + + defer cluster.PanicHandler(t) + _, err := initializeCluster(t) + defer localCluster.Teardown() + require.Nil(t, err) + err = localCluster.VtctlclientProcess.ApplySchema(keyspaceName, vtInsertTest) + require.Nil(t, err) + recovery.InsertData(t, master, 1, keyspaceName) + + cluster.VerifyRowsInTablet(t, replica1, keyspaceName, 1) + + // insert more data on the master + recovery.InsertData(t, master, 4, keyspaceName) + + err = localCluster.VtctlclientProcess.ApplyVSchema(keyspaceName, vSchema) + require.Nil(t, err) + + // create the split shards + for _, tablet := range []*cluster.Vttablet{shard0Master, shard0Replica, shard0RdOnly} { + err = localCluster.VtctlclientProcess.InitTablet(tablet, cell, keyspaceName, hostname, shard0Name) + require.Nil(t, err) + } + + for _, tablet := range []*cluster.Vttablet{shard1Master, shard1Replica, shard1RdOnly} { + err = localCluster.VtctlclientProcess.InitTablet(tablet, cell, keyspaceName, hostname, shard1Name) + require.Nil(t, err) + } + + for _, tablet := range []*cluster.Vttablet{shard0Master, shard0Replica, shard0RdOnly, shard1Master, shard1Replica, shard1RdOnly} { + tablet.VttabletProcess.ExtraArgs = []string{"-binlog_use_v3_resharding_mode=true"} + err = tablet.VttabletProcess.Setup() + require.Nil(t, err) + } + + err = localCluster.VtctlProcess.ExecuteCommand("InitShardMaster", "-force", "test_keyspace/-80", shard0Master.Alias) + require.Nil(t, err) + + err = localCluster.VtctlProcess.ExecuteCommand("InitShardMaster", "-force", "test_keyspace/80-", shard1Master.Alias) + require.Nil(t, err) + + shardedTablets := []*cluster.Vttablet{shard0Master, shard0Replica, shard0RdOnly, shard1Master, shard1Replica, shard1RdOnly} + + for _, tablet := range shardedTablets { + _ = tablet.VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + } + + for _, tablet := range shardedTablets { + assert.Equal(t, tablet.VttabletProcess.GetTabletStatus(), "SERVING") + } + + // we need to create the schema, and the worker will do data copying + for _, keyspaceShard := range []string{"test_keyspace/-80", "test_keyspace/80-"} { + err = localCluster.VtctlclientProcess.ExecuteCommand("CopySchemaShard", "test_keyspace/0", keyspaceShard) + require.Nil(t, err) + } + + err = localCluster.VtctlclientProcess.ExecuteCommand("SplitClone", "test_keyspace", "0", "-80,80-") + require.Nil(t, err) + + err = localCluster.VtctlclientProcess.ExecuteCommand("MigrateServedTypes", "test_keyspace/0", "rdonly") + require.Nil(t, err) + + err = localCluster.VtctlclientProcess.ExecuteCommand("MigrateServedTypes", "test_keyspace/0", "replica") + require.Nil(t, err) + + // then serve master from the split shards + err = localCluster.VtctlclientProcess.ExecuteCommand("MigrateServedTypes", "test_keyspace/0", "master") + require.Nil(t, err) + + // remove the original tablets in the original shard + removeTablets(t, []*cluster.Vttablet{master, replica1, rdOnly}) + + for _, tablet := range []*cluster.Vttablet{replica1, rdOnly} { + err = localCluster.VtctlclientProcess.ExecuteCommand("DeleteTablet", tablet.Alias) + require.Nil(t, err) + } + err = localCluster.VtctlclientProcess.ExecuteCommand("DeleteTablet", "-allow_master", master.Alias) + require.Nil(t, err) + + // rebuild the serving graph, all mentions of the old shards should be gone + err = localCluster.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", "test_keyspace") + require.Nil(t, err) + + // delete the original shard + err = localCluster.VtctlclientProcess.ExecuteCommand("DeleteShard", "test_keyspace/0") + require.Nil(t, err) + + qr, err := shard0Master.VttabletProcess.QueryTablet("select count(*) from vt_insert_test", keyspaceName, true) + require.Nil(t, err) + shard0CountStr := fmt.Sprintf("%s", qr.Rows[0][0].ToBytes()) + shard0Count, err := strconv.Atoi(shard0CountStr) + require.Nil(t, err) + var shard0TestId string + if shard0Count > 0 { + qr, err := shard0Master.VttabletProcess.QueryTablet("select id from vt_insert_test", keyspaceName, true) + require.Nil(t, err) + shard0TestId = fmt.Sprintf("%s", qr.Rows[0][0].ToBytes()) + require.Nil(t, err) + } + + qr, err = shard1Master.VttabletProcess.QueryTablet("select count(*) from vt_insert_test", keyspaceName, true) + require.Nil(t, err) + shard1CountStr := fmt.Sprintf("%s", qr.Rows[0][0].ToBytes()) + shard1Count, err := strconv.Atoi(shard1CountStr) + require.Nil(t, err) + var shard1TestId string + if shard1Count > 0 { + qr, err := shard1Master.VttabletProcess.QueryTablet("select id from vt_insert_test", keyspaceName, true) + require.Nil(t, err) + shard1TestId = fmt.Sprintf("%s", qr.Rows[0][0].ToBytes()) + require.Nil(t, err) + } + + // backup the new shards + err = localCluster.VtctlclientProcess.ExecuteCommand("Backup", shard0Replica.Alias) + require.Nil(t, err) + err = localCluster.VtctlclientProcess.ExecuteCommand("Backup", shard1Replica.Alias) + require.Nil(t, err) + + // check that the backup shows up in the listing + output, err := localCluster.ListBackups("test_keyspace/-80") + require.Nil(t, err) + assert.Equal(t, 1, len(output)) + assert.True(t, strings.HasSuffix(output[0], shard0Replica.Alias)) + + output, err = localCluster.ListBackups("test_keyspace/80-") + require.Nil(t, err) + assert.Equal(t, 1, len(output)) + assert.True(t, strings.HasSuffix(output[0], shard1Replica.Alias)) + + vtgateInstance := localCluster.GetVtgateInstance() + vtgateInstance.TabletTypesToWait = "MASTER" + err = vtgateInstance.Setup() + localCluster.VtgateGrpcPort = vtgateInstance.GrpcPort + require.Nil(t, err) + err = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.master", keyspaceName, shard0Name), 1) + require.Nil(t, err) + err = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.master", keyspaceName, shard1Name), 1) + require.Nil(t, err) + + // Build vtgate grpc connection + // check that vtgate doesn't route queries to new tablet + grpcAddress := fmt.Sprintf("%s:%d", localCluster.Hostname, localCluster.VtgateGrpcPort) + vtgateConn, err := vtgateconn.Dial(context.Background(), grpcAddress) + require.Nil(t, err) + session := vtgateConn.Session("@master", nil) + cluster.ExecuteQueriesUsingVtgate(t, session, "insert into vt_insert_test (id, msg) values (2,'test 2')") + cluster.ExecuteQueriesUsingVtgate(t, session, "insert into vt_insert_test (id, msg) values (3,'test 3')") + + vtgateConn.Close() + err = vtgateInstance.TearDown() + require.Nil(t, err) + + // now bring up the recovery keyspace and 2 tablets, letting it restore from backup. + recovery.RestoreTablet(t, localCluster, replica2, recoveryKS, "-80", keyspaceName, commonTabletArg) + recovery.RestoreTablet(t, localCluster, replica3, recoveryKS, "80-", keyspaceName, commonTabletArg) + + // check the new replicas have the correct number of rows + cluster.VerifyRowsInTablet(t, replica2, keyspaceName, shard0Count) + cluster.VerifyRowsInTablet(t, replica3, keyspaceName, shard1Count) + + // start vtgate + vtgateInstance = localCluster.GetVtgateInstance() + vtgateInstance.TabletTypesToWait = "REPLICA" + err = vtgateInstance.Setup() + localCluster.VtgateGrpcPort = vtgateInstance.GrpcPort + require.Nil(t, err) + err = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.master", keyspaceName, shard0Name), 1) + require.Nil(t, err) + err = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.replica", keyspaceName, shard1Name), 1) + require.Nil(t, err) + err = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.master", keyspaceName, shard0Name), 1) + require.Nil(t, err) + err = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.replica", keyspaceName, shard1Name), 1) + require.Nil(t, err) + err = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.replica", recoveryKS, shard0Name), 1) + require.Nil(t, err) + err = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.replica", recoveryKS, shard1Name), 1) + require.Nil(t, err) + + // check that vtgate doesn't route queries to new tablet + grpcAddress = fmt.Sprintf("%s:%d", localCluster.Hostname, localCluster.VtgateGrpcPort) + vtgateConn, err = vtgateconn.Dial(context.Background(), grpcAddress) + require.Nil(t, err) + session = vtgateConn.Session("@replica", nil) + recovery.VerifyQueriesUsingVtgate(t, session, "select count(*) from vt_insert_test", "INT64(4)") + + // check that new keyspace is accessible by using ks.table + recovery.VerifyQueriesUsingVtgate(t, session, "select count(*) from recovery_keyspace.vt_insert_test", "INT64(2)") + + // check that new keyspace is accessible with 'use ks' + cluster.ExecuteQueriesUsingVtgate(t, session, "use recovery_keyspace@replica") + recovery.VerifyQueriesUsingVtgate(t, session, "select count(*) from vt_insert_test", "INT64(2)") + + // check that new tablet is accessible with use `ks:shard` + cluster.ExecuteQueriesUsingVtgate(t, session, "use `recovery_keyspace:-80@replica`") + recovery.VerifyQueriesUsingVtgate(t, session, "select count(*) from vt_insert_test", "INT64("+shard0CountStr+")") + recovery.VerifyQueriesUsingVtgate(t, session, "select id from vt_insert_test", "INT64("+shard0TestId+")") + + cluster.ExecuteQueriesUsingVtgate(t, session, "use `recovery_keyspace:80-@replica`") + recovery.VerifyQueriesUsingVtgate(t, session, "select count(*) from vt_insert_test", "INT64("+shard1CountStr+")") + recovery.VerifyQueriesUsingVtgate(t, session, "select id from vt_insert_test", "INT64("+shard1TestId+")") + + vtgateConn.Close() + err = vtgateInstance.TearDown() + require.Nil(t, err) +} + +func removeTablets(t *testing.T, tablets []*cluster.Vttablet) { + var mysqlProcs []*exec.Cmd + for _, tablet := range tablets { + proc, _ := tablet.MysqlctlProcess.StopProcess() + mysqlProcs = append(mysqlProcs, proc) + tablet.VttabletProcess.TearDown() + } + for _, proc := range mysqlProcs { + err := proc.Wait() + require.Nil(t, err) + } +} + +func initializeCluster(t *testing.T) (int, error) { + + localCluster = cluster.NewCluster(cell, hostname) + + // Start topo server + err := localCluster.StartTopo() + if err != nil { + return 1, err + } + // Start keyspace + keyspace := &cluster.Keyspace{ + Name: keyspaceName, + } + localCluster.Keyspaces = append(localCluster.Keyspaces, *keyspace) + + // TODO : handle shards properly + shard := &cluster.Shard{ + Name: shardName, + } + shard0 := &cluster.Shard{ + Name: shard0Name, + } + shard1 := &cluster.Shard{ + Name: shard1Name, + } + + // Defining all the tablets + master = localCluster.GetVttabletInstance("replica", 0, "") + replica1 = localCluster.GetVttabletInstance("replica", 0, "") + rdOnly = localCluster.GetVttabletInstance("rdonly", 0, "") + replica2 = localCluster.GetVttabletInstance("replica", 0, "") + replica3 = localCluster.GetVttabletInstance("replica", 0, "") + shard0Master = localCluster.GetVttabletInstance("replica", 0, "") + shard0Replica = localCluster.GetVttabletInstance("replica", 0, "") + shard0RdOnly = localCluster.GetVttabletInstance("rdonly", 0, "") + shard1Master = localCluster.GetVttabletInstance("replica", 0, "") + shard1Replica = localCluster.GetVttabletInstance("replica", 0, "") + shard1RdOnly = localCluster.GetVttabletInstance("rdonly", 0, "") + + shard.Vttablets = []*cluster.Vttablet{master, replica1, rdOnly, replica2, replica3} + shard0.Vttablets = []*cluster.Vttablet{shard0Master, shard0Replica, shard0RdOnly} + shard1.Vttablets = []*cluster.Vttablet{shard1Master, shard1Replica, shard1RdOnly} + + localCluster.VtTabletExtraArgs = append(localCluster.VtTabletExtraArgs, commonTabletArg...) + localCluster.VtTabletExtraArgs = append(localCluster.VtTabletExtraArgs, "-restore_from_backup", "-enable_semi_sync") + + err = localCluster.LaunchCluster(keyspace, []cluster.Shard{*shard, *shard0, *shard1}) + + // Start MySql + var mysqlCtlProcessList []*exec.Cmd + for _, shard := range localCluster.Keyspaces[0].Shards { + for _, tablet := range shard.Vttablets { + if proc, err := tablet.MysqlctlProcess.StartProcess(); err != nil { + t.Fatal(err) + } else { + mysqlCtlProcessList = append(mysqlCtlProcessList, proc) + } + } + } + + // Wait for mysql processes to start + for _, proc := range mysqlCtlProcessList { + if err := proc.Wait(); err != nil { + t.Fatal(err) + } + } + + if err = localCluster.VtctlclientProcess.InitTablet(master, cell, keyspaceName, hostname, shard.Name); err != nil { + return 1, err + } + if err = localCluster.VtctlclientProcess.InitTablet(replica1, cell, keyspaceName, hostname, shard.Name); err != nil { + return 1, err + } + if err = localCluster.VtctlclientProcess.InitTablet(rdOnly, cell, keyspaceName, hostname, shard.Name); err != nil { + return 1, err + } + + for _, tablet := range []cluster.Vttablet{*master, *replica1, *rdOnly} { + if err = tablet.VttabletProcess.CreateDB(keyspaceName); err != nil { + return 1, err + } + if err = tablet.VttabletProcess.Setup(); err != nil { + return 1, err + } + } + + if err = localCluster.VtctlclientProcess.InitShardMaster(keyspaceName, shard.Name, cell, master.TabletUID); err != nil { + return 1, err + } + + return 0, nil +} diff --git a/go/test/endtoend/recovery/unshardedrecovery/recovery.go b/go/test/endtoend/recovery/unshardedrecovery/recovery.go new file mode 100644 index 00000000000..567c24e4fec --- /dev/null +++ b/go/test/endtoend/recovery/unshardedrecovery/recovery.go @@ -0,0 +1,347 @@ +/* +Copyright 2020 The Vitess Authors. + +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. +*/ + +package unshardedrecovery + +import ( + "context" + "flag" + "fmt" + "io/ioutil" + "os" + "os/exec" + "path" + "testing" + + "vitess.io/vitess/go/test/endtoend/recovery" + "vitess.io/vitess/go/test/endtoend/sharding/initialsharding" + + "vitess.io/vitess/go/vt/log" + "vitess.io/vitess/go/vt/vtgate/vtgateconn" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/test/endtoend/cluster" +) + +var ( + master *cluster.Vttablet + replica1 *cluster.Vttablet + replica2 *cluster.Vttablet + replica3 *cluster.Vttablet + localCluster *cluster.LocalProcessCluster + newInitDBFile string + cell = cluster.DefaultCell + hostname = "localhost" + keyspaceName = "ks" + dbPassword = "VtDbaPass" + shardKsName = fmt.Sprintf("%s/%s", keyspaceName, shardName) + dbCredentialFile string + shardName = "0" + commonTabletArg = []string{ + "-vreplication_healthcheck_topology_refresh", "1s", + "-vreplication_healthcheck_retry_delay", "1s", + "-vreplication_retry_delay", "1s", + "-degraded_threshold", "5s", + "-lock_tables_timeout", "5s", + "-watch_replication_stream", + "-serving_state_grace_period", "1s"} + recoveryKS1 = "recovery_ks1" + recoveryKS2 = "recovery_ks2" + vtInsertTest = `create table vt_insert_test ( + id bigint auto_increment, + msg varchar(64), + primary key (id) + ) Engine=InnoDB` + vSchema = `{ + "tables": { + "vt_insert_test": {} + } +}` +) + +// TestMainImpl creates cluster for unsharded recovery testing. +func TestMainImpl(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitCode, err := func() (int, error) { + localCluster = cluster.NewCluster(cell, hostname) + defer localCluster.Teardown() + + // Start topo server + err := localCluster.StartTopo() + if err != nil { + return 1, err + } + + // Start keyspace + keyspace := &cluster.Keyspace{ + Name: keyspaceName, + } + localCluster.Keyspaces = append(localCluster.Keyspaces, *keyspace) + + dbCredentialFile = initialsharding.WriteDbCredentialToTmp(localCluster.TmpDirectory) + initDb, _ := ioutil.ReadFile(path.Join(os.Getenv("VTROOT"), "/config/init_db.sql")) + sql := string(initDb) + newInitDBFile = path.Join(localCluster.TmpDirectory, "init_db_with_passwords.sql") + sql = sql + initialsharding.GetPasswordUpdateSQL(localCluster) + ioutil.WriteFile(newInitDBFile, []byte(sql), 0666) + + extraArgs := []string{"-db-credentials-file", dbCredentialFile} + commonTabletArg = append(commonTabletArg, "-db-credentials-file", dbCredentialFile) + + shard := cluster.Shard{ + Name: shardName, + } + + var mysqlProcs []*exec.Cmd + for i := 0; i < 4; i++ { + tabletType := "replica" + if i == 0 { + tabletType = "master" + } + tablet := localCluster.GetVttabletInstance(tabletType, 0, cell) + tablet.VttabletProcess = localCluster.GetVtprocessInstanceFromVttablet(tablet, shard.Name, keyspaceName) + tablet.VttabletProcess.DbPassword = dbPassword + tablet.VttabletProcess.ExtraArgs = commonTabletArg + if recovery.UseXb { + tablet.VttabletProcess.ExtraArgs = append(tablet.VttabletProcess.ExtraArgs, recovery.XbArgs...) + } + tablet.VttabletProcess.SupportsBackup = true + tablet.VttabletProcess.EnableSemiSync = true + + tablet.MysqlctlProcess = *cluster.MysqlCtlProcessInstance(tablet.TabletUID, tablet.MySQLPort, localCluster.TmpDirectory) + tablet.MysqlctlProcess.InitDBFile = newInitDBFile + tablet.MysqlctlProcess.ExtraArgs = extraArgs + proc, err := tablet.MysqlctlProcess.StartProcess() + if err != nil { + return 1, err + } + mysqlProcs = append(mysqlProcs, proc) + + shard.Vttablets = append(shard.Vttablets, tablet) + } + for _, proc := range mysqlProcs { + if err := proc.Wait(); err != nil { + return 1, err + } + } + master = shard.Vttablets[0] + replica1 = shard.Vttablets[1] + replica2 = shard.Vttablets[2] + replica3 = shard.Vttablets[3] + + if err := localCluster.VtctlclientProcess.InitTablet(master, cell, keyspaceName, hostname, shard.Name); err != nil { + return 1, err + } + if err := localCluster.VtctlclientProcess.InitTablet(replica1, cell, keyspaceName, hostname, shard.Name); err != nil { + return 1, err + } + + for _, tablet := range []cluster.Vttablet{*master, *replica1} { + if err := tablet.VttabletProcess.CreateDB(keyspaceName); err != nil { + return 1, err + } + if err := tablet.VttabletProcess.Setup(); err != nil { + return 1, err + } + } + + if err := localCluster.VtctlclientProcess.InitShardMaster(keyspaceName, shard.Name, cell, master.TabletUID); err != nil { + return 1, err + } + return m.Run(), nil + }() + + if err != nil { + log.Error(err.Error()) + os.Exit(1) + } else { + os.Exit(exitCode) + } + +} + +// TestRecoveryImpl does following +// - create a shard with master and replica1 only +// - run InitShardMaster +// - insert some data +// - take a backup +// - insert more data on the master +// - take another backup +// - create a recovery keyspace after first backup +// - bring up tablet_replica2 in the new keyspace +// - check that new tablet does not have data created after backup1 +// - create second recovery keyspace after second backup +// - bring up tablet_replica3 in second keyspace +// - check that new tablet has data created after backup1 but not data created after backup2 +// - check that vtgate queries work correctly +func TestRecoveryImpl(t *testing.T) { + defer cluster.PanicHandler(t) + defer tabletsTeardown() + verifyInitialReplication(t) + + err := localCluster.VtctlclientProcess.ExecuteCommand("Backup", replica1.Alias) + assert.Nil(t, err) + + backups := listBackups(t) + require.Equal(t, len(backups), 1) + assert.Contains(t, backups[0], replica1.Alias) + + _, err = master.VttabletProcess.QueryTablet("insert into vt_insert_test (msg) values ('test2')", keyspaceName, true) + assert.Nil(t, err) + cluster.VerifyRowsInTablet(t, replica1, keyspaceName, 2) + + err = localCluster.VtctlclientProcess.ApplyVSchema(keyspaceName, vSchema) + assert.Nil(t, err) + + output, err := localCluster.VtctlclientProcess.ExecuteCommandWithOutput("GetVSchema", keyspaceName) + assert.Nil(t, err) + assert.Contains(t, output, "vt_insert_test") + + recovery.RestoreTablet(t, localCluster, replica2, recoveryKS1, "0", keyspaceName, commonTabletArg) + + output, err = localCluster.VtctlclientProcess.ExecuteCommandWithOutput("GetSrvVSchema", cell) + assert.Nil(t, err) + assert.Contains(t, output, keyspaceName) + assert.Contains(t, output, recoveryKS1) + + err = localCluster.VtctlclientProcess.ExecuteCommand("GetSrvKeyspace", cell, keyspaceName) + assert.Nil(t, err) + + output, err = localCluster.VtctlclientProcess.ExecuteCommandWithOutput("GetVSchema", recoveryKS1) + assert.Nil(t, err) + assert.Contains(t, output, "vt_insert_test") + + cluster.VerifyRowsInTablet(t, replica2, keyspaceName, 1) + + cluster.VerifyLocalMetadata(t, replica2, recoveryKS1, shardName, cell) + + // update the original row in master + _, err = master.VttabletProcess.QueryTablet("update vt_insert_test set msg = 'msgx1' where id = 1", keyspaceName, true) + assert.Nil(t, err) + + //verify that master has new value + qr, err := master.VttabletProcess.QueryTablet("select msg from vt_insert_test where id = 1", keyspaceName, true) + assert.Nil(t, err) + assert.Equal(t, "msgx1", fmt.Sprintf("%s", qr.Rows[0][0].ToBytes())) + + //verify that restored replica has old value + qr, err = replica2.VttabletProcess.QueryTablet("select msg from vt_insert_test where id = 1", keyspaceName, true) + assert.Nil(t, err) + assert.Equal(t, "test1", fmt.Sprintf("%s", qr.Rows[0][0].ToBytes())) + + err = localCluster.VtctlclientProcess.ExecuteCommand("Backup", replica1.Alias) + assert.Nil(t, err) + + _, err = master.VttabletProcess.QueryTablet("insert into vt_insert_test (msg) values ('test3')", keyspaceName, true) + assert.Nil(t, err) + cluster.VerifyRowsInTablet(t, replica1, keyspaceName, 3) + + recovery.RestoreTablet(t, localCluster, replica3, recoveryKS2, "0", keyspaceName, commonTabletArg) + + output, err = localCluster.VtctlclientProcess.ExecuteCommandWithOutput("GetVSchema", recoveryKS2) + assert.Nil(t, err) + assert.Contains(t, output, "vt_insert_test") + + cluster.VerifyRowsInTablet(t, replica3, keyspaceName, 2) + + // update the original row in master + _, err = master.VttabletProcess.QueryTablet("update vt_insert_test set msg = 'msgx2' where id = 1", keyspaceName, true) + assert.Nil(t, err) + + //verify that master has new value + qr, err = master.VttabletProcess.QueryTablet("select msg from vt_insert_test where id = 1", keyspaceName, true) + assert.Nil(t, err) + assert.Equal(t, "msgx2", fmt.Sprintf("%s", qr.Rows[0][0].ToBytes())) + + //verify that restored replica has old value + qr, err = replica3.VttabletProcess.QueryTablet("select msg from vt_insert_test where id = 1", keyspaceName, true) + assert.Nil(t, err) + assert.Equal(t, "msgx1", fmt.Sprintf("%s", qr.Rows[0][0].ToBytes())) + + vtgateInstance := localCluster.GetVtgateInstance() + vtgateInstance.TabletTypesToWait = "REPLICA" + err = vtgateInstance.Setup() + localCluster.VtgateGrpcPort = vtgateInstance.GrpcPort + assert.Nil(t, err) + defer vtgateInstance.TearDown() + err = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.master", keyspaceName, shardName), 1) + assert.Nil(t, err) + err = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.replica", keyspaceName, shardName), 1) + assert.Nil(t, err) + err = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.replica", recoveryKS1, shardName), 1) + assert.Nil(t, err) + err = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.replica", recoveryKS2, shardName), 1) + assert.Nil(t, err) + + // Build vtgate grpc connection + grpcAddress := fmt.Sprintf("%s:%d", localCluster.Hostname, localCluster.VtgateGrpcPort) + vtgateConn, err := vtgateconn.Dial(context.Background(), grpcAddress) + assert.Nil(t, err) + defer vtgateConn.Close() + session := vtgateConn.Session("@replica", nil) + + //check that vtgate doesn't route queries to new tablet + recovery.VerifyQueriesUsingVtgate(t, session, "select count(*) from vt_insert_test", "INT64(3)") + recovery.VerifyQueriesUsingVtgate(t, session, "select msg from vt_insert_test where id = 1", `VARCHAR("msgx2")`) + recovery.VerifyQueriesUsingVtgate(t, session, fmt.Sprintf("select count(*) from %s.vt_insert_test", recoveryKS1), "INT64(1)") + recovery.VerifyQueriesUsingVtgate(t, session, fmt.Sprintf("select msg from %s.vt_insert_test where id = 1", recoveryKS1), `VARCHAR("test1")`) + recovery.VerifyQueriesUsingVtgate(t, session, fmt.Sprintf("select count(*) from %s.vt_insert_test", recoveryKS2), "INT64(2)") + recovery.VerifyQueriesUsingVtgate(t, session, fmt.Sprintf("select msg from %s.vt_insert_test where id = 1", recoveryKS2), `VARCHAR("msgx1")`) + + // check that new keyspace is accessible with 'use ks' + cluster.ExecuteQueriesUsingVtgate(t, session, "use "+recoveryKS1+"@replica") + recovery.VerifyQueriesUsingVtgate(t, session, "select count(*) from vt_insert_test", "INT64(1)") + + cluster.ExecuteQueriesUsingVtgate(t, session, "use "+recoveryKS2+"@replica") + recovery.VerifyQueriesUsingVtgate(t, session, "select count(*) from vt_insert_test", "INT64(2)") + + // check that new tablet is accessible with use `ks:shard` + cluster.ExecuteQueriesUsingVtgate(t, session, "use `"+recoveryKS1+":0@replica`") + recovery.VerifyQueriesUsingVtgate(t, session, "select count(*) from vt_insert_test", "INT64(1)") + + cluster.ExecuteQueriesUsingVtgate(t, session, "use `"+recoveryKS2+":0@replica`") + recovery.VerifyQueriesUsingVtgate(t, session, "select count(*) from vt_insert_test", "INT64(2)") +} + +// verifyInitialReplication will create schema in master, insert some data to master and verify the same data in replica. +func verifyInitialReplication(t *testing.T) { + _, err := master.VttabletProcess.QueryTablet(vtInsertTest, keyspaceName, true) + assert.Nil(t, err) + _, err = master.VttabletProcess.QueryTablet("insert into vt_insert_test (msg) values ('test1')", keyspaceName, true) + assert.Nil(t, err) + cluster.VerifyRowsInTablet(t, replica1, keyspaceName, 1) +} + +func listBackups(t *testing.T) []string { + output, err := localCluster.ListBackups(shardKsName) + assert.Nil(t, err) + return output +} + +func tabletsTeardown() { + var mysqlProcs []*exec.Cmd + for _, tablet := range []*cluster.Vttablet{master, replica1, replica2, replica3} { + proc, _ := tablet.MysqlctlProcess.StopProcess() + mysqlProcs = append(mysqlProcs, proc) + tablet.VttabletProcess.TearDown() + } + for _, proc := range mysqlProcs { + proc.Wait() + } +} diff --git a/go/test/endtoend/recovery/unshardedrecovery/recovery_test.go b/go/test/endtoend/recovery/unshardedrecovery/recovery_test.go new file mode 100644 index 00000000000..86079a6eb54 --- /dev/null +++ b/go/test/endtoend/recovery/unshardedrecovery/recovery_test.go @@ -0,0 +1,31 @@ +/* +Copyright 2020 The Vitess Authors. + +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. +*/ + +package unshardedrecovery + +import ( + "testing" + + _ "vitess.io/vitess/go/vt/vtgate/grpcvtgateconn" +) + +func TestMain(m *testing.M) { + TestMainImpl(m) +} + +func TestRecovery(t *testing.T) { + TestRecoveryImpl(t) +} diff --git a/go/test/endtoend/recovery/xtrabackup/recovery_test.go b/go/test/endtoend/recovery/xtrabackup/recovery_test.go new file mode 100644 index 00000000000..940fc5ad7e2 --- /dev/null +++ b/go/test/endtoend/recovery/xtrabackup/recovery_test.go @@ -0,0 +1,34 @@ +/* +Copyright 2020 The Vitess Authors. + +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. +*/ + +package xtrabackup + +import ( + "testing" + + "vitess.io/vitess/go/test/endtoend/recovery" + "vitess.io/vitess/go/test/endtoend/recovery/unshardedrecovery" + _ "vitess.io/vitess/go/vt/vtgate/grpcvtgateconn" +) + +func TestMain(m *testing.M) { + recovery.UseXb = true + unshardedrecovery.TestMainImpl(m) +} + +func TestRecovery(t *testing.T) { + unshardedrecovery.TestRecoveryImpl(t) +} diff --git a/go/test/endtoend/reparent/main_test.go b/go/test/endtoend/reparent/main_test.go new file mode 100644 index 00000000000..4e519b03511 --- /dev/null +++ b/go/test/endtoend/reparent/main_test.go @@ -0,0 +1,176 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package reparent + +import ( + "context" + "flag" + "fmt" + "os" + "os/exec" + "path" + "testing" + + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/test/endtoend/cluster" + tmc "vitess.io/vitess/go/vt/vttablet/grpctmclient" +) + +var ( + // ClusterInstance instance to be used for test with different params + clusterInstance *cluster.LocalProcessCluster + tmClient *tmc.Client + keyspaceName = "ks" + shardName = "0" + shard1Name = "0000000000000000-ffffffffffffffff" + keyspaceShard = keyspaceName + "/" + shardName + dbName = "vt_" + keyspaceName + username = "vt_dba" + hostname = "localhost" + cell1 = "zone1" + cell2 = "zone2" + insertSQL = "insert into vt_insert_test(id, msg) values (%d, 'test %d')" + sqlSchema = ` + create table vt_insert_test ( + id bigint, + msg varchar(64), + primary key (id) + ) Engine=InnoDB + ` + // Tablets for shard0 + tablet62344 *cluster.Vttablet + tablet62044 *cluster.Vttablet + tablet41983 *cluster.Vttablet + tablet31981 *cluster.Vttablet + + // Tablets for shard1 + masterTablet *cluster.Vttablet + replicaTablet *cluster.Vttablet +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitCode := func() int { + clusterInstance = cluster.NewCluster(cell1, hostname) + defer clusterInstance.Teardown() + + // Launch keyspace + keyspace := &cluster.Keyspace{Name: keyspaceName} + + // Start topo server + err := clusterInstance.StartTopo() + if err != nil { + return 1 + } + + // Adding another cell in the same cluster + err = clusterInstance.TopoProcess.ManageTopoDir("mkdir", "/vitess/"+cell2) + if err != nil { + return 1 + } + err = clusterInstance.VtctlProcess.AddCellInfo(cell2) + if err != nil { + return 1 + } + + tablet62344 = clusterInstance.GetVttabletInstance("replica", 62344, "") + tablet62044 = clusterInstance.GetVttabletInstance("replica", 62044, "") + tablet41983 = clusterInstance.GetVttabletInstance("replica", 41983, "") + tablet31981 = clusterInstance.GetVttabletInstance("replica", 31981, cell2) + + shard0 := &cluster.Shard{Name: shardName} + shard0.Vttablets = []*cluster.Vttablet{tablet62344, tablet62044, tablet41983, tablet31981} + + // Initiate shard1 - required for ranged based reparenting + masterTablet = clusterInstance.GetVttabletInstance("replica", 0, "") + replicaTablet = clusterInstance.GetVttabletInstance("replica", 0, "") + + shard1 := &cluster.Shard{Name: shard1Name} + shard1.Vttablets = []*cluster.Vttablet{masterTablet, replicaTablet} + + clusterInstance.VtTabletExtraArgs = []string{ + "-lock_tables_timeout", "5s", + "-enable_semi_sync", + } + + // Initialize Cluster + err = clusterInstance.LaunchCluster(keyspace, []cluster.Shard{*shard0, *shard1}) + if err != nil { + return 1 + } + + //Start MySql + var mysqlCtlProcessList []*exec.Cmd + for _, shard := range clusterInstance.Keyspaces[0].Shards { + for _, tablet := range shard.Vttablets { + fmt.Println("Starting MySql for tablet ", tablet.Alias) + if proc, err := tablet.MysqlctlProcess.StartProcess(); err != nil { + return 1 + } else { + mysqlCtlProcessList = append(mysqlCtlProcessList, proc) + } + } + } + + // Wait for mysql processes to start + for _, proc := range mysqlCtlProcessList { + if err := proc.Wait(); err != nil { + return 1 + } + } + + // We do not need semiSync for this test case. + clusterInstance.EnableSemiSync = false + + // create tablet manager client + tmClient = tmc.NewClient() + + return m.Run() + }() + os.Exit(exitCode) +} + +func getMysqlConnParam(tablet *cluster.Vttablet) mysql.ConnParams { + connParams := mysql.ConnParams{ + Uname: username, + DbName: dbName, + UnixSocket: path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("/vt_%010d/mysql.sock", tablet.TabletUID)), + } + return connParams +} + +func runSQL(ctx context.Context, t *testing.T, sql string, tablet *cluster.Vttablet) *sqltypes.Result { + // Get Connection + tabletParams := getMysqlConnParam(tablet) + conn, err := mysql.Connect(ctx, &tabletParams) + require.Nil(t, err) + defer conn.Close() + + // runSQL + return execute(t, conn, sql) +} + +func execute(t *testing.T, conn *mysql.Conn, query string) *sqltypes.Result { + t.Helper() + qr, err := conn.ExecuteFetch(query, 1000, true) + require.Nil(t, err) + return qr +} diff --git a/go/test/endtoend/reparent/reparent_range_based_test.go b/go/test/endtoend/reparent/reparent_range_based_test.go new file mode 100644 index 00000000000..4e7dfafbe75 --- /dev/null +++ b/go/test/endtoend/reparent/reparent_range_based_test.go @@ -0,0 +1,94 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package reparent + +import ( + "context" + "fmt" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/test/endtoend/cluster" +) + +func TestReparentGracefulRangeBased(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + + for _, tablet := range []cluster.Vttablet{*masterTablet, *replicaTablet} { + // create database + err := tablet.VttabletProcess.CreateDB(keyspaceName) + require.Nil(t, err) + // Init Tablet + err = clusterInstance.VtctlclientProcess.InitTablet(&tablet, tablet.Cell, keyspaceName, hostname, shard1Name) + require.Nil(t, err) + // Start the tablet + err = tablet.VttabletProcess.Setup() + require.Nil(t, err) + } + + for _, tablet := range []cluster.Vttablet{*masterTablet, *replicaTablet} { + err := tablet.VttabletProcess.WaitForTabletTypes([]string{"SERVING", "NOT_SERVING"}) + require.Nil(t, err) + } + + // Force the replica to reparent assuming that all the datasets are identical. + err := clusterInstance.VtctlclientProcess.ExecuteCommand("InitShardMaster", + "-force", fmt.Sprintf("%s/%s", keyspaceName, shard1Name), masterTablet.Alias) + require.Nil(t, err) + + // Validate topology + validateTopology(t, true) + + // create Tables + runSQL(ctx, t, sqlSchema, masterTablet) + + checkMasterTablet(t, masterTablet) + + validateTopology(t, false) + + // Run this to make sure it succeeds. + output, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput( + "ShardReplicationPositions", fmt.Sprintf("%s/%s", keyspaceName, shard1Name)) + require.Nil(t, err) + strArray := strings.Split(output, "\n") + if strArray[len(strArray)-1] == "" { + strArray = strArray[:len(strArray)-1] // Truncate slice, remove empty line + } + assert.Equal(t, 2, len(strArray)) // one master, one slave + assert.Contains(t, strArray[0], "master") // master first + + // Perform a graceful reparent operation + err = clusterInstance.VtctlclientProcess.ExecuteCommand( + "PlannedReparentShard", + "-keyspace_shard", fmt.Sprintf("%s/%s", keyspaceName, shard1Name), + "-new_master", replicaTablet.Alias) + require.Nil(t, err) + + // Validate topology + validateTopology(t, false) + + checkMasterTablet(t, replicaTablet) + + // insert data into the new master, check the connected replica work + insertSQL := fmt.Sprintf(insertSQL, 1, 1) + runSQL(ctx, t, insertSQL, replicaTablet) + err = checkInsertedValues(ctx, t, masterTablet, 1) + require.Nil(t, err) +} diff --git a/go/test/endtoend/reparent/reparent_test.go b/go/test/endtoend/reparent/reparent_test.go new file mode 100644 index 00000000000..2a5f8bacaf4 --- /dev/null +++ b/go/test/endtoend/reparent/reparent_test.go @@ -0,0 +1,911 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package reparent + +import ( + "context" + "encoding/json" + "fmt" + "reflect" + "strings" + "testing" + "time" + + "vitess.io/vitess/go/mysql" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/json2" + "vitess.io/vitess/go/test/endtoend/cluster" + querypb "vitess.io/vitess/go/vt/proto/query" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" +) + +func TestMasterToSpareStateChangeImpossible(t *testing.T) { + defer cluster.PanicHandler(t) + + args := []string{"InitTablet", "-hostname", hostname, + "-port", fmt.Sprintf("%d", tablet62344.HTTPPort), "-allow_update", "-parent", + "-keyspace", keyspaceName, + "-shard", shardName, + "-mysql_port", fmt.Sprintf("%d", tablet62344.MySQLPort), + "-grpc_port", fmt.Sprintf("%d", tablet62344.GrpcPort)} + args = append(args, fmt.Sprintf("%s-%010d", tablet62344.Cell, tablet62344.TabletUID), "master") + err := clusterInstance.VtctlclientProcess.ExecuteCommand(args...) + require.Nil(t, err) + + // Start the tablet + err = tablet62344.VttabletProcess.Setup() + require.Nil(t, err) + + // Create Database + err = tablet62344.VttabletProcess.CreateDB(keyspaceName) + require.Nil(t, err) + + // We cannot change a master to spare + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", tablet62344.Alias, "spare") + require.Error(t, err) + + //kill Tablet + err = tablet62344.VttabletProcess.TearDown() + require.Nil(t, err) +} + +func TestReparentDownMaster(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + + for _, tablet := range []cluster.Vttablet{*tablet62344, *tablet62044, *tablet41983, *tablet31981} { + // Create Database + err := tablet.VttabletProcess.CreateDB(keyspaceName) + require.Nil(t, err) + + // Reset status, don't wait for the tablet status. We will check it later + tablet.VttabletProcess.ServingStatus = "" + // Init Tablet + err = clusterInstance.VtctlclientProcess.InitTablet(&tablet, tablet.Cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + // Start the tablet + err = tablet.VttabletProcess.Setup() + require.Nil(t, err) + } + + for _, tablet := range []cluster.Vttablet{*tablet62344, *tablet62044, *tablet41983, *tablet31981} { + err := tablet.VttabletProcess.WaitForTabletTypes([]string{"SERVING", "NOT_SERVING"}) + require.Nil(t, err) + } + + // Init Shard Master + err := clusterInstance.VtctlclientProcess.ExecuteCommand("InitShardMaster", + "-force", fmt.Sprintf("%s/%s", keyspaceName, shardName), tablet62344.Alias) + require.Nil(t, err) + + validateTopology(t, true) + + // create Tables + runSQL(ctx, t, sqlSchema, tablet62344) + + // Make the current master agent and database unavailable. + err = tablet62344.VttabletProcess.TearDown() + require.Nil(t, err) + err = tablet62344.MysqlctlProcess.Stop() + require.Nil(t, err) + + // Perform a planned reparent operation, will try to contact + // the current master and fail somewhat quickly + err = clusterInstance.VtctlclientProcess.ExecuteCommand( + "PlannedReparentShard", + "-wait-time", "5s", + "-keyspace_shard", keyspaceShard, + "-new_master", tablet62044.Alias) + require.Error(t, err) + + // Run forced reparent operation, this should now proceed unimpeded. + err = clusterInstance.VtctlclientProcess.ExecuteCommand( + "EmergencyReparentShard", + "-keyspace_shard", keyspaceShard, + "-new_master", tablet62044.Alias) + require.Nil(t, err) + + validateTopology(t, false) + + checkMasterTablet(t, tablet62044) + + // insert data into the new master, check the connected replica work + insertSQL := fmt.Sprintf(insertSQL, 2, 2) + runSQL(ctx, t, insertSQL, tablet62044) + err = checkInsertedValues(ctx, t, tablet41983, 2) + require.Nil(t, err) + err = checkInsertedValues(ctx, t, tablet31981, 2) + require.Nil(t, err) + + // bring back the old master as a replica, check that it catches up + tablet62344.MysqlctlProcess.InitMysql = false + err = tablet62344.MysqlctlProcess.Start() + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.InitTablet(tablet62344, tablet62344.Cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + // As there is already a master the new replica will come directly in SERVING state + tablet62344.VttabletProcess.ServingStatus = "SERVING" + // Start the tablet + err = tablet62344.VttabletProcess.Setup() + require.Nil(t, err) + + err = checkInsertedValues(ctx, t, tablet62344, 2) + require.Nil(t, err) + + // Kill tablets + killTablets(t) +} + +func TestReparentCrossCell(t *testing.T) { + + defer cluster.PanicHandler(t) + for _, tablet := range []cluster.Vttablet{*tablet62344, *tablet62044, *tablet41983, *tablet31981} { + // create database + err := tablet.VttabletProcess.CreateDB(keyspaceName) + require.Nil(t, err) + + // Init Tablet + err = clusterInstance.VtctlclientProcess.InitTablet(&tablet, tablet.Cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + // Start the tablet + err = tablet.VttabletProcess.Setup() + require.Nil(t, err) + } + + for _, tablet := range []cluster.Vttablet{*tablet62344, *tablet62044, *tablet41983, *tablet31981} { + err := tablet.VttabletProcess.WaitForTabletTypes([]string{"SERVING", "NOT_SERVING"}) + require.Nil(t, err) + } + + // Force the replica to reparent assuming that all the datasets are identical. + err := clusterInstance.VtctlclientProcess.ExecuteCommand("InitShardMaster", + "-force", fmt.Sprintf("%s/%s", keyspaceName, shardName), tablet62344.Alias) + require.Nil(t, err) + + validateTopology(t, true) + + checkMasterTablet(t, tablet62344) + + // Perform a graceful reparent operation to another cell. + err = clusterInstance.VtctlclientProcess.ExecuteCommand( + "PlannedReparentShard", + "-keyspace_shard", keyspaceShard, + "-new_master", tablet31981.Alias) + require.Nil(t, err) + + validateTopology(t, false) + + checkMasterTablet(t, tablet31981) + + // Kill tablets + killTablets(t) + +} + +func TestReparentGraceful(t *testing.T) { + reparentGraceful(t, false) +} + +func TestReparentGracefulRecovery(t *testing.T) { + reparentGraceful(t, true) +} + +func reparentGraceful(t *testing.T, confusedMaster bool) { + defer cluster.PanicHandler(t) + ctx := context.Background() + + for _, tablet := range []cluster.Vttablet{*tablet62344, *tablet62044, *tablet41983, *tablet31981} { + // create database + err := tablet.VttabletProcess.CreateDB(keyspaceName) + require.Nil(t, err) + + // Init Tablet + err = clusterInstance.VtctlclientProcess.InitTablet(&tablet, tablet.Cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + // Start the tablet + err = tablet.VttabletProcess.Setup() + require.Nil(t, err) + } + + for _, tablet := range []cluster.Vttablet{*tablet62344, *tablet62044, *tablet41983, *tablet31981} { + err := tablet.VttabletProcess.WaitForTabletTypes([]string{"SERVING", "NOT_SERVING"}) + require.Nil(t, err) + } + + // Force the replica to reparent assuming that all the datasets are identical. + err := clusterInstance.VtctlclientProcess.ExecuteCommand("InitShardMaster", + "-force", fmt.Sprintf("%s/%s", keyspaceName, shardName), tablet62344.Alias) + require.Nil(t, err) + + validateTopology(t, true) + + // create Tables + runSQL(ctx, t, sqlSchema, tablet62344) + + checkMasterTablet(t, tablet62344) + + validateTopology(t, false) + + // Run this to make sure it succeeds. + output, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput( + "ShardReplicationPositions", fmt.Sprintf("%s/%s", keyspaceName, shardName)) + require.Nil(t, err) + strArray := strings.Split(output, "\n") + if strArray[len(strArray)-1] == "" { + strArray = strArray[:len(strArray)-1] // Truncate slice, remove empty line + } + assert.Equal(t, 4, len(strArray)) // one master, three replicas + assert.Contains(t, strArray[0], "master") // master first + + // Perform a graceful reparent operation + err = clusterInstance.VtctlclientProcess.ExecuteCommand( + "PlannedReparentShard", + "-keyspace_shard", fmt.Sprintf("%s/%s", keyspaceName, shardName), + "-new_master", tablet62044.Alias) + require.Nil(t, err) + + validateTopology(t, false) + + checkMasterTablet(t, tablet62044) + + // Simulate a master that forgets it's master and becomes replica. + // PlannedReparentShard should be able to recover by reparenting to the same master again, + // as long as all tablets are available to check that it's safe. + if confusedMaster { + tablet62044.Type = "replica" + err = clusterInstance.VtctlclientProcess.InitTablet(tablet62044, tablet62044.Cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RefreshState", tablet62044.Alias) + require.Nil(t, err) + } + + // Perform a graceful reparent to the same master. + // It should be idempotent, and should fix any inconsistencies if necessary + err = clusterInstance.VtctlclientProcess.ExecuteCommand( + "PlannedReparentShard", + "-keyspace_shard", fmt.Sprintf("%s/%s", keyspaceName, shardName), + "-new_master", tablet62044.Alias) + require.Nil(t, err) + + validateTopology(t, false) + + checkMasterTablet(t, tablet62044) + + // insert data into the new master, check the connected replica work + insertSQL := fmt.Sprintf(insertSQL, 1, 1) + runSQL(ctx, t, insertSQL, tablet62044) + err = checkInsertedValues(ctx, t, tablet41983, 1) + require.Nil(t, err) + err = checkInsertedValues(ctx, t, tablet62344, 1) + require.Nil(t, err) + + // Kill tablets + killTablets(t) +} + +func TestReparentSlaveOffline(t *testing.T) { + defer cluster.PanicHandler(t) + + for _, tablet := range []cluster.Vttablet{*tablet62344, *tablet62044, *tablet41983, *tablet31981} { + // create database + err := tablet.VttabletProcess.CreateDB(keyspaceName) + require.Nil(t, err) + + // Init Tablet + err = clusterInstance.VtctlclientProcess.InitTablet(&tablet, tablet.Cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + // Start the tablet + err = tablet.VttabletProcess.Setup() + require.Nil(t, err) + } + + for _, tablet := range []cluster.Vttablet{*tablet62344, *tablet62044, *tablet41983, *tablet31981} { + err := tablet.VttabletProcess.WaitForTabletTypes([]string{"SERVING", "NOT_SERVING"}) + require.Nil(t, err) + } + + // Force the replica to reparent assuming that all the datasets are identical. + err := clusterInstance.VtctlclientProcess.ExecuteCommand("InitShardMaster", + "-force", keyspaceShard, tablet62344.Alias) + require.Nil(t, err) + + validateTopology(t, true) + + checkMasterTablet(t, tablet62344) + + // Kill one tablet so we seem offline + err = tablet31981.VttabletProcess.TearDown() + require.Nil(t, err) + + // Perform a graceful reparent operation. + out, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput( + "PlannedReparentShard", + "-keyspace_shard", keyspaceShard, + "-new_master", tablet62044.Alias) + require.Error(t, err) + assert.Contains(t, out, "tablet zone2-0000031981 SetMaster failed") + + checkMasterTablet(t, tablet62044) + + killTablets(t) +} + +func TestReparentAvoid(t *testing.T) { + defer cluster.PanicHandler(t) + // Remove tablet41983 from topology as that tablet is not required for this test + err := clusterInstance.VtctlclientProcess.ExecuteCommand("DeleteTablet", tablet41983.Alias) + require.Nil(t, err) + + for _, tablet := range []cluster.Vttablet{*tablet62344, *tablet62044, *tablet31981} { + // create database + err := tablet.VttabletProcess.CreateDB(keyspaceName) + require.Nil(t, err) + + // Init Tablet + err = clusterInstance.VtctlclientProcess.InitTablet(&tablet, tablet.Cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + // Start the tablet + err = tablet.VttabletProcess.Setup() + require.Nil(t, err) + } + + for _, tablet := range []cluster.Vttablet{*tablet62344, *tablet62044, *tablet31981} { + err := tablet.VttabletProcess.WaitForTabletTypes([]string{"SERVING", "NOT_SERVING"}) + require.Nil(t, err) + } + + // Force the replica to reparent assuming that all the dataset's are identical. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("InitShardMaster", + "-force", keyspaceShard, tablet62344.Alias) + require.Nil(t, err) + + validateTopology(t, true) + + checkMasterTablet(t, tablet62344) + + // Perform a reparent operation with avoid_master pointing to non-master. It + // should succeed without doing anything. + err = clusterInstance.VtctlclientProcess.ExecuteCommand( + "PlannedReparentShard", + "-keyspace_shard", keyspaceShard, + "-avoid_master", tablet62044.Alias) + require.Nil(t, err) + + validateTopology(t, false) + + checkMasterTablet(t, tablet62344) + + // Perform a reparent operation with avoid_master pointing to master. + err = clusterInstance.VtctlclientProcess.ExecuteCommand( + "PlannedReparentShard", + "-keyspace_shard", keyspaceShard, + "-avoid_master", tablet62344.Alias) + require.Nil(t, err) + + validateTopology(t, false) + + // 62044 is in the same cell and 31981 is in a different cell, so we must land on 62044 + checkMasterTablet(t, tablet62044) + + // If we kill the tablet in the same cell as master then reparent -avoid_master will fail. + err = tablet62344.VttabletProcess.TearDown() + require.Nil(t, err) + + output, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput( + "PlannedReparentShard", + "-keyspace_shard", keyspaceShard, + "-avoid_master", tablet62044.Alias) + require.Error(t, err) + assert.Contains(t, output, "cannot find a tablet to reparent to") + + validateTopology(t, false) + + checkMasterTablet(t, tablet62044) + + killTablets(t) +} + +func TestReparentFromOutside(t *testing.T) { + reparentFromOutside(t, false) +} + +func TestReparentFromOutsideWithNoMaster(t *testing.T) { + defer cluster.PanicHandler(t) + reparentFromOutside(t, true) + + // We will have to restart mysql to avoid hanging/locks due to external Reparent + for _, tablet := range []cluster.Vttablet{*tablet62344, *tablet62044, *tablet41983, *tablet31981} { + fmt.Println("Restarting MySql for tablet ", tablet.Alias) + err := tablet.MysqlctlProcess.Stop() + require.Nil(t, err) + tablet.MysqlctlProcess.InitMysql = false + err = tablet.MysqlctlProcess.Start() + require.Nil(t, err) + } +} + +func reparentFromOutside(t *testing.T, downMaster bool) { + //This test will start a master and 3 replicas. + //Then: + //- one replica will be the new master + //- one replica will be reparented to that new master + //- one replica will be busted and dead in the water and we'll call TabletExternallyReparented. + //Args: + //downMaster: kills the old master first + defer cluster.PanicHandler(t) + + ctx := context.Background() + + for _, tablet := range []cluster.Vttablet{*tablet62344, *tablet62044, *tablet41983, *tablet31981} { + // create database + err := tablet.VttabletProcess.CreateDB(keyspaceName) + require.Nil(t, err) + + // Init Tablet + err = clusterInstance.VtctlclientProcess.InitTablet(&tablet, tablet.Cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + // Start the tablet + err = tablet.VttabletProcess.Setup() + require.Nil(t, err) + } + + for _, tablet := range []cluster.Vttablet{*tablet62344, *tablet62044, *tablet41983, *tablet31981} { + err := tablet.VttabletProcess.WaitForTabletTypes([]string{"SERVING", "NOT_SERVING"}) + require.Nil(t, err) + } + + // Reparent as a starting point + err := clusterInstance.VtctlclientProcess.ExecuteCommand("InitShardMaster", + "-force", fmt.Sprintf("%s/%s", keyspaceName, shardName), tablet62344.Alias) + require.Nil(t, err) + + validateTopology(t, true) + + checkMasterTablet(t, tablet62344) + + // now manually reparent 1 out of 2 tablets + // 62044 will be the new master + // 31981 won't be re-parented, so it will be busted + + if !downMaster { + // commands to stop the current master + demoteMasterCommands := "SET GLOBAL read_only = ON; FLUSH TABLES WITH READ LOCK; UNLOCK TABLES" + runSQL(ctx, t, demoteMasterCommands, tablet62344) + + //Get the position of the old master and wait for the new one to catch up. + err = waitForReplicationPosition(t, tablet62344, tablet62044) + require.Nil(t, err) + } + + // commands to convert a replica to a master + promoteSlaveCommands := "STOP SLAVE; RESET SLAVE ALL; SET GLOBAL read_only = OFF;" + runSQL(ctx, t, promoteSlaveCommands, tablet62044) + + // Get master position + _, gtID := cluster.GetMasterPosition(t, *tablet62044, hostname) + + // 62344 will now be a slave of 62044 + changeMasterCommands := fmt.Sprintf("RESET MASTER; RESET SLAVE; SET GLOBAL gtid_purged = '%s';"+ + "CHANGE MASTER TO MASTER_HOST='%s', MASTER_PORT=%d, MASTER_USER='vt_repl', MASTER_AUTO_POSITION = 1;"+ + "START SLAVE;", gtID, hostname, tablet62044.MySQLPort) + runSQL(ctx, t, changeMasterCommands, tablet62344) + + // Capture time when we made tablet62044 master + baseTime := time.Now().UnixNano() / 1000000000 + + // 41983 will be a slave of 62044 + changeMasterCommands = fmt.Sprintf("STOP SLAVE; RESET MASTER; SET GLOBAL gtid_purged = '%s';"+ + "CHANGE MASTER TO MASTER_HOST='%s', MASTER_PORT=%d, MASTER_USER='vt_repl', MASTER_AUTO_POSITION = 1;"+ + "START SLAVE;", gtID, hostname, tablet62044.MySQLPort) + runSQL(ctx, t, changeMasterCommands, tablet41983) + + // To test the downMaster, we kill the old master first and delete its tablet record + if downMaster { + err := tablet62344.VttabletProcess.TearDown() + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("DeleteTablet", + "-allow_master", tablet62344.Alias) + require.Nil(t, err) + } + + // update topology with the new server + err = clusterInstance.VtctlclientProcess.ExecuteCommand("TabletExternallyReparented", + tablet62044.Alias) + require.Nil(t, err) + + checkReparentFromOutside(t, tablet62044, downMaster, baseTime) + + if !downMaster { + err := tablet62344.VttabletProcess.TearDown() + require.Nil(t, err) + } + + killTablets(t) +} + +func TestReparentWithDownSlave(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + + for _, tablet := range []cluster.Vttablet{*tablet62344, *tablet62044, *tablet41983, *tablet31981} { + // Create Database + err := tablet.VttabletProcess.CreateDB(keyspaceName) + require.Nil(t, err) + + // Init Tablet + err = clusterInstance.VtctlclientProcess.InitTablet(&tablet, tablet.Cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + // Start the tablet + err = tablet.VttabletProcess.Setup() + require.Nil(t, err) + } + + for _, tablet := range []cluster.Vttablet{*tablet62344, *tablet62044, *tablet41983, *tablet31981} { + err := tablet.VttabletProcess.WaitForTabletTypes([]string{"SERVING", "NOT_SERVING"}) + require.Nil(t, err) + } + + // Init Shard Master + err := clusterInstance.VtctlclientProcess.ExecuteCommand("InitShardMaster", + "-force", fmt.Sprintf("%s/%s", keyspaceName, shardName), tablet62344.Alias) + require.Nil(t, err) + + validateTopology(t, true) + + // create Tables + runSQL(ctx, t, sqlSchema, tablet62344) + + // Stop replica mysql Process + err = tablet41983.MysqlctlProcess.Stop() + require.Nil(t, err) + + // Perform a graceful reparent operation. It will fail as one tablet is down. + output, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput( + "PlannedReparentShard", + "-keyspace_shard", keyspaceShard, + "-new_master", tablet62044.Alias) + require.Error(t, err) + assert.Contains(t, output, "TabletManager.SetMaster on zone1-0000041983 error") + + // insert data into the new master, check the connected replica work + insertSQL := fmt.Sprintf(insertSQL, 3, 3) + runSQL(ctx, t, insertSQL, tablet62044) + err = checkInsertedValues(ctx, t, tablet31981, 3) + require.Nil(t, err) + err = checkInsertedValues(ctx, t, tablet62344, 3) + require.Nil(t, err) + + // restart mysql on the old replica, should still be connecting to the old master + tablet41983.MysqlctlProcess.InitMysql = false + err = tablet41983.MysqlctlProcess.Start() + require.Nil(t, err) + + // Use the same PlannedReparentShard command to fix up the tablet. + err = clusterInstance.VtctlclientProcess.ExecuteCommand( + "PlannedReparentShard", + "-keyspace_shard", keyspaceShard, + "-new_master", tablet62044.Alias) + require.Nil(t, err) + + // wait until it gets the data + err = checkInsertedValues(ctx, t, tablet41983, 3) + require.Nil(t, err) + + killTablets(t) +} + +func TestChangeTypeSemiSync(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + + // Create new names for tablets, so this test is less confusing. + master := tablet62344 + replica := tablet62044 + rdonly1 := tablet41983 + rdonly2 := tablet31981 + + for _, tablet := range []cluster.Vttablet{*master, *replica, *rdonly1, *rdonly2} { + // Create Database + err := tablet.VttabletProcess.CreateDB(keyspaceName) + require.Nil(t, err) + + // Init Tablet + err = clusterInstance.VtctlclientProcess.InitTablet(&tablet, tablet.Cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + // Start the tablet + err = tablet.VttabletProcess.Setup() + require.Nil(t, err) + } + + // Init Shard Master + err := clusterInstance.VtctlclientProcess.ExecuteCommand("InitShardMaster", + "-force", fmt.Sprintf("%s/%s", keyspaceName, shardName), master.Alias) + require.Nil(t, err) + + for _, tablet := range []cluster.Vttablet{*master, *replica, *rdonly1, *rdonly2} { + err := tablet.VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + } + + // Updated rdonly tablet and set tablet type to rdonly + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", rdonly1.Alias, "rdonly") + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", rdonly2.Alias, "rdonly") + require.Nil(t, err) + + validateTopology(t, true) + + checkMasterTablet(t, master) + + // Stop replication on rdonly1, to make sure when we make it replica it doesn't start again. + // Note we do a similar test for replica -> rdonly below. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("StopSlave", rdonly1.Alias) + require.Nil(t, err) + + // Check semi-sync on replicas. + // The flag is only an indication of the value to use next time + // we turn replication on, so also check the status. + // rdonly1 is not replicating, so its status is off. + checkDBvar(ctx, t, replica, "rpl_semi_sync_slave_enabled", "ON") + checkDBvar(ctx, t, rdonly1, "rpl_semi_sync_slave_enabled", "OFF") + checkDBvar(ctx, t, rdonly2, "rpl_semi_sync_slave_enabled", "OFF") + checkDBstatus(ctx, t, replica, "Rpl_semi_sync_slave_status", "ON") + checkDBstatus(ctx, t, rdonly1, "Rpl_semi_sync_slave_status", "OFF") + checkDBstatus(ctx, t, rdonly2, "Rpl_semi_sync_slave_status", "OFF") + + // Change replica to rdonly while replicating, should turn off semi-sync, and restart replication. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", replica.Alias, "rdonly") + require.Nil(t, err) + checkDBvar(ctx, t, replica, "rpl_semi_sync_slave_enabled", "OFF") + checkDBstatus(ctx, t, replica, "Rpl_semi_sync_slave_status", "OFF") + + // Change rdonly1 to replica, should turn on semi-sync, and not start replication. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", rdonly1.Alias, "replica") + require.Nil(t, err) + checkDBvar(ctx, t, rdonly1, "rpl_semi_sync_slave_enabled", "ON") + checkDBstatus(ctx, t, rdonly1, "Rpl_semi_sync_slave_status", "OFF") + checkSlaveStatus(ctx, t, rdonly1) + + // Now change from replica back to rdonly, make sure replication is still not enabled. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", rdonly1.Alias, "rdonly") + require.Nil(t, err) + checkDBvar(ctx, t, rdonly1, "rpl_semi_sync_slave_enabled", "OFF") + checkDBstatus(ctx, t, rdonly1, "Rpl_semi_sync_slave_status", "OFF") + checkSlaveStatus(ctx, t, rdonly1) + + // Change rdonly2 to replica, should turn on semi-sync, and restart replication. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", rdonly2.Alias, "replica") + require.Nil(t, err) + checkDBvar(ctx, t, rdonly2, "rpl_semi_sync_slave_enabled", "ON") + checkDBstatus(ctx, t, rdonly2, "Rpl_semi_sync_slave_status", "ON") + + killTablets(t) +} + +func TestReparentDoesntHangIfMasterFails(t *testing.T) { + defer cluster.PanicHandler(t) + for _, tablet := range []cluster.Vttablet{*tablet62344, *tablet62044, *tablet41983, *tablet31981} { + // Create Database + err := tablet.VttabletProcess.CreateDB(keyspaceName) + require.Nil(t, err) + + // Init Tablet + err = clusterInstance.VtctlclientProcess.InitTablet(&tablet, tablet.Cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + // Start the tablet + err = tablet.VttabletProcess.Setup() + require.Nil(t, err) + } + + // Init Shard Master + err := clusterInstance.VtctlclientProcess.ExecuteCommand("InitShardMaster", + "-force", fmt.Sprintf("%s/%s", keyspaceName, shardName), tablet62344.Alias) + require.Nil(t, err) + + for _, tablet := range []cluster.Vttablet{*tablet62344, *tablet62044, *tablet41983, *tablet31981} { + err := tablet.VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + } + + validateTopology(t, true) + + // Change the schema of the _vt.reparent_journal table, so that + // inserts into it will fail. That will make the master fail. + _, err = tablet62344.VttabletProcess.QueryTabletWithDB( + "ALTER TABLE reparent_journal DROP COLUMN replication_position", "_vt") + require.Nil(t, err) + + // Perform a planned reparent operation, the master will fail the + // insert. The slaves should then abort right away. + out, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput( + "PlannedReparentShard", + "-keyspace_shard", keyspaceShard, + "-new_master", tablet62044.Alias) + require.Error(t, err) + assert.Contains(t, out, "master failed to PopulateReparentJournal") + + killTablets(t) +} + +// Waits for tablet B to catch up to the replication position of tablet A. +func waitForReplicationPosition(t *testing.T, tabletA *cluster.Vttablet, tabletB *cluster.Vttablet) error { + posA, _ := cluster.GetMasterPosition(t, *tabletA, hostname) + timeout := time.Now().Add(5 * time.Second) + for time.Now().Before(timeout) { + posB, _ := cluster.GetMasterPosition(t, *tabletB, hostname) + if positionAtLeast(t, tabletB, posA, posB) { + return nil + } + time.Sleep(100 * time.Millisecond) + } + return fmt.Errorf("failed to catch up on replication position") +} + +func positionAtLeast(t *testing.T, tablet *cluster.Vttablet, a string, b string) bool { + isAtleast := false + val, err := tablet.MysqlctlProcess.ExecuteCommandWithOutput("position", "at_least", a, b) + require.Nil(t, err) + if strings.Contains(val, "true") { + isAtleast = true + } + return isAtleast +} + +func checkReparentFromOutside(t *testing.T, tablet *cluster.Vttablet, downMaster bool, baseTime int64) { + result, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("GetShardReplication", cell1, keyspaceShard) + require.Nil(t, err, "error should be Nil") + if !downMaster { + assertNodeCount(t, result, int(3)) + } else { + assertNodeCount(t, result, int(2)) + } + + // make sure the master status page says it's the master + status := tablet.VttabletProcess.GetStatus() + assert.Contains(t, status, "Tablet Type: MASTER") + + // make sure the master health stream says it's the master too + // (health check is disabled on these servers, force it first) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", tablet.Alias) + require.Nil(t, err) + + streamHealth, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput( + "VtTabletStreamHealth", + "-count", "1", tablet.Alias) + require.Nil(t, err) + + var streamHealthResponse querypb.StreamHealthResponse + err = json.Unmarshal([]byte(streamHealth), &streamHealthResponse) + require.Nil(t, err) + assert.Equal(t, streamHealthResponse.Target.TabletType, topodatapb.TabletType_MASTER) + assert.True(t, streamHealthResponse.TabletExternallyReparentedTimestamp >= baseTime) + +} + +func assertNodeCount(t *testing.T, result string, want int) { + resultMap := make(map[string]interface{}) + err := json.Unmarshal([]byte(result), &resultMap) + require.Nil(t, err) + + nodes := reflect.ValueOf(resultMap["nodes"]) + got := nodes.Len() + assert.Equal(t, want, got) +} + +func checkDBvar(ctx context.Context, t *testing.T, tablet *cluster.Vttablet, variable string, status string) { + tabletParams := getMysqlConnParam(tablet) + conn, err := mysql.Connect(ctx, &tabletParams) + require.Nil(t, err) + defer conn.Close() + + qr := execute(t, conn, fmt.Sprintf("show variables like '%s'", variable)) + got := fmt.Sprintf("%v", qr.Rows) + want := fmt.Sprintf("[[VARCHAR(\"%s\") VARCHAR(\"%s\")]]", variable, status) + assert.Equal(t, want, got) +} + +func checkDBstatus(ctx context.Context, t *testing.T, tablet *cluster.Vttablet, variable string, status string) { + tabletParams := getMysqlConnParam(tablet) + conn, err := mysql.Connect(ctx, &tabletParams) + require.Nil(t, err) + defer conn.Close() + + qr := execute(t, conn, fmt.Sprintf("show status like '%s'", variable)) + got := fmt.Sprintf("%v", qr.Rows) + want := fmt.Sprintf("[[VARCHAR(\"%s\") VARCHAR(\"%s\")]]", variable, status) + assert.Equal(t, want, got) +} + +func checkSlaveStatus(ctx context.Context, t *testing.T, tablet *cluster.Vttablet) { + qr := runSQL(ctx, t, "show slave status", tablet) + SlaveIORunning := fmt.Sprintf("%v", qr.Rows[0][10]) // Slave_IO_Running + SlaveSQLRunning := fmt.Sprintf("%v", qr.Rows[0][10]) // Slave_SQL_Running + assert.Equal(t, SlaveIORunning, "VARCHAR(\"No\")") + assert.Equal(t, SlaveSQLRunning, "VARCHAR(\"No\")") +} + +// Makes sure the tablet type is master, and its health check agrees. +func checkMasterTablet(t *testing.T, tablet *cluster.Vttablet) { + result, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("GetTablet", tablet.Alias) + require.Nil(t, err) + var tabletInfo topodatapb.Tablet + err = json2.Unmarshal([]byte(result), &tabletInfo) + require.Nil(t, err) + assert.Equal(t, topodatapb.TabletType_MASTER, tabletInfo.GetType()) + + // make sure the health stream is updated + result, err = clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("VtTabletStreamHealth", "-count", "1", tablet.Alias) + require.Nil(t, err) + var streamHealthResponse querypb.StreamHealthResponse + + err = json2.Unmarshal([]byte(result), &streamHealthResponse) + require.Nil(t, err) + + assert.True(t, streamHealthResponse.GetServing()) + tabletType := streamHealthResponse.GetTarget().GetTabletType() + assert.Equal(t, topodatapb.TabletType_MASTER, tabletType) + +} + +func checkInsertedValues(ctx context.Context, t *testing.T, tablet *cluster.Vttablet, index int) error { + // wait until it gets the data + timeout := time.Now().Add(10 * time.Second) + for time.Now().Before(timeout) { + selectSQL := fmt.Sprintf("select msg from vt_insert_test where id=%d", index) + qr := runSQL(ctx, t, selectSQL, tablet) + if len(qr.Rows) == 1 { + return nil + } + time.Sleep(300 * time.Millisecond) + } + return fmt.Errorf("data is not yet replicated") +} + +func validateTopology(t *testing.T, pingTablets bool) { + if pingTablets { + err := clusterInstance.VtctlclientProcess.ExecuteCommand("Validate", "-ping-tablets=true") + require.Nil(t, err) + } else { + err := clusterInstance.VtctlclientProcess.ExecuteCommand("Validate") + require.Nil(t, err) + } +} + +func killTablets(t *testing.T) { + for _, tablet := range []cluster.Vttablet{*tablet62344, *tablet62044, *tablet41983, *tablet31981} { + fmt.Println("Teardown tablet: ", tablet.Alias) + err := tablet.VttabletProcess.TearDown() + require.Nil(t, err) + + // Reset status and type + tablet.VttabletProcess.ServingStatus = "" + tablet.Type = "replica" + } +} diff --git a/go/test/endtoend/sharded/sharded_keyspace_test.go b/go/test/endtoend/sharded/sharded_keyspace_test.go new file mode 100644 index 00000000000..7b89dc2bf47 --- /dev/null +++ b/go/test/endtoend/sharded/sharded_keyspace_test.go @@ -0,0 +1,265 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package sharded + +import ( + "flag" + "fmt" + "os" + "os/exec" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/vt/log" + + "vitess.io/vitess/go/test/endtoend/cluster" +) + +var ( + clusterInstance *cluster.LocalProcessCluster + hostname = "localhost" + keyspaceName = "ks" + cell = "zone1" + sqlSchema = ` + create table vt_select_test ( + id bigint not null, + msg varchar(64), + primary key (id) + ) Engine=InnoDB + ` + sqlSchemaReverse = ` + create table vt_select_test ( + msg varchar(64), + id bigint not null, + primary key (id) + ) Engine=InnoDB + ` + vSchema = ` + { + "sharded": true, + "vindexes": { + "hash_index": { + "type": "hash" + } + }, + "tables": { + "vt_select_test": { + "column_vindexes": [ + { + "column": "id", + "name": "hash_index" + } + ] + } + } + } + ` +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitcode, err := func() (int, error) { + clusterInstance = cluster.NewCluster(cell, hostname) + defer clusterInstance.Teardown() + + // Start topo server + if err := clusterInstance.StartTopo(); err != nil { + return 1, err + } + if err := clusterInstance.VtctlProcess.CreateKeyspace(keyspaceName); err != nil { + return 1, err + } + + initCluster([]string{"-80", "80-"}, 2) + + return m.Run(), nil + }() + if err != nil { + fmt.Printf("%v\n", err) + os.Exit(1) + } else { + os.Exit(exitcode) + } + +} + +func TestShardedKeyspace(t *testing.T) { + defer cluster.PanicHandler(t) + shard1 := clusterInstance.Keyspaces[0].Shards[0] + shard2 := clusterInstance.Keyspaces[0].Shards[1] + + shard1Master := shard1.Vttablets[0] + shard2Master := shard2.Vttablets[0] + + // apply the schema on the first shard through vtctl, so all tablets + // are the same. + _, err := shard1Master.VttabletProcess.QueryTablet(sqlSchema, keyspaceName, true) + require.Nil(t, err) + _, err = shard1.Vttablets[1].VttabletProcess.QueryTablet(sqlSchema, keyspaceName, true) + require.Nil(t, err) + + //apply the schema on the second shard. + _, err = shard2Master.VttabletProcess.QueryTablet(sqlSchemaReverse, keyspaceName, true) + require.Nil(t, err) + _, err = shard2.Vttablets[1].VttabletProcess.QueryTablet(sqlSchemaReverse, keyspaceName, true) + require.Nil(t, err) + + if err = clusterInstance.VtctlclientProcess.ApplyVSchema(keyspaceName, vSchema); err != nil { + log.Error(err.Error()) + return + } + + reloadSchemas(t, + shard1Master.Alias, + shard1.Vttablets[1].Alias, + shard2Master.Alias, + shard2.Vttablets[1].Alias) + + err = clusterInstance.VtctlclientProcess.InitShardMaster(keyspaceName, shard1.Name, cell, shard1Master.TabletUID) + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.InitShardMaster(keyspaceName, shard2.Name, cell, shard2Master.TabletUID) + require.Nil(t, err) + + _ = clusterInstance.VtctlclientProcess.ExecuteCommand("SetReadWrite", shard1Master.Alias) + _ = clusterInstance.VtctlclientProcess.ExecuteCommand("SetReadWrite", shard2Master.Alias) + + _, _ = shard1Master.VttabletProcess.QueryTablet("insert into vt_select_test (id, msg) values (1, 'test 1')", keyspaceName, true) + _, _ = shard2Master.VttabletProcess.QueryTablet("insert into vt_select_test (id, msg) values (10, 'test 10')", keyspaceName, true) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("Validate", "-ping-tablets") + require.Nil(t, err) + + rows, err := shard1Master.VttabletProcess.QueryTablet("select id, msg from vt_select_test order by id", keyspaceName, true) + require.Nil(t, err) + assert.Equal(t, `[[INT64(1) VARCHAR("test 1")]]`, fmt.Sprintf("%v", rows.Rows)) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ValidateSchemaShard", fmt.Sprintf("%s/%s", keyspaceName, shard1.Name)) + require.Nil(t, err) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ValidateSchemaShard", fmt.Sprintf("%s/%s", keyspaceName, shard1.Name)) + require.Nil(t, err) + + output, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("ValidateSchemaKeyspace", keyspaceName) + require.Error(t, err) + assert.True(t, strings.Contains(output, "schemas differ on table vt_select_test:\n"+shard1Master.Alias+": CREATE TABLE")) + fmt.Println(output) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ValidateVersionShard", fmt.Sprintf("%s/%s", keyspaceName, shard1.Name)) + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("GetPermissions", shard1.Vttablets[1].Alias) + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ValidatePermissionsShard", fmt.Sprintf("%s/%s", keyspaceName, shard1.Name)) + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ValidatePermissionsKeyspace", keyspaceName) + require.Nil(t, err) + + rows, err = shard1Master.VttabletProcess.QueryTablet("select id, msg from vt_select_test order by id", keyspaceName, true) + require.Nil(t, err) + assert.Equal(t, `[[INT64(1) VARCHAR("test 1")]]`, fmt.Sprintf("%v", rows.Rows)) + + rows, err = shard2Master.VttabletProcess.QueryTablet("select id, msg from vt_select_test order by id", keyspaceName, true) + require.Nil(t, err) + assert.Equal(t, `[[INT64(10) VARCHAR("test 10")]]`, fmt.Sprintf("%v", rows.Rows)) +} + +func reloadSchemas(t *testing.T, aliases ...string) { + for _, alias := range aliases { + if err := clusterInstance.VtctlclientProcess.ExecuteCommand("ReloadSchema", alias); err != nil { + assert.Fail(t, "Unable to reload schema") + } + + } +} + +func initCluster(shardNames []string, totalTabletsRequired int) { + keyspace := cluster.Keyspace{ + Name: keyspaceName, + } + for _, shardName := range shardNames { + shard := &cluster.Shard{ + Name: shardName, + } + + var mysqlCtlProcessList []*exec.Cmd + + for i := 0; i < totalTabletsRequired; i++ { + // instantiate vttablet object with reserved ports + tabletUID := clusterInstance.GetAndReserveTabletUID() + tablet := &cluster.Vttablet{ + TabletUID: tabletUID, + HTTPPort: clusterInstance.GetAndReservePort(), + GrpcPort: clusterInstance.GetAndReservePort(), + MySQLPort: clusterInstance.GetAndReservePort(), + Alias: fmt.Sprintf("%s-%010d", clusterInstance.Cell, tabletUID), + } + if i == 0 { // Make the first one as master + tablet.Type = "master" + } + // Start Mysqlctl process + tablet.MysqlctlProcess = *cluster.MysqlCtlProcessInstance(tablet.TabletUID, tablet.MySQLPort, clusterInstance.TmpDirectory) + if proc, err := tablet.MysqlctlProcess.StartProcess(); err != nil { + return + } else { + mysqlCtlProcessList = append(mysqlCtlProcessList, proc) + } + + // start vttablet process + tablet.VttabletProcess = cluster.VttabletProcessInstance(tablet.HTTPPort, + tablet.GrpcPort, + tablet.TabletUID, + clusterInstance.Cell, + shardName, + keyspaceName, + clusterInstance.VtctldProcess.Port, + tablet.Type, + clusterInstance.TopoProcess.Port, + clusterInstance.Hostname, + clusterInstance.TmpDirectory, + clusterInstance.VtTabletExtraArgs, + clusterInstance.EnableSemiSync) + tablet.Alias = tablet.VttabletProcess.TabletPath + + shard.Vttablets = append(shard.Vttablets, tablet) + } + for _, proc := range mysqlCtlProcessList { + if err := proc.Wait(); err != nil { + return + } + } + + for _, tablet := range shard.Vttablets { + if _, err := tablet.VttabletProcess.QueryTablet(fmt.Sprintf("create database vt_%s", keyspace.Name), keyspace.Name, false); err != nil { + log.Error(err.Error()) + return + } + + log.Info(fmt.Sprintf("Starting vttablet for tablet uid %d, grpc port %d", tablet.TabletUID, tablet.GrpcPort)) + + if err := tablet.VttabletProcess.Setup(); err != nil { + log.Error(err.Error()) + return + } + } + + keyspace.Shards = append(keyspace.Shards, *shard) + } + clusterInstance.Keyspaces = append(clusterInstance.Keyspaces, keyspace) +} diff --git a/go/test/endtoend/sharding/base_sharding.go b/go/test/endtoend/sharding/base_sharding.go new file mode 100644 index 00000000000..d3d01a6c30b --- /dev/null +++ b/go/test/endtoend/sharding/base_sharding.go @@ -0,0 +1,532 @@ +/* +Copyright 2019 The Vitess Authors. + +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. + +*/ + +package sharding + +import ( + "fmt" + "io/ioutil" + "math" + "net/http" + "reflect" + "strconv" + "strings" + "testing" + "time" + + "vitess.io/vitess/go/json2" + "vitess.io/vitess/go/test/endtoend/cluster" + querypb "vitess.io/vitess/go/vt/proto/query" + "vitess.io/vitess/go/vt/proto/topodata" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +var ( + lotRange1 uint64 = 0xA000000000000000 + lotRange2 uint64 = 0xE000000000000000 + // InsertTabletTemplateKsID common insert format to be used for different tests + InsertTabletTemplateKsID = `insert into %s (id, msg) values (%d, '%s') /* id:%d */` +) + +// CheckSrvKeyspace verifies the schema with expectedPartition +func CheckSrvKeyspace(t *testing.T, cell string, ksname string, shardingCol string, colType topodata.KeyspaceIdType, expectedPartition map[topodata.TabletType][]string, ci cluster.LocalProcessCluster) { + srvKeyspace := GetSrvKeyspace(t, cell, ksname, ci) + if shardingCol != "" { + assert.Equal(t, srvKeyspace.ShardingColumnName, shardingCol) + } + if colType != 0 { + assert.Equal(t, srvKeyspace.ShardingColumnType, colType) + } + + currentPartition := map[topodata.TabletType][]string{} + + for _, partition := range srvKeyspace.Partitions { + currentPartition[partition.ServedType] = []string{} + for _, shardRef := range partition.ShardReferences { + currentPartition[partition.ServedType] = append(currentPartition[partition.ServedType], shardRef.Name) + } + } + + assert.True(t, reflect.DeepEqual(currentPartition, expectedPartition)) +} + +// GetSrvKeyspace return the Srv Keyspace structure +func GetSrvKeyspace(t *testing.T, cell string, ksname string, ci cluster.LocalProcessCluster) *topodata.SrvKeyspace { + output, err := ci.VtctlclientProcess.ExecuteCommandWithOutput("GetSrvKeyspace", cell, ksname) + require.Nil(t, err) + var srvKeyspace topodata.SrvKeyspace + + err = json2.Unmarshal([]byte(output), &srvKeyspace) + require.Nil(t, err) + return &srvKeyspace +} + +// VerifyTabletHealth checks that the tablet URL is reachable. +func VerifyTabletHealth(t *testing.T, vttablet cluster.Vttablet, hostname string) { + tabletURL := fmt.Sprintf("http://%s:%d/healthz", hostname, vttablet.HTTPPort) + resp, err := http.Get(tabletURL) + require.Nil(t, err) + assert.Equal(t, resp.StatusCode, 200) +} + +// VerifyReconciliationCounters checks that the reconciliation Counters have the expected values. +func VerifyReconciliationCounters(t *testing.T, vtworkerURL string, availabilityType string, table string, + inserts int, updates int, deletes int, equals int) { + resp, err := http.Get(vtworkerURL) + require.Nil(t, err) + assert.Equal(t, resp.StatusCode, 200) + + resultMap := make(map[string]interface{}) + respByte, _ := ioutil.ReadAll(resp.Body) + err = json2.Unmarshal(respByte, &resultMap) + require.Nil(t, err) + + value := getValueFromJSON(resultMap, "Worker"+availabilityType+"InsertsCounters", table) + if inserts == 0 { + assert.Equal(t, value, "") + } else { + assert.Equal(t, value, fmt.Sprintf("%d", inserts)) + } + + value = getValueFromJSON(resultMap, "Worker"+availabilityType+"UpdatesCounters", table) + if updates == 0 { + assert.Equal(t, value, "") + } else { + assert.Equal(t, value, fmt.Sprintf("%d", updates)) + } + + value = getValueFromJSON(resultMap, "Worker"+availabilityType+"DeletesCounters", table) + if deletes == 0 { + assert.Equal(t, value, "") + } else { + assert.Equal(t, value, fmt.Sprintf("%d", deletes)) + } + + value = getValueFromJSON(resultMap, "Worker"+availabilityType+"EqualRowsCounters", table) + if equals == 0 { + assert.Equal(t, value, "") + } else { + assert.Equal(t, value, fmt.Sprintf("%d", equals)) + } +} + +func getValueFromJSON(jsonMap map[string]interface{}, keyname string, tableName string) string { + object := reflect.ValueOf(jsonMap[keyname]) + if object.Kind() == reflect.Map { + for _, key := range object.MapKeys() { + if key.String() == tableName { + return fmt.Sprintf("%v", object.MapIndex(key)) + } + } + } + return "" +} + +// CheckValues check value from sql query to table with expected values +func CheckValues(t *testing.T, vttablet cluster.Vttablet, id uint64, msg string, exists bool, tableName string, ks string, keyType querypb.Type) bool { + query := fmt.Sprintf("select id, msg from %s where id = %d", tableName, id) + if keyType == querypb.Type_VARBINARY { + query = fmt.Sprintf("select id, msg from %s where id = '%d'", tableName, id) + } + + result, err := vttablet.VttabletProcess.QueryTablet(query, ks, true) + require.Nil(t, err) + isFound := false + if exists && len(result.Rows) > 0 { + if keyType == querypb.Type_VARBINARY { + isFound = assert.Equal(t, fmt.Sprintf("%v", result.Rows), fmt.Sprintf(`[[VARBINARY("%d") VARCHAR("%s")]]`, id, msg)) + } else { + isFound = assert.Equal(t, fmt.Sprintf("%v", result.Rows), fmt.Sprintf(`[[UINT64(%d) VARCHAR("%s")]]`, id, msg)) + } + + } else { + assert.Equal(t, len(result.Rows), 0) + } + return isFound +} + +// CheckDestinationMaster performs multiple checks on a destination master. +func CheckDestinationMaster(t *testing.T, vttablet cluster.Vttablet, sourceShards []string, ci cluster.LocalProcessCluster) { + _ = vttablet.VttabletProcess.WaitForBinLogPlayerCount(len(sourceShards)) + CheckBinlogPlayerVars(t, vttablet, sourceShards, 0) + checkStreamHealthEqualsBinlogPlayerVars(t, vttablet, len(sourceShards), ci) +} + +// CheckBinlogPlayerVars Checks the binlog player variables are correctly exported. +func CheckBinlogPlayerVars(t *testing.T, vttablet cluster.Vttablet, sourceShards []string, secondBehindMaster int64) { + tabletVars := vttablet.VttabletProcess.GetVars() + + assert.Contains(t, tabletVars, "VReplicationStreamCount") + assert.Contains(t, tabletVars, "VReplicationSecondsBehindMasterMax") + assert.Contains(t, tabletVars, "VReplicationSecondsBehindMaster") + assert.Contains(t, tabletVars, "VReplicationSource") + assert.Contains(t, tabletVars, "VReplicationSourceTablet") + + streamCountStr := fmt.Sprintf("%v", reflect.ValueOf(tabletVars["VReplicationStreamCount"])) + streamCount, _ := strconv.Atoi(streamCountStr) + assert.Equal(t, streamCount, len(sourceShards)) + + replicationSourceObj := reflect.ValueOf(tabletVars["VReplicationSource"]) + replicationSourceValue := []string{} + + assert.Equal(t, len(replicationSourceObj.MapKeys()), len(reflect.ValueOf(tabletVars["VReplicationSourceTablet"]).MapKeys())) + + for _, key := range replicationSourceObj.MapKeys() { + replicationSourceValue = append(replicationSourceValue, + fmt.Sprintf("%v", replicationSourceObj.MapIndex(key))) + } + + for _, shard := range sourceShards { + assert.Containsf(t, replicationSourceValue, shard, "Source shard is not matched with vReplication shard value") + } + + if secondBehindMaster != 0 { + secondBehindMaserMaxStr := fmt.Sprintf("%v", reflect.ValueOf(tabletVars["VReplicationSecondsBehindMasterMax"])) + secondBehindMaserMax, _ := strconv.ParseFloat(secondBehindMaserMaxStr, 64) + + assert.True(t, secondBehindMaserMax < float64(secondBehindMaster)) + + replicationSecondBehindMasterObj := reflect.ValueOf(tabletVars["VReplicationSecondsBehindMaster"]) + for _, key := range replicationSourceObj.MapKeys() { + str := fmt.Sprintf("%v", replicationSecondBehindMasterObj.MapIndex(key)) + flt, _ := strconv.ParseFloat(str, 64) + assert.True(t, flt < float64(secondBehindMaster)) + } + } +} + +// checkStreamHealthEqualsBinlogPlayerVars - Checks the variables exported by streaming health check match vars. +func checkStreamHealthEqualsBinlogPlayerVars(t *testing.T, vttablet cluster.Vttablet, count int, ci cluster.LocalProcessCluster) { + tabletVars := vttablet.VttabletProcess.GetVars() + + streamCountStr := fmt.Sprintf("%v", reflect.ValueOf(tabletVars["VReplicationStreamCount"])) + streamCount, _ := strconv.Atoi(streamCountStr) + + secondBehindMaserMaxStr := fmt.Sprintf("%v", reflect.ValueOf(tabletVars["VReplicationSecondsBehindMasterMax"])) + secondBehindMaserMax, _ := strconv.ParseFloat(secondBehindMaserMaxStr, 64) + + assert.Equal(t, streamCount, count) + // Enforce health check because it's not running by default as + // tablets may not be started with it, or may not run it in time. + _ = ci.VtctlclientProcess.ExecuteCommand("RunHealthCheck", vttablet.Alias) + streamHealth, err := ci.VtctlclientProcess.ExecuteCommandWithOutput("VtTabletStreamHealth", "-count", "1", vttablet.Alias) + require.Nil(t, err) + + var streamHealthResponse querypb.StreamHealthResponse + err = json2.Unmarshal([]byte(streamHealth), &streamHealthResponse) + require.Nil(t, err, "error should be Nil") + assert.Equal(t, streamHealthResponse.Serving, false) + assert.NotNil(t, streamHealthResponse.RealtimeStats) + assert.Equal(t, streamHealthResponse.RealtimeStats.HealthError, "") + assert.NotNil(t, streamHealthResponse.RealtimeStats.BinlogPlayersCount) + + assert.Equal(t, streamCount, int(streamHealthResponse.RealtimeStats.BinlogPlayersCount)) + assert.Equal(t, secondBehindMaserMax, float64(streamHealthResponse.RealtimeStats.SecondsBehindMasterFilteredReplication)) +} + +// CheckBinlogServerVars checks the binlog server variables are correctly exported. +func CheckBinlogServerVars(t *testing.T, vttablet cluster.Vttablet, minStatement int, minTxn int, isVerticalSplit bool) { + resultMap := vttablet.VttabletProcess.GetVars() + skey := "UpdateStreamKeyRangeStatements" + tkey := "UpdateStreamKeyRangeTransactions" + if isVerticalSplit { + skey = "UpdateStreamTablesStatements" + tkey = "UpdateStreamTablesTransactions" + } + assert.Contains(t, resultMap, skey) + assert.Contains(t, resultMap, tkey) + if minStatement > 0 { + value := fmt.Sprintf("%v", reflect.ValueOf(resultMap[skey])) + iValue, _ := strconv.Atoi(value) + assert.True(t, iValue >= minStatement, fmt.Sprintf("only got %d < %d statements", iValue, minStatement)) + } + if minTxn > 0 { + value := fmt.Sprintf("%v", reflect.ValueOf(resultMap[tkey])) + iValue, _ := strconv.Atoi(value) + assert.True(t, iValue >= minTxn, fmt.Sprintf("only got %d < %d transactions", iValue, minTxn)) + } +} + +// InsertLots inserts multiple values to vttablet +func InsertLots(t *testing.T, count uint64, vttablet cluster.Vttablet, table string, ks string) { + var query1, query2 string + var i uint64 + for i = 0; i < count; i++ { + query1 = fmt.Sprintf(InsertTabletTemplateKsID, table, lotRange1+i, fmt.Sprintf("msg-range1-%d", 10000+i), lotRange1+i) + query2 = fmt.Sprintf(InsertTabletTemplateKsID, table, lotRange2+i, fmt.Sprintf("msg-range2-%d", 20000+i), lotRange2+i) + + InsertToTablet(t, query1, vttablet, ks, false) + InsertToTablet(t, query2, vttablet, ks, false) + } +} + +// InsertToTablet inserts a single row to vttablet +func InsertToTablet(t *testing.T, query string, vttablet cluster.Vttablet, ks string, expectFail bool) { + _, _ = vttablet.VttabletProcess.QueryTablet("begin", ks, true) + _, err := vttablet.VttabletProcess.QueryTablet(query, ks, true) + if expectFail { + require.Error(t, err) + } else { + require.Nil(t, err) + } + _, _ = vttablet.VttabletProcess.QueryTablet("commit", ks, true) +} + +// InsertMultiValues inserts a multiple values to vttablet +func InsertMultiValues(t *testing.T, tablet cluster.Vttablet, keyspaceName string, tableName string, + fixedParentID int, ids []int, msgs []string, ksIDs []uint64) { + queryStr := fmt.Sprintf("insert into %s (parent_id, id, msg, custom_ksid_col) values", tableName) + valueSQL := "" + keyspaceIds := "" + valueIds := "" + for i := range ids { + valueSQL += fmt.Sprintf(`(%d, %d, "%s", %d)`, fixedParentID, ids[i], msgs[i], ksIDs[i]) + keyspaceIds += fmt.Sprintf("%d", ksIDs[i]) + valueIds += fmt.Sprintf("%d", ids[i]) + if i < len(ids)-1 { + valueSQL += "," + keyspaceIds += "," + valueIds += "," + } + } + + queryStr += valueSQL + queryStr += fmt.Sprintf(" /* vtgate:: keyspace_id:%s */", keyspaceIds) + queryStr += fmt.Sprintf(" /* id:%s */", valueIds) + InsertToTablet(t, queryStr, tablet, keyspaceName, false) +} + +// CheckLotsTimeout waits till all values are inserted +func CheckLotsTimeout(t *testing.T, vttablet cluster.Vttablet, count uint64, table string, ks string, keyType querypb.Type, pctFound int) bool { + timeout := time.Now().Add(10 * time.Second) + var percentFound float64 + for time.Now().Before(timeout) { + percentFound = checkLots(t, vttablet, count, table, ks, keyType) + if int(math.Round(percentFound)) == pctFound { + return true + } + time.Sleep(300 * time.Millisecond) + } + println(fmt.Sprintf("expected pct %d, got pct %f", pctFound, percentFound)) + return false +} + +// CheckLotsNotPresent verifies that no rows should be present in vttablet +func CheckLotsNotPresent(t *testing.T, vttablet cluster.Vttablet, count uint64, table string, ks string, keyType querypb.Type) { + var i uint64 + for i = 0; i < count; i++ { + assert.False(t, CheckValues(t, vttablet, + lotRange1+i, fmt.Sprintf("msg-range1-%d", 10000+i), true, table, ks, keyType)) + + assert.False(t, CheckValues(t, vttablet, + lotRange2+i, fmt.Sprintf("msg-range2-%d", 20000+i), true, table, ks, keyType)) + } +} + +func checkLots(t *testing.T, vttablet cluster.Vttablet, count uint64, table string, ks string, keyType querypb.Type) float64 { + var isFound bool + var totalFound int + var i uint64 + + for i = 0; i < count; i++ { + isFound = CheckValues(t, vttablet, + lotRange1+i, fmt.Sprintf("msg-range1-%d", 10000+i), true, table, ks, keyType) + if isFound { + totalFound++ + } + + isFound = CheckValues(t, vttablet, + lotRange2+i, fmt.Sprintf("msg-range2-%d", 20000+i), true, table, ks, keyType) + if isFound { + totalFound++ + } + } + println(fmt.Sprintf("Total found %d", totalFound)) + return float64(float64(totalFound) * 100 / float64(count) / 2) +} + +// CheckRunningBinlogPlayer Checks binlog player is running and showing in status +func CheckRunningBinlogPlayer(t *testing.T, vttablet cluster.Vttablet, numberOfQueries int, numberOfTxns int) { + status := vttablet.VttabletProcess.GetStatus() + assert.Contains(t, status, "VReplication state: Open") + assert.Contains(t, status, fmt.Sprintf("All: %d
Query: %d
Transaction: %d
", numberOfQueries+numberOfTxns, numberOfQueries, numberOfTxns)) + assert.Contains(t, status, "") +} + +// CheckTabletQueryServices check that the query service is enabled or disabled on the specified tablets. +func CheckTabletQueryServices(t *testing.T, vttablets []cluster.Vttablet, expectedStatus string, tabletControlEnabled bool, ci cluster.LocalProcessCluster) { + for _, tablet := range vttablets { + CheckTabletQueryService(t, tablet, expectedStatus, tabletControlEnabled, ci) + } +} + +// CheckTabletQueryService check that the query service is enabled or disabled on the tablet +func CheckTabletQueryService(t *testing.T, vttablet cluster.Vttablet, expectedStatus string, tabletControlEnabled bool, ci cluster.LocalProcessCluster) { + tabletStatus := vttablet.VttabletProcess.GetTabletStatus() + assert.Equal(t, tabletStatus, expectedStatus) + + queryServiceDisabled := "Query Service disabled: TabletControl.DisableQueryService set" + status := vttablet.VttabletProcess.GetStatus() + if tabletControlEnabled { + assert.Contains(t, status, queryServiceDisabled) + } else { + assert.NotContains(t, status, queryServiceDisabled) + } + + if vttablet.Type == "rdonly" { + // Run RunHealthCheck to be sure the tablet doesn't change its serving state. + _ = ci.VtctlclientProcess.ExecuteCommand("RunHealthCheck", vttablet.Alias) + tabletStatus = vttablet.VttabletProcess.GetTabletStatus() + assert.Equal(t, tabletStatus, expectedStatus) + } +} + +// CheckShardQueryServices checks DisableQueryService for all shards +func CheckShardQueryServices(t *testing.T, ci cluster.LocalProcessCluster, shards []cluster.Shard, cell string, + keyspaceName string, tabletType topodata.TabletType, expectedState bool) { + for _, shard := range shards { + CheckShardQueryService(t, ci, cell, keyspaceName, shard.Name, tabletType, expectedState) + } +} + +// CheckShardQueryService checks DisableQueryService in the shard record's TabletControlMap. +func CheckShardQueryService(t *testing.T, ci cluster.LocalProcessCluster, cell string, keyspaceName string, + shardName string, tabletType topodata.TabletType, expectedState bool) { + // We assume that query service should be enabled unless + // DisableQueryService is explicitly True + queryServiceEnabled := true + srvKeyspace := GetSrvKeyspace(t, cell, keyspaceName, ci) + for _, partition := range srvKeyspace.Partitions { + tType := partition.GetServedType() + if tabletType != tType { + continue + } + for _, shardTabletControl := range partition.GetShardTabletControls() { + if shardTabletControl.GetName() == shardName { + if shardTabletControl.GetQueryServiceDisabled() { + queryServiceEnabled = false + } + } + } + } + + assert.True(t, queryServiceEnabled == expectedState, + fmt.Sprintf("shard %s does not have the correct query service state: got %t but expected %t", + shardName, queryServiceEnabled, expectedState)) + +} + +// GetShardInfo return the Shard information +func GetShardInfo(t *testing.T, shard1Ks string, ci cluster.LocalProcessCluster) *topodata.Shard { + output, err := ci.VtctlclientProcess.ExecuteCommandWithOutput("GetShard", shard1Ks) + require.Nil(t, err) + var shard topodata.Shard + err = json2.Unmarshal([]byte(output), &shard) + require.Nil(t, err) + return &shard +} + +// checkThrottlerServiceMaxRates Checks the vtctl ThrottlerMaxRates and ThrottlerSetRate commands. +func checkThrottlerServiceMaxRates(t *testing.T, server string, names []string, rate int, ci cluster.LocalProcessCluster) { + // Avoid flakes by waiting for all throttlers. (Necessary because filtered + // replication on vttablet will register the throttler asynchronously.) + var output string + var err error + startTime := time.Now() + msg := fmt.Sprintf("%d active throttler(s)", len(names)) + for { + output, err = ci.VtctlclientProcess.ExecuteCommandWithOutput("ThrottlerMaxRates", "--server", server) + require.Nil(t, err) + if strings.Contains(output, msg) || (time.Now().After(startTime.Add(2 * time.Minute))) { + break + } + time.Sleep(2 * time.Second) + } + assert.Contains(t, output, msg) + + for _, name := range names { + str := fmt.Sprintf("| %s | %d |", name, rate) + assert.Contains(t, output, str) + } + + // Check that it's possible to change the max rate on the throttler. + newRate := "unlimited" + output, err = ci.VtctlclientProcess.ExecuteCommandWithOutput("ThrottlerSetMaxRate", "--server", server, newRate) + require.Nil(t, err) + assert.Contains(t, output, msg) + + output, err = ci.VtctlclientProcess.ExecuteCommandWithOutput("ThrottlerMaxRates", "--server", server) + require.Nil(t, err) + for _, name := range names { + str := fmt.Sprintf("| %s | %s |", name, newRate) + assert.Contains(t, output, str) + } + assert.Contains(t, output, msg) +} + +// checkThrottlerServiceConfiguration checks the vtctl (Get|Update|Reset)ThrottlerConfiguration commands. +func checkThrottlerServiceConfiguration(t *testing.T, server string, names []string, ci cluster.LocalProcessCluster) { + output, err := ci.VtctlclientProcess.ExecuteCommandWithOutput( + "UpdateThrottlerConfiguration", "--server", server, + "--copy_zero_values", + "target_replication_lag_sec:12345 "+ + "max_replication_lag_sec:65789 "+ + "initial_rate:3 max_increase:0.4 "+ + "emergency_decrease:0.5 "+ + "min_duration_between_increases_sec:6 "+ + "max_duration_between_increases_sec:7 "+ + "min_duration_between_decreases_sec:8 "+ + "spread_backlog_across_sec:9 "+ + "ignore_n_slowest_replicas:0 "+ + "ignore_n_slowest_rdonlys:0 "+ + "age_bad_rate_after_sec:12 "+ + "bad_rate_increase:0.13 "+ + "max_rate_approach_threshold: 0.9 ", + ) + require.Nil(t, err) + msg := fmt.Sprintf("%d active throttler(s)", len(names)) + assert.Contains(t, output, msg) + + output, err = ci.VtctlclientProcess.ExecuteCommandWithOutput("GetThrottlerConfiguration", "--server", server) + require.Nil(t, err) + for _, name := range names { + str := fmt.Sprintf("| %s | target_replication_lag_sec:12345 ", name) + assert.Contains(t, output, str) + assert.NotContains(t, output, "ignore_n_slowest_replicas") + } + assert.Contains(t, output, msg) + + // Reset clears our configuration values. + output, err = ci.VtctlclientProcess.ExecuteCommandWithOutput("ResetThrottlerConfiguration", "--server", server) + require.Nil(t, err) + assert.Contains(t, output, msg) + + // Check that the reset configuration no longer has our values. + output, err = ci.VtctlclientProcess.ExecuteCommandWithOutput("GetThrottlerConfiguration", "--server", server) + require.Nil(t, err) + assert.NotContains(t, output, "target_replication_lag_sec:12345") + assert.Contains(t, output, msg) + +} + +// CheckThrottlerService runs checkThrottlerServiceMaxRates and checkThrottlerServiceConfigs +func CheckThrottlerService(t *testing.T, server string, names []string, rate int, ci cluster.LocalProcessCluster) { + checkThrottlerServiceMaxRates(t, server, names, rate, ci) + checkThrottlerServiceConfiguration(t, server, names, ci) +} diff --git a/go/test/endtoend/sharding/initialsharding/bytes/initial_sharding_bytes_test.go b/go/test/endtoend/sharding/initialsharding/bytes/initial_sharding_bytes_test.go new file mode 100644 index 00000000000..72794e88810 --- /dev/null +++ b/go/test/endtoend/sharding/initialsharding/bytes/initial_sharding_bytes_test.go @@ -0,0 +1,38 @@ +/* +Copyright 2019 The Vitess Authors. + +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. + + +"""Re-runs initial_sharding_test.go with a varbinary keyspace_id.""" +*/ + +package bytes + +import ( + "testing" + + "vitess.io/vitess/go/test/endtoend/cluster" + sharding "vitess.io/vitess/go/test/endtoend/sharding/initialsharding" + querypb "vitess.io/vitess/go/vt/proto/query" +) + +func TestInitialShardingBytes(t *testing.T) { + defer cluster.PanicHandler(t) + code, err := sharding.ClusterWrapper(false) + if err != nil { + t.Errorf("setup failed with status code %d", code) + } + sharding.TestInitialSharding(t, &sharding.ClusterInstance.Keyspaces[0], querypb.Type_VARBINARY, false, false) + defer sharding.ClusterInstance.Teardown() +} diff --git a/go/test/endtoend/sharding/initialsharding/multi/initial_sharding_multi_test.go b/go/test/endtoend/sharding/initialsharding/multi/initial_sharding_multi_test.go new file mode 100644 index 00000000000..cab8b3fa36d --- /dev/null +++ b/go/test/endtoend/sharding/initialsharding/multi/initial_sharding_multi_test.go @@ -0,0 +1,64 @@ +/* +Copyright 2019 The Vitess Authors. + +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 test simulates the first time a database has to be split +in a multi-vttablet-single-mysql environment + +We have 2 keyspaces. One keyspace is in managing mode. It's vttablets +own the MySQL instances and can reparent, start/stop server, start/stop +replication etc. Other keyspace is in non-managing mode and cannot do +any of these actions. Only TabletExternallyReparented is allowed, but +resharding should still work. + +For each keyspace: +- we start with a keyspace with a single shard and a single table +- we add and populate the sharding key +- we set the sharding key in the topology +- we clone into 2 instances +- we enable filtered replication +- we move all serving types +- we remove the source tablets +- we remove the original shard + +*/ + +package multi + +import ( + "testing" + + "vitess.io/vitess/go/test/endtoend/cluster" + sharding "vitess.io/vitess/go/test/endtoend/sharding/initialsharding" + querypb "vitess.io/vitess/go/vt/proto/query" +) + +func TestInitialShardingMulti(t *testing.T) { + defer cluster.PanicHandler(t) + code, err := sharding.ClusterWrapper(true) + if err != nil { + t.Errorf("setup failed with status code %d", code) + } + sharding.AssignMysqlPortFromKs1ToKs2() + sharding.TestInitialSharding(t, &sharding.ClusterInstance.Keyspaces[0], querypb.Type_UINT64, true, false) + println("-----------------------------") + println("Done with 1st keyspace test") + println("-----------------------------") + sharding.TestInitialSharding(t, &sharding.ClusterInstance.Keyspaces[1], querypb.Type_UINT64, true, true) + println("----------Done with 2nd keyspace test----------") + sharding.KillVtgateInstances() + sharding.KillTabletsInKeyspace(&sharding.ClusterInstance.Keyspaces[0]) + sharding.KillTabletsInKeyspace(&sharding.ClusterInstance.Keyspaces[1]) + defer sharding.ClusterInstance.Teardown() +} diff --git a/go/test/endtoend/sharding/initialsharding/sharding_util.go b/go/test/endtoend/sharding/initialsharding/sharding_util.go new file mode 100644 index 00000000000..542c700a8e1 --- /dev/null +++ b/go/test/endtoend/sharding/initialsharding/sharding_util.go @@ -0,0 +1,750 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package initialsharding + +import ( + "fmt" + "io/ioutil" + "os" + "os/exec" + "path" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/test/endtoend/cluster" + "vitess.io/vitess/go/test/endtoend/sharding" + querypb "vitess.io/vitess/go/vt/proto/query" + "vitess.io/vitess/go/vt/proto/topodata" +) + +var ( + // ClusterInstance instance to be used for test with different params + ClusterInstance *cluster.LocalProcessCluster + hostname = "localhost" + keyspaceName1 = "ks1" + keyspaceName2 = "ks2" + dbPwd = "" + cell = "zone1" + newInitDbFile string + dbCredentialFile string + vtgateInstances []*cluster.VtgateProcess + commonTabletArg = []string{ + "-vreplication_healthcheck_topology_refresh", "1s", + "-vreplication_healthcheck_retry_delay", "1s", + "-vreplication_retry_delay", "1s", + "-degraded_threshold", "5s", + "-lock_tables_timeout", "5s", + "-watch_replication_stream", + "-enable_replication_reporter", + "-serving_state_grace_period", "1s", + "-binlog_use_v3_resharding_mode=true"} + createTabletTemplate = ` + create table %s( + msg varchar(64), + id bigint(20) unsigned, + primary key (id) + ) Engine=InnoDB; +` + createTabletTemplateByte = ` + create table %s( + msg varchar(64), + id varbinary(64), + primary key (id) + ) Engine=InnoDB; +` + insertTabletTemplate = `insert into %s(id, msg) values(%d, "%s")` + tableName = "resharding1" + vSchema = ` + { + "sharded": true, + "vindexes": { + "hash_index": { + "type": "hash" + } + }, + "tables": { + "%s": { + "column_vindexes": [ + { + "column": "%s", + "name": "hash_index" + } + ] + } + } + } + ` +) + +// ClusterWrapper common wrapper code for cluster +func ClusterWrapper(isMulti bool) (int, error) { + ClusterInstance = nil + ClusterInstance = cluster.NewCluster(cell, hostname) + + // Start topo server + if err := ClusterInstance.StartTopo(); err != nil { + return 1, err + } + + if isMulti { + WriteDbCredentialToTmp(ClusterInstance.TmpDirectory) + writeInitDBFile() + dbPwd = "VtDbaPass" + } + + if err := ClusterInstance.VtctlProcess.CreateKeyspace(keyspaceName1); err != nil { + return 1, err + } else { + ClusterInstance.Keyspaces = append(ClusterInstance.Keyspaces, cluster.Keyspace{Name: keyspaceName1}) + } + if isMulti { + if err := ClusterInstance.VtctlProcess.CreateKeyspace(keyspaceName2); err != nil { + return 1, err + } else { + ClusterInstance.Keyspaces = append(ClusterInstance.Keyspaces, cluster.Keyspace{Name: keyspaceName2}) + } + } + + initClusterForInitialSharding(keyspaceName1, []string{"0"}, 3, true, isMulti) + initClusterForInitialSharding(keyspaceName1, []string{"-80", "80-"}, 3, true, isMulti) + + if isMulti { + initClusterForInitialSharding(keyspaceName2, []string{"0"}, 3, true, isMulti) + initClusterForInitialSharding(keyspaceName2, []string{"-80", "80-"}, 3, true, isMulti) + } + return 0, nil +} + +func initClusterForInitialSharding(keyspaceName string, shardNames []string, totalTabletsRequired int, rdonly bool, isMulti bool) { + var mysqlProcesses []*exec.Cmd + var extraArgs []string + if isMulti { + extraArgs = []string{"-db-credentials-file", dbCredentialFile} + } + + for _, shardName := range shardNames { + shard := &cluster.Shard{ + Name: shardName, + } + + for i := 0; i < totalTabletsRequired; i++ { + // instantiate vttablet object with reserved ports + var tablet *cluster.Vttablet + if i == totalTabletsRequired-1 && rdonly { + tablet = ClusterInstance.GetVttabletInstance("rdonly", 0, "") + } else if i == 0 { + tablet = ClusterInstance.GetVttabletInstance("master", 0, "") + } else { + tablet = ClusterInstance.GetVttabletInstance("replica", 0, "") + } + // Start Mysqlctl process + tablet.MysqlctlProcess = *cluster.MysqlCtlProcessInstance(tablet.TabletUID, tablet.MySQLPort, ClusterInstance.TmpDirectory) + + if isMulti { + tablet.MysqlctlProcess.InitDBFile = newInitDbFile + tablet.MysqlctlProcess.ExtraArgs = extraArgs + } + // Start Mysqlctl process, for multi keyspace we need only 1st keyspace sql procs, that is why this check is added + if keyspaceName == keyspaceName1 { + if proc, err := tablet.MysqlctlProcess.StartProcess(); err != nil { + return + } else { + mysqlProcesses = append(mysqlProcesses, proc) + } + } else { // Since we'll be using mysql procs of keyspace-1 for ks-2, resetting this to 0 + tablet.MysqlctlProcess.TabletUID = 0 + } + + // start vttablet process + tablet.VttabletProcess = cluster.VttabletProcessInstance(tablet.HTTPPort, + tablet.GrpcPort, + tablet.TabletUID, + ClusterInstance.Cell, + shardName, + keyspaceName, + ClusterInstance.VtctldProcess.Port, + tablet.Type, + ClusterInstance.TopoProcess.Port, + ClusterInstance.Hostname, + ClusterInstance.TmpDirectory, + ClusterInstance.VtTabletExtraArgs, + ClusterInstance.EnableSemiSync) + tablet.Alias = tablet.VttabletProcess.TabletPath + tablet.VttabletProcess.DbPassword = dbPwd + tablet.VttabletProcess.EnableSemiSync = true + tablet.VttabletProcess.SupportsBackup = false + shard.Vttablets = append(shard.Vttablets, tablet) + } + for idx, ks := range ClusterInstance.Keyspaces { + if ks.Name == keyspaceName { + ClusterInstance.Keyspaces[idx].Shards = append(ClusterInstance.Keyspaces[idx].Shards, *shard) + } + } + } + for _, proc := range mysqlProcesses { + proc.Wait() + } + +} + +// AssignMysqlPortFromKs1ToKs2 assigns mysql port of all tablets of ks1 to all corresponding tablets of ks2 +func AssignMysqlPortFromKs1ToKs2() { + portMap := map[string]int{} + for _, shard := range ClusterInstance.Keyspaces[0].Shards { + for _, tablet := range shard.Vttablets { + portMap[fmt.Sprintf("%s-%s", shard.Name, tablet.Type)] = tablet.MySQLPort + } + } + + for _, shard := range ClusterInstance.Keyspaces[1].Shards { + for idx, tablet := range shard.Vttablets { + port := portMap[fmt.Sprintf("%s-%s", shard.Name, tablet.Type)] + shard.Vttablets[idx].MySQLPort = port + shard.Vttablets[idx].VttabletProcess.DbPort = port + shard.Vttablets[idx].VttabletProcess.PidFile = path.Join(shard.Vttablets[idx].VttabletProcess.LogDir, fmt.Sprintf("vttablet-%d.pid", port)) + } + } +} + +// TestInitialSharding - main test which accepts different params for various test +func TestInitialSharding(t *testing.T, keyspace *cluster.Keyspace, keyType querypb.Type, isMulti bool, isExternal bool) { + defer cluster.PanicHandler(t) + if isExternal { + commonTabletArg = append(commonTabletArg, "-db_host", "127.0.0.1") + commonTabletArg = append(commonTabletArg, "-disable_active_reparents") + for _, shard := range keyspace.Shards { + for _, tablet := range shard.Vttablets { + tablet.VttabletProcess.ExtraArgs = append(tablet.VttabletProcess.ExtraArgs, "-db_port", fmt.Sprintf("%d", tablet.MySQLPort)) + tablet.VttabletProcess.DbPassword = dbPwd + } + } + } + if isMulti { + commonTabletArg = append(commonTabletArg, "-db-credentials-file", dbCredentialFile) + } + // Start the master and rdonly of 1st shard + shard1 := keyspace.Shards[0] + keyspaceName := keyspace.Name + shard1Ks := fmt.Sprintf("%s/%s", keyspaceName, shard1.Name) + shard1MasterTablet := *shard1.MasterTablet() + + // master tablet start + shard1MasterTablet.VttabletProcess.ExtraArgs = append(shard1MasterTablet.VttabletProcess.ExtraArgs, commonTabletArg...) + //var err error + err := ClusterInstance.VtctlclientProcess.InitTablet(&shard1MasterTablet, cell, keyspaceName, hostname, shard1.Name) + require.Nil(t, err) + shard1.Replica().VttabletProcess.ExtraArgs = append(shard1.Replica().VttabletProcess.ExtraArgs, commonTabletArg...) + shard1.Rdonly().VttabletProcess.ExtraArgs = append(shard1.Rdonly().VttabletProcess.ExtraArgs, commonTabletArg...) + + for _, tablet := range shard1.Vttablets { + _ = tablet.VttabletProcess.CreateDB(keyspaceName) + } + err = shard1MasterTablet.VttabletProcess.Setup() + require.Nil(t, err) + + // replica tablet init + err = ClusterInstance.VtctlclientProcess.InitTablet(shard1.Replica(), cell, keyspaceName, hostname, shard1.Name) + require.Nil(t, err) + + // rdonly tablet start + err = ClusterInstance.VtctlclientProcess.InitTablet(shard1.Rdonly(), cell, keyspaceName, hostname, shard1.Name) + require.Nil(t, err) + if isExternal { + shard1.Rdonly().VttabletProcess.ServingStatus = "SERVING" + shard1.Replica().VttabletProcess.ServingStatus = "SERVING" + } + err = shard1.Rdonly().VttabletProcess.Setup() + require.Nil(t, err) + + if !isMulti { + output, err := ClusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("InitShardMaster", + "-force", fmt.Sprintf("%s/%s", keyspaceName, shard1.Name), shard1MasterTablet.Alias) + require.Error(t, err, "Should fail as no replica tablet is present.") + assert.Contains(t, output, fmt.Sprintf("tablet %s ResetReplication failed", shard1.Replica().Alias)) + } + // start replica + err = shard1.Replica().VttabletProcess.Setup() + require.Nil(t, err) + + // reparent to make the tablets work + if !isExternal { + // reparent to make the tablets work + err = ClusterInstance.VtctlclientProcess.InitShardMaster(keyspace.Name, shard1.Name, cell, shard1MasterTablet.TabletUID) + require.Nil(t, err) + } else { + err = shard1.Replica().VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + _, err = ClusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("TabletExternallyReparented", shard1MasterTablet.Alias) + require.Nil(t, err) + } + + err = shard1.Replica().VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + err = shard1.Rdonly().VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + for _, vttablet := range shard1.Vttablets { + assert.Equal(t, vttablet.VttabletProcess.GetTabletStatus(), "SERVING") + } + // create the tables and add startup values + sqlSchemaToApply := createTabletTemplate + if keyType == querypb.Type_VARBINARY { + sqlSchemaToApply = createTabletTemplateByte + } + err = ClusterInstance.VtctlclientProcess.ApplySchema(keyspaceName, fmt.Sprintf(sqlSchemaToApply, tableName)) + require.Nil(t, err) + + err = ClusterInstance.VtctlclientProcess.ApplyVSchema(keyspaceName, fmt.Sprintf(vSchema, tableName, "id")) + require.Nil(t, err) + _, err = shard1MasterTablet.VttabletProcess.QueryTablet(fmt.Sprintf(insertTabletTemplate, tableName, uint64(0x1000000000000000), "msg1"), keyspaceName, true) + require.Nil(t, err) + _, err = shard1MasterTablet.VttabletProcess.QueryTablet(fmt.Sprintf(insertTabletTemplate, tableName, uint64(0x9000000000000000), "msg2"), keyspaceName, true) + require.Nil(t, err) + _, err = shard1MasterTablet.VttabletProcess.QueryTablet(fmt.Sprintf(insertTabletTemplate, tableName, uint64(0xD000000000000000), "msg3"), keyspaceName, true) + require.Nil(t, err) + + // reload schema on all tablets so we can query them + for _, vttablet := range shard1.Vttablets { + _ = ClusterInstance.VtctlclientProcess.ExecuteCommand("ReloadSchema", vttablet.Alias) + } + vtgateInstance := ClusterInstance.GetVtgateInstance() + vtgateInstance.PidFile = path.Join(ClusterInstance.TmpDirectory, fmt.Sprintf("vtgate-%s.pid", keyspaceName)) + vtgateInstance.MySQLServerSocketPath = path.Join(ClusterInstance.TmpDirectory, fmt.Sprintf("mysql-%s.sock", keyspaceName)) + vtgateInstance.ExtraArgs = []string{"-retry-count", fmt.Sprintf("%d", 2), "-tablet_protocol", "grpc", "-normalize_queries", "-tablet_refresh_interval", "2s"} + err = vtgateInstance.Setup() + vtgateInstances = append(vtgateInstances, vtgateInstance) + require.Nil(t, err) + + for _, tabletType := range []string{"master", "replica", "rdonly"} { + if err = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.%s", keyspaceName, shard1.Name, tabletType), 1); err != nil { + assert.Fail(t, err.Error()) + } + } + + _ = ClusterInstance.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", keyspaceName) + + // run a health check on source replica so it responds to discovery + err = ClusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", shard1.Replica().Alias) + require.Nil(t, err) + + // create the split shards + shard21 := keyspace.Shards[1] + shard22 := keyspace.Shards[2] + + for _, shard := range []cluster.Shard{shard21, shard22} { + for idx, vttablet := range shard.Vttablets { + vttablet.VttabletProcess.ExtraArgs = append(vttablet.VttabletProcess.ExtraArgs, commonTabletArg...) + err = ClusterInstance.VtctlclientProcess.InitTablet(vttablet, cell, keyspaceName, hostname, shard.Name) + require.Nil(t, err) + _ = vttablet.VttabletProcess.CreateDB(keyspaceName) + if isExternal { + shard.Vttablets[idx].VttabletProcess.ServingStatus = "" + } + err = vttablet.VttabletProcess.Setup() + require.Nil(t, err) + } + } + if !isExternal { + _ = ClusterInstance.VtctlclientProcess.InitShardMaster(keyspaceName, shard21.Name, cell, shard21.MasterTablet().TabletUID) + _ = ClusterInstance.VtctlclientProcess.InitShardMaster(keyspaceName, shard22.Name, cell, shard22.MasterTablet().TabletUID) + _ = ClusterInstance.VtctlclientProcess.ApplySchema(keyspaceName, fmt.Sprintf(sqlSchemaToApply, tableName)) + _ = ClusterInstance.VtctlclientProcess.ApplyVSchema(keyspaceName, fmt.Sprintf(vSchema, tableName, "id")) + + for _, shard := range []cluster.Shard{shard21, shard22} { + _ = shard.Replica().VttabletProcess.WaitForTabletType("SERVING") + _ = shard.Rdonly().VttabletProcess.WaitForTabletType("SERVING") + } + + for _, shard := range []cluster.Shard{shard21, shard22} { + for _, vttablet := range shard.Vttablets { + assert.Equal(t, vttablet.VttabletProcess.GetTabletStatus(), "SERVING") + } + } + } else { + _, err = ClusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("TabletExternallyReparented", shard21.MasterTablet().Alias) + require.Nil(t, err) + _, err = ClusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("TabletExternallyReparented", shard22.MasterTablet().Alias) + require.Nil(t, err) + } + + // must restart vtgate after tablets are up, or else wait until 1min refresh + // we want cache_ttl at zero so we re-read the topology for every test query. + + _ = vtgateInstance.TearDown() + _ = vtgateInstance.Setup() + + // Wait for the endpoints, either local or remote. + for _, shard := range []cluster.Shard{shard1, shard21, shard22} { + err = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.master", keyspaceName, shard.Name), 1) + require.Nil(t, err) + err = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.replica", keyspaceName, shard.Name), 1) + require.Nil(t, err) + err = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.rdonly", keyspaceName, shard.Name), 1) + require.Nil(t, err) + } + + // Check srv keyspace + expectedPartitions := map[topodata.TabletType][]string{} + expectedPartitions[topodata.TabletType_MASTER] = []string{shard1.Name} + expectedPartitions[topodata.TabletType_REPLICA] = []string{shard1.Name} + expectedPartitions[topodata.TabletType_RDONLY] = []string{shard1.Name} + checkSrvKeyspaceForSharding(t, keyspaceName, expectedPartitions) + + err = ClusterInstance.VtctlclientProcess.ExecuteCommand("CopySchemaShard", + "--exclude_tables", "unrelated", + shard1.Rdonly().Alias, fmt.Sprintf("%s/%s", keyspaceName, shard21.Name)) + require.Nil(t, err) + + err = ClusterInstance.VtctlclientProcess.ExecuteCommand("CopySchemaShard", + "--exclude_tables", "unrelated", + shard1.Rdonly().Alias, fmt.Sprintf("%s/%s", keyspaceName, shard22.Name)) + require.Nil(t, err) + + err = ClusterInstance.StartVtworker(cell, "--use_v3_resharding_mode=true") + require.Nil(t, err) + + // Initial clone (online). + _ = ClusterInstance.VtworkerProcess.ExecuteCommand("SplitClone", + "--offline=false", + "--exclude_tables", "unrelated", + "--chunk_count", "10", + "--min_rows_per_chunk", "1", + "--min_healthy_rdonly_tablets", "1", + fmt.Sprintf("%s/%s", keyspaceName, shard1.Name)) + + // Reset vtworker such that we can run the next command. + _ = ClusterInstance.VtworkerProcess.ExecuteCommand("Reset") + + // Modify the destination shard. SplitClone will revert the changes. + // Delete row 1 (provokes an insert). + _, _ = shard21.MasterTablet().VttabletProcess.QueryTablet(fmt.Sprintf("delete from %s where id=%d", tableName, uint64(0x1000000000000000)), keyspaceName, true) + // Delete row 2 (provokes an insert). + _, _ = shard22.MasterTablet().VttabletProcess.QueryTablet(fmt.Sprintf("delete from %s where id=%d", tableName, uint64(0x9000000000000000)), keyspaceName, true) + // Update row 3 (provokes an update). + _, _ = shard22.MasterTablet().VttabletProcess.QueryTablet(fmt.Sprintf("update %s set msg='msg-not-3' where id=%d", tableName, uint64(0xD000000000000000)), keyspaceName, true) + // Insert row 4 (provokes a delete). + var ksid uint64 = 0xD000000000000000 + insertSQL := fmt.Sprintf(sharding.InsertTabletTemplateKsID, tableName, ksid, "msg4", ksid) + sharding.InsertToTablet(t, insertSQL, *shard22.MasterTablet(), keyspaceName, true) + + _ = ClusterInstance.VtworkerProcess.ExecuteCommand("SplitClone", + "--exclude_tables", "unrelated", + "--chunk_count", "10", + "--min_rows_per_chunk", "1", + "--min_healthy_rdonly_tablets", "1", + fmt.Sprintf("%s/%s", keyspaceName, shard1.Name)) + + // check first value is in the left shard + for _, tablet := range shard21.Vttablets { + sharding.CheckValues(t, *tablet, 0x1000000000000000, "msg1", true, tableName, keyspaceName, keyType) + } + + for _, tablet := range shard22.Vttablets { + sharding.CheckValues(t, *tablet, 0x1000000000000000, "msg1", false, tableName, keyspaceName, keyType) + } + + for _, tablet := range shard21.Vttablets { + sharding.CheckValues(t, *tablet, 0x9000000000000000, "msg2", false, tableName, keyspaceName, keyType) + } + + for _, tablet := range shard22.Vttablets { + sharding.CheckValues(t, *tablet, 0x9000000000000000, "msg2", true, tableName, keyspaceName, keyType) + } + + for _, tablet := range shard21.Vttablets { + sharding.CheckValues(t, *tablet, 0xD000000000000000, "msg3", false, tableName, keyspaceName, keyType) + } + + for _, tablet := range shard22.Vttablets { + sharding.CheckValues(t, *tablet, 0xD000000000000000, "msg3", true, tableName, keyspaceName, keyType) + } + + err = ClusterInstance.VtctlclientProcess.ExecuteCommand("ValidateSchemaKeyspace", keyspaceName) + require.Nil(t, err) + + // check the binlog players are running + sharding.CheckDestinationMaster(t, *shard21.MasterTablet(), []string{shard1Ks}, *ClusterInstance) + sharding.CheckDestinationMaster(t, *shard22.MasterTablet(), []string{shard1Ks}, *ClusterInstance) + + // check that binlog server exported the stats vars + sharding.CheckBinlogServerVars(t, *shard1.Replica(), 0, 0, false) + + for _, tablet := range []cluster.Vttablet{*shard21.Rdonly(), *shard22.Rdonly()} { + err = ClusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", tablet.Alias) + require.Nil(t, err) + } + + // testing filtered replication: insert a bunch of data on shard 1, + // check we get most of it after a few seconds, wait for binlog server + // timeout, check we get all of it. + sharding.InsertLots(t, 1000, shard1MasterTablet, tableName, keyspaceName) + + assert.True(t, sharding.CheckLotsTimeout(t, *shard21.Replica(), 1000, tableName, keyspaceName, keyType, 49)) + assert.True(t, sharding.CheckLotsTimeout(t, *shard22.Replica(), 1000, tableName, keyspaceName, keyType, 51)) + + sharding.CheckDestinationMaster(t, *shard21.MasterTablet(), []string{shard1Ks}, *ClusterInstance) + sharding.CheckDestinationMaster(t, *shard22.MasterTablet(), []string{shard1Ks}, *ClusterInstance) + sharding.CheckBinlogServerVars(t, *shard1.Replica(), 1000, 1000, false) + + err = ClusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", shard21.Rdonly().Alias) + require.Nil(t, err) + err = ClusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", shard22.Rdonly().Alias) + require.Nil(t, err) + + //use vtworker to compare the data + ClusterInstance.VtworkerProcess.Cell = cell + if !isMulti { + err = ClusterInstance.VtworkerProcess.ExecuteVtworkerCommand(ClusterInstance.GetAndReservePort(), + ClusterInstance.GetAndReservePort(), + "--use_v3_resharding_mode=true", + "MultiSplitDiff", + fmt.Sprintf("%s/%s", keyspaceName, shard1.Name)) + require.Nil(t, err) + + for _, shard := range []string{shard21.Name, shard22.Name} { + err = ClusterInstance.VtworkerProcess.ExecuteVtworkerCommand(ClusterInstance.GetAndReservePort(), + ClusterInstance.GetAndReservePort(), + "--use_v3_resharding_mode=true", + "SplitDiff", + "--min_healthy_rdonly_tablets", "1", + fmt.Sprintf("%s/%s", keyspaceName, shard)) + require.Nil(t, err) + } + } + + if isExternal { + // get status for the destination master tablet, make sure we have it all + sharding.CheckRunningBinlogPlayer(t, *shard21.MasterTablet(), 3956, 2002) + sharding.CheckRunningBinlogPlayer(t, *shard22.MasterTablet(), 4048, 2002) + } else { + sharding.CheckRunningBinlogPlayer(t, *shard21.MasterTablet(), 3954, 2000) + sharding.CheckRunningBinlogPlayer(t, *shard22.MasterTablet(), 4046, 2000) + } + + // check we can't migrate the master just yet + err = ClusterInstance.VtctlclientProcess.ExecuteCommand("MigrateServedTypes", shard1Ks, "master") + require.Error(t, err) + + // now serve rdonly from the split shards + err = ClusterInstance.VtctlclientProcess.ExecuteCommand("MigrateServedTypes", shard1Ks, "rdonly") + require.Nil(t, err) + expectedPartitions = map[topodata.TabletType][]string{} + expectedPartitions[topodata.TabletType_MASTER] = []string{shard1.Name} + expectedPartitions[topodata.TabletType_REPLICA] = []string{shard1.Name} + expectedPartitions[topodata.TabletType_RDONLY] = []string{shard21.Name, shard22.Name} + checkSrvKeyspaceForSharding(t, keyspaceName, expectedPartitions) + + _ = shard21.Rdonly().VttabletProcess.WaitForTabletType("SERVING") + _ = shard22.Rdonly().VttabletProcess.WaitForTabletType("SERVING") + + _ = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.rdonly", keyspaceName, shard21.Name), 1) + _ = vtgateInstance.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.rdonly", keyspaceName, shard22.Name), 1) + + //then serve replica from the split shards + + sourceTablet := shard1.Replica() + destinationTablets := []cluster.Vttablet{*shard21.Replica(), *shard22.Replica()} + + _ = ClusterInstance.VtctlclientProcess.ExecuteCommand("MigrateServedTypes", shard1Ks, "replica") + expectedPartitions = map[topodata.TabletType][]string{} + expectedPartitions[topodata.TabletType_MASTER] = []string{shard1.Name} + expectedPartitions[topodata.TabletType_REPLICA] = []string{shard21.Name, shard22.Name} + expectedPartitions[topodata.TabletType_RDONLY] = []string{shard21.Name, shard22.Name} + checkSrvKeyspaceForSharding(t, keyspaceName, expectedPartitions) + + //move replica back and forth + _ = ClusterInstance.VtctlclientProcess.ExecuteCommand("MigrateServedTypes", "-reverse", shard1Ks, "replica") + + // After a backwards migration, queryservice should be enabled on source and disabled on destinations + sharding.CheckTabletQueryService(t, *sourceTablet, "SERVING", false, *ClusterInstance) + sharding.CheckTabletQueryServices(t, destinationTablets, "NOT_SERVING", true, *ClusterInstance) + + expectedPartitions = map[topodata.TabletType][]string{} + expectedPartitions[topodata.TabletType_MASTER] = []string{shard1.Name} + expectedPartitions[topodata.TabletType_REPLICA] = []string{shard1.Name} + expectedPartitions[topodata.TabletType_RDONLY] = []string{shard21.Name, shard22.Name} + checkSrvKeyspaceForSharding(t, keyspaceName, expectedPartitions) + + _ = ClusterInstance.VtctlclientProcess.ExecuteCommand("MigrateServedTypes", shard1Ks, "replica") + + // After a forwards migration, queryservice should be disabled on source and enabled on destinations + sharding.CheckTabletQueryService(t, *sourceTablet, "NOT_SERVING", true, *ClusterInstance) + sharding.CheckTabletQueryServices(t, destinationTablets, "SERVING", false, *ClusterInstance) + expectedPartitions = map[topodata.TabletType][]string{} + expectedPartitions[topodata.TabletType_MASTER] = []string{shard1.Name} + expectedPartitions[topodata.TabletType_REPLICA] = []string{shard21.Name, shard22.Name} + expectedPartitions[topodata.TabletType_RDONLY] = []string{shard21.Name, shard22.Name} + checkSrvKeyspaceForSharding(t, keyspaceName, expectedPartitions) + + // then serve master from the split shards + _ = ClusterInstance.VtctlclientProcess.ExecuteCommand("MigrateServedTypes", shard1Ks, "master") + expectedPartitions = map[topodata.TabletType][]string{} + expectedPartitions[topodata.TabletType_MASTER] = []string{shard21.Name, shard22.Name} + expectedPartitions[topodata.TabletType_REPLICA] = []string{shard21.Name, shard22.Name} + expectedPartitions[topodata.TabletType_RDONLY] = []string{shard21.Name, shard22.Name} + checkSrvKeyspaceForSharding(t, keyspaceName, expectedPartitions) + + // check the binlog players are gone now + err = shard21.MasterTablet().VttabletProcess.WaitForBinLogPlayerCount(0) + require.Nil(t, err) + err = shard22.MasterTablet().VttabletProcess.WaitForBinLogPlayerCount(0) + require.Nil(t, err) + + // make sure we can't delete a shard with tablets + err = ClusterInstance.VtctlclientProcess.ExecuteCommand("DeleteShard", shard1Ks) + require.Error(t, err) + if !isMulti { + KillTabletsInKeyspace(keyspace) + KillVtgateInstances() + } + ClusterInstance.VtworkerProcess.TearDown() + +} + +// KillTabletsInKeyspace kill the first shard tablets in ordered way +func KillTabletsInKeyspace(keyspace *cluster.Keyspace) { + // Teardown + shard1 := keyspace.Shards[0] + var mysqlctlProcessList []*exec.Cmd + for _, tablet := range []cluster.Vttablet{*shard1.MasterTablet(), *shard1.Replica(), *shard1.Rdonly()} { + proc, _ := tablet.MysqlctlProcess.StopProcess() + mysqlctlProcessList = append(mysqlctlProcessList, proc) + _ = tablet.VttabletProcess.TearDown() + } + for _, proc := range mysqlctlProcessList { + proc.Wait() + } + _ = ClusterInstance.VtctlclientProcess.ExecuteCommand("DeleteTablet", shard1.Replica().Alias) + _ = ClusterInstance.VtctlclientProcess.ExecuteCommand("DeleteTablet", shard1.Rdonly().Alias) + _ = ClusterInstance.VtctlclientProcess.ExecuteCommand("DeleteTablet", "-allow_master", shard1.MasterTablet().Alias) + + _ = ClusterInstance.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", keyspace.Name) + _ = ClusterInstance.VtctlclientProcess.ExecuteCommand("DeleteShard", keyspace.Name+"/"+shard1.Name) +} + +// KillVtgateInstances stops the vtgate process +func KillVtgateInstances() { + if len(vtgateInstances) > 0 { + for _, vtgateInstance := range vtgateInstances { + _ = vtgateInstance.TearDown() + } + } +} + +func checkSrvKeyspaceForSharding(t *testing.T, ksName string, expectedPartitions map[topodata.TabletType][]string) { + sharding.CheckSrvKeyspace(t, cell, ksName, "", 0, expectedPartitions, *ClusterInstance) +} + +// Create a new init_db.sql file that sets up passwords for all users. +// Then we use a db-credentials-file with the passwords. +func writeInitDBFile() { + initDb, _ := ioutil.ReadFile(path.Join(os.Getenv("VTROOT"), "/config/init_db.sql")) + sql := string(initDb) + newInitDbFile = path.Join(ClusterInstance.TmpDirectory, "init_db_with_passwords.sql") + sql = sql + GetPasswordUpdateSQL(ClusterInstance) + ` +# connecting through a port requires 127.0.0.1 +# --host=localhost will connect through socket +CREATE USER 'vt_dba'@'127.0.0.1' IDENTIFIED BY 'VtDbaPass'; +GRANT ALL ON *.* TO 'vt_dba'@'127.0.0.1'; +GRANT GRANT OPTION ON *.* TO 'vt_dba'@'127.0.0.1'; +# User for app traffic, with global read-write access. +CREATE USER 'vt_app'@'127.0.0.1' IDENTIFIED BY 'VtAppPass'; +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE, + REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, + LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, + SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER + ON *.* TO 'vt_app'@'127.0.0.1'; +# User for administrative operations that need to be executed as non-SUPER. +# Same permissions as vt_app here. +CREATE USER 'vt_allprivs'@'127.0.0.1' IDENTIFIED BY 'VtAllPrivsPass'; +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE, + REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, + LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, + SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER + ON *.* TO 'vt_allprivs'@'127.0.0.1'; +# User for Vitess filtered replication (binlog player). +# Same permissions as vt_app. +CREATE USER 'vt_filtered'@'127.0.0.1' IDENTIFIED BY 'VtFilteredPass'; +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE, + REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, + LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, + SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER + ON *.* TO 'vt_filtered'@'127.0.0.1'; +FLUSH PRIVILEGES; +` + ioutil.WriteFile(newInitDbFile, []byte(sql), 0666) + +} + +// WriteDbCredentialToTmp writes json format db credentials to tmp directory +func WriteDbCredentialToTmp(tmpDir string) string { + data := []byte(`{ + "vt_dba": ["VtDbaPass"], + "vt_app": ["VtAppPass"], + "vt_allprivs": ["VtAllprivsPass"], + "vt_repl": ["VtReplPass"], + "vt_filtered": ["VtFilteredPass"] + }`) + dbCredentialFile = path.Join(tmpDir, "db_credentials.json") + ioutil.WriteFile(dbCredentialFile, data, 0666) + return dbCredentialFile +} + +// GetPasswordUpdateSQL returns the sql for password update +func GetPasswordUpdateSQL(localCluster *cluster.LocalProcessCluster) string { + pwdChangeCmd := ` + # Set real passwords for all users. + UPDATE mysql.user SET %s = PASSWORD('RootPass') + WHERE User = 'root' AND Host = 'localhost'; + UPDATE mysql.user SET %s = PASSWORD('VtDbaPass') + WHERE User = 'vt_dba' AND Host = 'localhost'; + UPDATE mysql.user SET %s = PASSWORD('VtAppPass') + WHERE User = 'vt_app' AND Host = 'localhost'; + UPDATE mysql.user SET %s = PASSWORD('VtAllprivsPass') + WHERE User = 'vt_allprivs' AND Host = 'localhost'; + UPDATE mysql.user SET %s = PASSWORD('VtReplPass') + WHERE User = 'vt_repl' AND Host = '%%'; + UPDATE mysql.user SET %s = PASSWORD('VtFilteredPass') + WHERE User = 'vt_filtered' AND Host = 'localhost'; + FLUSH PRIVILEGES; + ` + pwdCol, _ := getPasswordField(localCluster) + return fmt.Sprintf(pwdChangeCmd, pwdCol, pwdCol, pwdCol, pwdCol, pwdCol, pwdCol) +} + +// getPasswordField Determines which column is used for user passwords in this MySQL version. +func getPasswordField(localCluster *cluster.LocalProcessCluster) (pwdCol string, err error) { + tablet := &cluster.Vttablet{ + Type: "relpica", + TabletUID: 100, + MySQLPort: 15000, + MysqlctlProcess: *cluster.MysqlCtlProcessInstance(100, 15000, localCluster.TmpDirectory), + } + if err = tablet.MysqlctlProcess.Start(); err != nil { + return "", err + } + tablet.VttabletProcess = cluster.VttabletProcessInstance(tablet.HTTPPort, tablet.GrpcPort, tablet.TabletUID, "", "", "", 0, + tablet.Type, localCluster.TopoPort, "", "", nil, false) + result, err := tablet.VttabletProcess.QueryTablet("select password from mysql.user limit 0", "", false) + if err == nil && len(result.Rows) > 0 { + return "password", nil + } + tablet.MysqlctlProcess.Stop() + os.RemoveAll(path.Join(tablet.VttabletProcess.Directory)) + return "authentication_string", nil + +} diff --git a/go/test/endtoend/sharding/initialsharding/v3/initial_sharding_test.go b/go/test/endtoend/sharding/initialsharding/v3/initial_sharding_test.go new file mode 100644 index 00000000000..95e5e5c8975 --- /dev/null +++ b/go/test/endtoend/sharding/initialsharding/v3/initial_sharding_test.go @@ -0,0 +1,47 @@ +/* +Copyright 2019 The Vitess Authors. + +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 test simulates the first time a database has to be split. + +- we start with a keyspace with a single shard and a single table +- we add and populate the sharding key +- we set the sharding key in the topology +- we clone into 2 instances +- we enable filtered replication +- we move all serving types +- we remove the source tablets +- we remove the original shard + +*/ + +package v3 + +import ( + "testing" + + "vitess.io/vitess/go/test/endtoend/cluster" + sharding "vitess.io/vitess/go/test/endtoend/sharding/initialsharding" + querypb "vitess.io/vitess/go/vt/proto/query" +) + +func TestInitialSharding(t *testing.T) { + defer cluster.PanicHandler(t) + code, err := sharding.ClusterWrapper(false) + if err != nil { + t.Errorf("setup failed with status code %d", code) + } + sharding.TestInitialSharding(t, &sharding.ClusterInstance.Keyspaces[0], querypb.Type_UINT64, false, false) + defer sharding.ClusterInstance.Teardown() +} diff --git a/go/test/endtoend/sharding/mergesharding/int/mergesharding_int_test.go b/go/test/endtoend/sharding/mergesharding/int/mergesharding_int_test.go new file mode 100644 index 00000000000..94efd03bf4e --- /dev/null +++ b/go/test/endtoend/sharding/mergesharding/int/mergesharding_int_test.go @@ -0,0 +1,29 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package v3 + +import ( + "testing" + + sharding "vitess.io/vitess/go/test/endtoend/sharding/mergesharding" +) + +// TestMergeShardingIntShardingKey - tests merge sharding using a INT column +func TestMergeShardingIntShardingKey(t *testing.T) { + sharding.TestMergesharding(t, false /* useVarbinaryShardingKeyType */) + +} diff --git a/go/test/endtoend/sharding/mergesharding/mergesharding_base.go b/go/test/endtoend/sharding/mergesharding/mergesharding_base.go new file mode 100644 index 00000000000..d196123e39e --- /dev/null +++ b/go/test/endtoend/sharding/mergesharding/mergesharding_base.go @@ -0,0 +1,642 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package mergesharding + +import ( + "context" + "encoding/json" + "fmt" + "os/exec" + "path" + "strings" + "testing" + "time" + + "vitess.io/vitess/go/sqltypes" + + "vitess.io/vitess/go/mysql" + + "github.com/prometheus/common/log" + + "vitess.io/vitess/go/test/endtoend/cluster" + "vitess.io/vitess/go/test/endtoend/sharding" + querypb "vitess.io/vitess/go/vt/proto/query" + "vitess.io/vitess/go/vt/proto/topodata" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +var ( + // ClusterInstance instance to be used for test with different params + clusterInstance *cluster.LocalProcessCluster + hostname = "localhost" + keyspaceName = "ks" + cell = "zone1" + createTabletTemplate = ` + create table %s( + custom_ksid_col %s not null, + msg varchar(64), + id bigint not null, + parent_id bigint not null, + primary key (parent_id, id), + index by_msg (msg) + ) Engine=InnoDB; + ` + fixedParentID = 86 + tableName = "resharding1" + vSchema = ` + { + "sharded": true, + "vindexes": { + "hash_index": { + "type": "hash" + } + }, + "tables": { + "resharding1": { + "column_vindexes": [ + { + "column": "custom_ksid_col", + "name": "hash_index" + } + ] + } + } + } + ` + // insertTabletTemplateKsID common insert format + insertTabletTemplateKsID = `insert into %s (parent_id, id, msg, custom_ksid_col) values (%d, %d, '%s', %d) /* vtgate:: keyspace_id:%d */ /* id:%d */` + + // initial shards + // range -40, 40-80 & 80- + shard0 = &cluster.Shard{Name: "-40"} + shard1 = &cluster.Shard{Name: "40-80"} + shard2 = &cluster.Shard{Name: "80-"} + + // merge shard + // merging -40 & 40-80 to -80 + shard3 = &cluster.Shard{Name: "-80"} + + // Sharding keys + key1 uint64 = 1 // Key redirect to shard 0 [-40] + key2 uint64 = 3 // key redirect to shard 1 [40-80] + key3 uint64 = 4 // Key redirect to shard 2 [80-] +) + +// TestMergesharding covers the workflow for a sharding merge. +// We start with 3 shards: -40, 40-80, and 80-. We then merge -40 and 40-80 into -80. +// Note this test is just testing the full workflow, not corner cases or error +// cases. These are mostly done by the other resharding tests. +func TestMergesharding(t *testing.T, useVarbinaryShardingKeyType bool) { + defer cluster.PanicHandler(t) + clusterInstance = cluster.NewCluster(cell, hostname) + defer clusterInstance.Teardown() + + // Launch keyspace + keyspace := &cluster.Keyspace{Name: keyspaceName} + + // Start topo server + err := clusterInstance.StartTopo() + require.Nil(t, err) + + // Defining all the tablets + shard0Master := clusterInstance.GetVttabletInstance("replica", 0, "") + shard0Replica := clusterInstance.GetVttabletInstance("replica", 0, "") + shard0Rdonly := clusterInstance.GetVttabletInstance("rdonly", 0, "") + + shard1Master := clusterInstance.GetVttabletInstance("replica", 0, "") + shard1Replica := clusterInstance.GetVttabletInstance("replica", 0, "") + shard1Rdonly := clusterInstance.GetVttabletInstance("rdonly", 0, "") + + shard2Master := clusterInstance.GetVttabletInstance("replica", 0, "") + shard2Replica := clusterInstance.GetVttabletInstance("replica", 0, "") + shard2Rdonly := clusterInstance.GetVttabletInstance("rdonly", 0, "") + + shard3Master := clusterInstance.GetVttabletInstance("replica", 0, "") + shard3Replica := clusterInstance.GetVttabletInstance("replica", 0, "") + shard3Rdonly := clusterInstance.GetVttabletInstance("rdonly", 0, "") + + shard0.Vttablets = []*cluster.Vttablet{shard0Master, shard0Replica, shard0Rdonly} + shard1.Vttablets = []*cluster.Vttablet{shard1Master, shard1Replica, shard1Rdonly} + shard2.Vttablets = []*cluster.Vttablet{shard2Master, shard2Replica, shard2Rdonly} + shard3.Vttablets = []*cluster.Vttablet{shard3Master, shard3Replica, shard3Rdonly} + + clusterInstance.VtTabletExtraArgs = []string{ + "-vreplication_healthcheck_topology_refresh", "1s", + "-vreplication_healthcheck_retry_delay", "1s", + "-vreplication_retry_delay", "1s", + "-degraded_threshold", "5s", + "-lock_tables_timeout", "5s", + "-watch_replication_stream", + "-enable_semi_sync", + "-enable_replication_reporter", + "-enable-tx-throttler", + "-binlog_use_v3_resharding_mode=true", + } + + shardingColumnType := "bigint(20) unsigned" + shardingKeyType := querypb.Type_UINT64 + + if useVarbinaryShardingKeyType { + shardingColumnType = "varbinary(64)" + shardingKeyType = querypb.Type_VARBINARY + } + + // Initialize Cluster + err = clusterInstance.LaunchCluster(keyspace, []cluster.Shard{*shard0, *shard1, *shard2, *shard3}) + require.Nil(t, err) + assert.Equal(t, len(clusterInstance.Keyspaces[0].Shards), 4) + + //Start MySql + var mysqlCtlProcessList []*exec.Cmd + for _, shard := range clusterInstance.Keyspaces[0].Shards { + for _, tablet := range shard.Vttablets { + fmt.Println("Starting MySql for tablet ", tablet.Alias) + if proc, err := tablet.MysqlctlProcess.StartProcess(); err != nil { + t.Fatal(err) + } else { + mysqlCtlProcessList = append(mysqlCtlProcessList, proc) + } + } + } + + // Wait for mysql processes to start + for _, proc := range mysqlCtlProcessList { + if err := proc.Wait(); err != nil { + t.Fatal(err) + } + } + + // Rebuild keyspace Graph + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", keyspaceName) + require.Nil(t, err) + + // Get Keyspace and verify the structure + srvKeyspace := sharding.GetSrvKeyspace(t, cell, keyspaceName, *clusterInstance) + assert.Equal(t, "", srvKeyspace.GetShardingColumnName()) + + //Start Tablets and Wait for the Process + for _, shard := range clusterInstance.Keyspaces[0].Shards { + for _, tablet := range shard.Vttablets { + // Init Tablet + err := clusterInstance.VtctlclientProcess.InitTablet(tablet, tablet.Cell, keyspaceName, hostname, shard.Name) + require.Nil(t, err) + + // Start the tablet + err = tablet.VttabletProcess.Setup() + require.Nil(t, err) + + // Create Database + _, err = tablet.VttabletProcess.QueryTablet(fmt.Sprintf("create database vt_%s", + keyspace.Name), keyspace.Name, false) + require.Nil(t, err) + } + } + + // Init Shard Master + err = clusterInstance.VtctlclientProcess.ExecuteCommand("InitShardMaster", + "-force", fmt.Sprintf("%s/%s", keyspaceName, shard0.Name), shard0Master.Alias) + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("InitShardMaster", + "-force", fmt.Sprintf("%s/%s", keyspaceName, shard1.Name), shard1Master.Alias) + require.Nil(t, err) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("InitShardMaster", + "-force", fmt.Sprintf("%s/%s", keyspaceName, shard2.Name), shard2Master.Alias) + require.Nil(t, err) + + // Init Shard Master on Merge Shard + err = clusterInstance.VtctlclientProcess.ExecuteCommand("InitShardMaster", + "-force", fmt.Sprintf("%s/%s", keyspaceName, shard3.Name), shard3Master.Alias) + require.Nil(t, err) + + // Wait for tablets to come in Service state + err = shard0Master.VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + err = shard1Master.VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + err = shard2Master.VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + err = shard3Master.VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + + // keyspace/shard name fields + shard0Ks := fmt.Sprintf("%s/%s", keyspaceName, shard0.Name) + shard1Ks := fmt.Sprintf("%s/%s", keyspaceName, shard1.Name) + shard3Ks := fmt.Sprintf("%s/%s", keyspaceName, shard3.Name) + + // check for shards + result, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("FindAllShardsInKeyspace", keyspaceName) + require.Nil(t, err) + resultMap := make(map[string]interface{}) + err = json.Unmarshal([]byte(result), &resultMap) + require.Nil(t, err) + assert.Equal(t, 4, len(resultMap), "No of shards should be 4") + + // Apply Schema + err = clusterInstance.VtctlclientProcess.ApplySchema(keyspaceName, fmt.Sprintf(createTabletTemplate, "resharding1", shardingColumnType)) + require.Nil(t, err) + + // Apply VSchema + err = clusterInstance.VtctlclientProcess.ApplyVSchema(keyspaceName, vSchema) + require.Nil(t, err) + + // Insert Data + insertStartupValues(t) + + // run a health check on source replicas so they respond to discovery + // (for binlog players) and on the source rdonlys (for workers) + for _, shard := range keyspace.Shards { + for _, tablet := range shard.Vttablets { + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", tablet.Alias) + require.Nil(t, err) + } + } + + // Rebuild keyspace Graph + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", keyspaceName) + require.Nil(t, err) + + // check srv keyspace + expectedPartitions := map[topodata.TabletType][]string{} + expectedPartitions[topodata.TabletType_MASTER] = []string{shard0.Name, shard1.Name, shard2.Name} + expectedPartitions[topodata.TabletType_REPLICA] = []string{shard0.Name, shard1.Name, shard2.Name} + expectedPartitions[topodata.TabletType_RDONLY] = []string{shard0.Name, shard1.Name, shard2.Name} + sharding.CheckSrvKeyspace(t, cell, keyspaceName, "", 0, expectedPartitions, *clusterInstance) + + // we need to create the schema, and the worker will do data copying + err = clusterInstance.VtctlclientProcess.ExecuteCommand("CopySchemaShard", + shard0.Rdonly().Alias, fmt.Sprintf("%s/%s", keyspaceName, shard3.Name)) + require.Nil(t, err) + + // Run vtworker as daemon for the following SplitClone commands. -use_v3_resharding_mode default is true + err = clusterInstance.StartVtworker(cell, "--command_display_interval", "10ms") + require.Nil(t, err) + + // Initial clone (online). + err = clusterInstance.VtworkerProcess.ExecuteCommand("SplitClone", + "--offline=false", + "--chunk_count", "10", + "--min_rows_per_chunk", "1", + "--min_healthy_rdonly_tablets", "1", + "--max_tps", "9999", + shard3Ks) + require.Nil(t, err) + + // Check values in the merge shard + checkValues(t, *shard3.MasterTablet(), []string{"INT64(86)", "INT64(1)", `VARCHAR("msg1")`, fmt.Sprintf("UINT64(%d)", key1)}, + 1, true, tableName, fixedParentID, keyspaceName, shardingKeyType, nil) + checkValues(t, *shard3.MasterTablet(), []string{"INT64(86)", "INT64(2)", `VARCHAR("msg2")`, fmt.Sprintf("UINT64(%d)", key2)}, + 2, true, tableName, fixedParentID, keyspaceName, shardingKeyType, nil) + + // Reset vtworker such that we can run the next command. + err = clusterInstance.VtworkerProcess.ExecuteCommand("Reset") + require.Nil(t, err) + + // Delete row 2 (provokes an insert). + _, err = shard3Master.VttabletProcess.QueryTablet("delete from resharding1 where id=2", keyspaceName, true) + require.Nil(t, err) + // Update row 3 (provokes an update). + _, err = shard3Master.VttabletProcess.QueryTablet("update resharding1 set msg='msg-not-1' where id=1", keyspaceName, true) + require.Nil(t, err) + + // Insert row 4 (provokes a delete). + insertValue(t, shard3.MasterTablet(), keyspaceName, tableName, 4, "msg4", key3) + + err = clusterInstance.VtworkerProcess.ExecuteCommand( + "SplitClone", + "--chunk_count", "10", + "--min_rows_per_chunk", "1", + "--min_healthy_rdonly_tablets", "1", + "--max_tps", "9999", + shard3Ks) + require.Nil(t, err) + + // Change tablet, which was taken offline, back to rdonly. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", shard0Rdonly.Alias, "rdonly") + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", shard1Rdonly.Alias, "rdonly") + require.Nil(t, err) + + // Terminate worker daemon because it is no longer needed. + err = clusterInstance.VtworkerProcess.TearDown() + require.Nil(t, err) + + // Check startup values + checkStartupValues(t, shardingKeyType) + + // check the schema too + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ValidateSchemaKeyspace", keyspaceName) + require.Nil(t, err) + + // Verify vreplication table entries + qr, err := shard3.MasterTablet().VttabletProcess.QueryTabletWithDB("select * from vreplication", "_vt") + require.Nil(t, err) + assert.Equal(t, 2, len(qr.Rows)) + assert.Contains(t, fmt.Sprintf("%v", qr.Rows), "SplitClone") + assert.Contains(t, fmt.Sprintf("%v", qr.Rows), `"keyspace:\"ks\" shard:\"-40\" key_range: "`) + assert.Contains(t, fmt.Sprintf("%v", qr.Rows), `"keyspace:\"ks\" shard:\"40-80\" key_range: "`) + + // check the binlog players are running and exporting vars + sharding.CheckDestinationMaster(t, *shard3Master, []string{shard1Ks, shard0Ks}, *clusterInstance) + + // When the binlog players/filtered replication is turned on, the query + // service must be turned off on the destination masters. + // The tested behavior is a safeguard to prevent that somebody can + // accidentally modify data on the destination masters while they are not + // migrated yet and the source shards are still the source of truth. + err = shard3Master.VttabletProcess.WaitForTabletType("NOT_SERVING") + require.Nil(t, err) + + // check that binlog server exported the stats vars + sharding.CheckBinlogServerVars(t, *shard0Replica, 0, 0, false) + sharding.CheckBinlogServerVars(t, *shard1Replica, 0, 0, false) + + // testing filtered replication: insert a bunch of data on shard 1, check we get most of it after a few seconds, + // wait for binlog server timeout, check we get all of it. + log.Debug("Inserting lots of data on source shard") + insertLots(t, 100, 0, tableName, fixedParentID, keyspaceName) + + //Checking 100 percent of data is sent quickly + assert.True(t, checkLotsTimeout(t, 100, 0, tableName, keyspaceName, shardingKeyType)) + + sharding.CheckBinlogPlayerVars(t, *shard3Master, []string{shard1Ks, shard0Ks}, 30) + + sharding.CheckBinlogServerVars(t, *shard0Replica, 100, 100, false) + sharding.CheckBinlogServerVars(t, *shard1Replica, 100, 100, false) + + // use vtworker to compare the data (after health-checking the destination + // rdonly tablets so discovery works) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", shard3Rdonly.Alias) + require.Nil(t, err) + + // use vtworker to compare the data + clusterInstance.VtworkerProcess.Cell = cell + + // Compare using SplitDiff + log.Debug("Running vtworker SplitDiff") + err = clusterInstance.VtworkerProcess.ExecuteVtworkerCommand(clusterInstance.GetAndReservePort(), + clusterInstance.GetAndReservePort(), + "--use_v3_resharding_mode=true", + "SplitDiff", + "--exclude_tables", "unrelated", + "--min_healthy_rdonly_tablets", "1", + "--source_uid", "1", + shard3Ks) + require.Nil(t, err) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", shard0Rdonly.Alias, "rdonly") + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", shard3Rdonly.Alias, "rdonly") + require.Nil(t, err) + + log.Debug("Running vtworker SplitDiff on second half") + + err = clusterInstance.VtworkerProcess.ExecuteVtworkerCommand(clusterInstance.GetAndReservePort(), + clusterInstance.GetAndReservePort(), + "--use_v3_resharding_mode=true", + "SplitDiff", + "--exclude_tables", "unrelated", + "--min_healthy_rdonly_tablets", "1", + "--source_uid", "2", + shard3Ks) + require.Nil(t, err) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", shard1Rdonly.Alias, "rdonly") + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", shard3Rdonly.Alias, "rdonly") + require.Nil(t, err) + + // get status for destination master tablets, make sure we have it all + sharding.CheckRunningBinlogPlayer(t, *shard3Master, 300, 100) + + sharding.CheckTabletQueryService(t, *shard3Master, "NOT_SERVING", false, *clusterInstance) + streamHealth, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput( + "VtTabletStreamHealth", + "-count", "1", shard3Master.Alias) + require.Nil(t, err) + log.Debug("Got health: ", streamHealth) + + var streamHealthResponse querypb.StreamHealthResponse + err = json.Unmarshal([]byte(streamHealth), &streamHealthResponse) + require.Nil(t, err) + assert.Equal(t, streamHealthResponse.Serving, false) + assert.NotNil(t, streamHealthResponse.RealtimeStats) + + // check the destination master 3 is healthy, even though its query + // service is not running (if not healthy this would exception out) + sharding.VerifyTabletHealth(t, *shard3Master, hostname) + + // now serve rdonly from the split shards, in cell1 only + err = clusterInstance.VtctlclientProcess.ExecuteCommand( + "MigrateServedTypes", shard3Ks, "rdonly") + require.Nil(t, err) + + // check srv keyspace + expectedPartitions = map[topodata.TabletType][]string{} + expectedPartitions[topodata.TabletType_MASTER] = []string{shard0.Name, shard1.Name, shard2.Name} + expectedPartitions[topodata.TabletType_RDONLY] = []string{shard3.Name, shard2.Name} + expectedPartitions[topodata.TabletType_REPLICA] = []string{shard0.Name, shard1.Name, shard2.Name} + sharding.CheckSrvKeyspace(t, cell, keyspaceName, "", 0, expectedPartitions, *clusterInstance) + + sharding.CheckTabletQueryService(t, *shard0Rdonly, "NOT_SERVING", true, *clusterInstance) + sharding.CheckTabletQueryService(t, *shard1Rdonly, "NOT_SERVING", true, *clusterInstance) + + // Now serve replica from the split shards + err = clusterInstance.VtctlclientProcess.ExecuteCommand( + "MigrateServedTypes", shard3Ks, "replica") + require.Nil(t, err) + + expectedPartitions = map[topodata.TabletType][]string{} + expectedPartitions[topodata.TabletType_MASTER] = []string{shard0.Name, shard1.Name, shard2.Name} + expectedPartitions[topodata.TabletType_RDONLY] = []string{shard3.Name, shard2.Name} + expectedPartitions[topodata.TabletType_REPLICA] = []string{shard3.Name, shard2.Name} + sharding.CheckSrvKeyspace(t, cell, keyspaceName, "", 0, expectedPartitions, *clusterInstance) + + // now serve master from the split shards + err = clusterInstance.VtctlclientProcess.ExecuteCommand( + "MigrateServedTypes", shard3Ks, "master") + require.Nil(t, err) + + expectedPartitions = map[topodata.TabletType][]string{} + expectedPartitions[topodata.TabletType_MASTER] = []string{shard3.Name, shard2.Name} + expectedPartitions[topodata.TabletType_RDONLY] = []string{shard3.Name, shard2.Name} + expectedPartitions[topodata.TabletType_REPLICA] = []string{shard3.Name, shard2.Name} + sharding.CheckSrvKeyspace(t, cell, keyspaceName, "", 0, expectedPartitions, *clusterInstance) + + sharding.CheckTabletQueryService(t, *shard0Master, "NOT_SERVING", true, *clusterInstance) + sharding.CheckTabletQueryService(t, *shard1Master, "NOT_SERVING", true, *clusterInstance) + + // check destination shards are serving + sharding.CheckTabletQueryService(t, *shard3Master, "SERVING", false, *clusterInstance) + + // check the binlog players are gone now + err = shard3Master.VttabletProcess.WaitForBinLogPlayerCount(0) + require.Nil(t, err) + + // delete the original tablets in the original shard + for _, shard := range []cluster.Shard{*shard0, *shard1} { + for _, tablet := range shard.Vttablets { + _ = tablet.MysqlctlProcess.Stop() + _ = tablet.VttabletProcess.TearDown() + } + } + + for _, tablet := range []cluster.Vttablet{*shard0Replica, *shard1Replica, *shard0Rdonly, *shard1Rdonly} { + err = clusterInstance.VtctlclientProcess.ExecuteCommand("DeleteTablet", tablet.Alias) + require.Nil(t, err) + } + + for _, tablet := range []cluster.Vttablet{*shard0Master, *shard1Master} { + err = clusterInstance.VtctlclientProcess.ExecuteCommand("DeleteTablet", "-allow_master", tablet.Alias) + require.Nil(t, err) + } + + // rebuild the serving graph, all mentions of the old shards should be gone + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", keyspaceName) + require.Nil(t, err) + +} + +func insertStartupValues(t *testing.T) { + insertSQL := fmt.Sprintf(insertTabletTemplateKsID, "resharding1", fixedParentID, 1, "msg1", key1, key1, 1) + sharding.InsertToTablet(t, insertSQL, *shard0.MasterTablet(), keyspaceName, false) + + insertSQL = fmt.Sprintf(insertTabletTemplateKsID, "resharding1", fixedParentID, 2, "msg2", key2, key2, 2) + sharding.InsertToTablet(t, insertSQL, *shard1.MasterTablet(), keyspaceName, false) + + insertSQL = fmt.Sprintf(insertTabletTemplateKsID, "resharding1", fixedParentID, 3, "msg3", key3, key3, 3) + sharding.InsertToTablet(t, insertSQL, *shard2.MasterTablet(), keyspaceName, false) +} + +func insertValue(t *testing.T, tablet *cluster.Vttablet, keyspaceName string, tableName string, id int, msg string, ksID uint64) { + insertSQL := fmt.Sprintf(insertTabletTemplateKsID, tableName, fixedParentID, id, msg, ksID, ksID, id) + sharding.InsertToTablet(t, insertSQL, *tablet, keyspaceName, false) +} + +func checkStartupValues(t *testing.T, shardingKeyType querypb.Type) { + for _, tablet := range shard3.Vttablets { + checkValues(t, *tablet, []string{"INT64(86)", "INT64(1)", `VARCHAR("msg1")`, fmt.Sprintf("UINT64(%d)", key1)}, + 1, true, "resharding1", fixedParentID, keyspaceName, shardingKeyType, nil) + + checkValues(t, *tablet, []string{"INT64(86)", "INT64(2)", `VARCHAR("msg2")`, fmt.Sprintf("UINT64(%d)", key2)}, + 2, true, "resharding1", fixedParentID, keyspaceName, shardingKeyType, nil) + } +} + +// checkLotsTimeout waits till all values are inserted +func checkLotsTimeout(t *testing.T, count uint64, base uint64, table string, keyspaceName string, keyType querypb.Type) bool { + timeout := time.Now().Add(10 * time.Second) + for time.Now().Before(timeout) { + percentFound := checkLots(t, count, base, table, keyspaceName, keyType) + if percentFound == 100 { + return true + } + time.Sleep(300 * time.Millisecond) + } + return false +} + +func checkLots(t *testing.T, count uint64, base uint64, table string, keyspaceName string, keyType querypb.Type) float32 { + shard3Replica := *shard3.Vttablets[1] + + ctx := context.Background() + dbParams := getDBparams(shard3Replica, keyspaceName) + dbConn, _ := mysql.Connect(ctx, &dbParams) + defer dbConn.Close() + + var isFound bool + var totalFound int + var i uint64 + for i = 0; i < count; i++ { + isFound = checkValues(t, shard3Replica, []string{"INT64(86)", + fmt.Sprintf("INT64(%d)", 10000+base+i), + fmt.Sprintf(`VARCHAR("msg-range0-%d")`, 10000+base+i), + fmt.Sprintf("UINT64(%d)", key1)}, + 10000+base+i, true, table, fixedParentID, keyspaceName, keyType, dbConn) + if isFound { + totalFound++ + } + + isFound = checkValues(t, shard3Replica, []string{"INT64(86)", + fmt.Sprintf("INT64(%d)", 20000+base+i), + fmt.Sprintf(`VARCHAR("msg-range1-%d")`, 20000+base+i), + fmt.Sprintf("UINT64(%d)", key2)}, + 20000+base+i, true, table, fixedParentID, keyspaceName, keyType, dbConn) + if isFound { + totalFound++ + } + } + return float32(totalFound * 100 / int(count) / 2) +} + +func checkValues(t *testing.T, vttablet cluster.Vttablet, values []string, id uint64, exists bool, tableName string, + parentID int, ks string, keyType querypb.Type, dbConn *mysql.Conn) bool { + query := fmt.Sprintf("select parent_id, id, msg, custom_ksid_col from %s where parent_id = %d and id = %d", tableName, parentID, id) + var result *sqltypes.Result + var err error + if dbConn != nil { + result, err = dbConn.ExecuteFetch(query, 1000, true) + require.Nil(t, err) + } else { + result, err = vttablet.VttabletProcess.QueryTablet(query, ks, true) + require.Nil(t, err) + } + + isFound := false + if exists && len(result.Rows) > 0 { + isFound = assert.Equal(t, result.Rows[0][0].String(), values[0]) + isFound = isFound && assert.Equal(t, result.Rows[0][1].String(), values[1]) + isFound = isFound && assert.Equal(t, result.Rows[0][2].String(), values[2]) + if keyType == querypb.Type_VARBINARY { + r := strings.NewReplacer("UINT64(", "VARBINARY(\"", ")", "\")") + expected := r.Replace(values[3]) + isFound = isFound && assert.Equal(t, result.Rows[0][3].String(), expected) + } else { + isFound = isFound && assert.Equal(t, result.Rows[0][3].String(), values[3]) + } + + } else { + assert.Equal(t, len(result.Rows), 0) + } + return isFound +} + +// insertLots inserts multiple values to vttablet +func insertLots(t *testing.T, count uint64, base uint64, table string, parentID int, ks string) { + var query1, query2 string + var i uint64 + for i = 0; i < count; i++ { + query1 = fmt.Sprintf(insertTabletTemplateKsID, table, parentID, 10000+base+i, + fmt.Sprintf("msg-range0-%d", 10000+base+i), key1, key1, 10000+base+i) + query2 = fmt.Sprintf(insertTabletTemplateKsID, table, parentID, 20000+base+i, + fmt.Sprintf("msg-range1-%d", 20000+base+i), key2, key2, 20000+base+i) + + sharding.InsertToTablet(t, query1, *shard0.MasterTablet(), ks, false) + sharding.InsertToTablet(t, query2, *shard1.MasterTablet(), ks, false) + } +} + +func getDBparams(vttablet cluster.Vttablet, ks string) mysql.ConnParams { + dbParams := mysql.ConnParams{ + Uname: "vt_dba", + UnixSocket: path.Join(vttablet.VttabletProcess.Directory, "mysql.sock"), + DbName: "vt_" + ks, + } + return dbParams +} diff --git a/go/test/endtoend/sharding/mergesharding/string/mergesharding_string_test.go b/go/test/endtoend/sharding/mergesharding/string/mergesharding_string_test.go new file mode 100644 index 00000000000..95b1dbf01f7 --- /dev/null +++ b/go/test/endtoend/sharding/mergesharding/string/mergesharding_string_test.go @@ -0,0 +1,29 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package v3 + +import ( + "testing" + + sharding "vitess.io/vitess/go/test/endtoend/sharding/mergesharding" +) + +// TestMergeShardingStringShardingKey - tests merge sharding using a String column +func TestMergeShardingStringShardingKey(t *testing.T) { + sharding.TestMergesharding(t, true /* useVarbinaryShardingKeyType */) + +} diff --git a/go/test/endtoend/sharding/resharding/resharding_base.go b/go/test/endtoend/sharding/resharding/resharding_base.go new file mode 100644 index 00000000000..eebf38888a8 --- /dev/null +++ b/go/test/endtoend/sharding/resharding/resharding_base.go @@ -0,0 +1,1329 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package resharding + +import ( + "context" + "encoding/json" + "fmt" + "os/exec" + "path" + "strings" + "testing" + "time" + + "vitess.io/vitess/go/sqltypes" + + "vitess.io/vitess/go/mysql" + + "github.com/prometheus/common/log" + + "vitess.io/vitess/go/test/endtoend/cluster" + "vitess.io/vitess/go/test/endtoend/sharding" + querypb "vitess.io/vitess/go/vt/proto/query" + "vitess.io/vitess/go/vt/proto/topodata" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +var ( + // ClusterInstance instance to be used for test with different params + clusterInstance *cluster.LocalProcessCluster + hostname = "localhost" + keyspaceName = "ks" + cell1 = "zone1" + cell2 = "zone2" + createTabletTemplate = ` + create table %s( + custom_ksid_col %s not null, + msg varchar(64), + id bigint not null, + parent_id bigint not null, + primary key (parent_id, id), + index by_msg (msg) + ) Engine=InnoDB; + ` + createTableBindataTemplate = ` + create table %s( + custom_ksid_col %s not null, + id bigint not null, + parent_id bigint not null, + msg bit(8), + primary key (parent_id, id), + index by_msg (msg) + ) Engine=InnoDB; + ` + createViewTemplate = ` + create view %s (parent_id, id, msg, custom_ksid_col) as select parent_id, id, msg, custom_ksid_col from %s; + ` + createTimestampTable = ` + create table timestamps( + id int not null, + time_milli bigint(20) unsigned not null, + custom_ksid_col %s not null, + primary key (id) + ) Engine=InnoDB; + ` + // Make sure that clone and diff work with tables which have no primary key. + // Work with RBR only + createNoPkTable = ` + create table no_pk( + custom_ksid_col %s not null, + msg varchar(64), + id bigint not null, + parent_id bigint not null + ) Engine=InnoDB; + ` + createUnrelatedTable = ` + create table unrelated( + custom_ksid_col bigint not null, + name varchar(64), + primary key (name) + ) Engine=InnoDB; + ` + fixedParentID = 86 + tableName = "resharding1" + vSchema = ` + { + "sharded": true, + "vindexes": { + "hash_index": { + "type": "hash" + } + }, + "tables": { + "resharding1": { + "column_vindexes": [ + { + "column": "custom_ksid_col", + "name": "hash_index" + } + ] + }, + "resharding2": { + "column_vindexes": [ + { + "column": "custom_ksid_col", + "name": "hash_index" + } + ] + }, + "resharding3": { + "column_vindexes": [ + { + "column": "custom_ksid_col", + "name": "hash_index" + } + ] + }, + "no_pk": { + "column_vindexes": [ + { + "column": "custom_ksid_col", + "name": "hash_index" + } + ] + }, + "timestamps": { + "column_vindexes": [ + { + "column": "custom_ksid_col", + "name": "hash_index" + } + ] + }, + "unrelated": { + "column_vindexes": [ + { + "column": "custom_ksid_col", + "name": "hash_index" + } + ] + } + } + } + ` + + // initial shards + // range '' - 80 & range 80 - '' + shard0 = &cluster.Shard{Name: "-80"} + shard1 = &cluster.Shard{Name: "80-"} + + // split shards + // range 80 - c0 & range c0 - '' + shard2 = &cluster.Shard{Name: "80-c0"} + shard3 = &cluster.Shard{Name: "c0-"} + + // Sharding keys + key1 uint64 = 1152921504606846976 // Key redirect to shard 0 + key2 uint64 = 14987979559889010688 // key redirect to shard 1 (& 2 after Resharding) + key3 uint64 = 10376293541461622784 // Key redirect to shard 1 (& 3 after Resharding) + key4 uint64 = 10376293541461622789 // Key redirect to shard 1 (& 3 after Resharding) + key5 uint64 = 14987979559889010670 // key redirect to shard 1 (& 2 after Resharding) + key6 uint64 = 17293822569102704640 + + // insertTabletTemplateKsID common insert format + insertTabletTemplateKsID = `insert into %s (parent_id, id, msg, custom_ksid_col) values (%d, %d, '%s', %d) /* vtgate:: keyspace_id:%d */ /* id:%d */` +) + +// TestResharding - main test with accepts different params for various test +func TestResharding(t *testing.T, useVarbinaryShardingKeyType bool) { + defer cluster.PanicHandler(t) + clusterInstance = cluster.NewCluster(cell1, hostname) + defer clusterInstance.Teardown() + + // Launch keyspace + keyspace := &cluster.Keyspace{Name: keyspaceName} + + // Start topo server + err := clusterInstance.StartTopo() + require.Nil(t, err) + + // Adding another cell in the same cluster + err = clusterInstance.TopoProcess.ManageTopoDir("mkdir", "/vitess/"+cell2) + require.Nil(t, err) + err = clusterInstance.VtctlProcess.AddCellInfo(cell2) + require.Nil(t, err) + + // Defining all the tablets + shard0Master := clusterInstance.GetVttabletInstance("replica", 0, "") + shard0Replica := clusterInstance.GetVttabletInstance("replica", 0, "") + shard0RdonlyZ2 := clusterInstance.GetVttabletInstance("rdonly", 0, cell2) + + shard1Master := clusterInstance.GetVttabletInstance("replica", 0, "") + shard1Replica1 := clusterInstance.GetVttabletInstance("replica", 0, "") + shard1Replica2 := clusterInstance.GetVttabletInstance("replica", 0, "") + shard1Rdonly := clusterInstance.GetVttabletInstance("rdonly", 0, "") + shard1RdonlyZ2 := clusterInstance.GetVttabletInstance("rdonly", 0, cell2) + + shard2Master := clusterInstance.GetVttabletInstance("replica", 0, "") + shard2Replica1 := clusterInstance.GetVttabletInstance("replica", 0, "") + shard2Replica2 := clusterInstance.GetVttabletInstance("replica", 0, "") + shard2Rdonly := clusterInstance.GetVttabletInstance("rdonly", 0, "") + + shard3Master := clusterInstance.GetVttabletInstance("replica", 0, "") + shard3Replica := clusterInstance.GetVttabletInstance("replica", 0, "") + shard3Rdonly := clusterInstance.GetVttabletInstance("rdonly", 0, "") + + shard0.Vttablets = []*cluster.Vttablet{shard0Master, shard0Replica, shard0RdonlyZ2} + shard1.Vttablets = []*cluster.Vttablet{shard1Master, shard1Replica1, shard1Replica2, shard1Rdonly, shard1RdonlyZ2} + shard2.Vttablets = []*cluster.Vttablet{shard2Master, shard2Replica1, shard2Replica2, shard2Rdonly} + shard3.Vttablets = []*cluster.Vttablet{shard3Master, shard3Replica, shard3Rdonly} + + clusterInstance.VtTabletExtraArgs = []string{ + "-vreplication_healthcheck_topology_refresh", "1s", + "-vreplication_healthcheck_retry_delay", "1s", + "-vreplication_retry_delay", "1s", + "-degraded_threshold", "5s", + "-lock_tables_timeout", "5s", + "-watch_replication_stream", + "-enable_semi_sync", + "-enable_replication_reporter", + "-enable-tx-throttler", + "-binlog_use_v3_resharding_mode=true", + } + + shardingColumnType := "bigint(20) unsigned" + shardingKeyType := querypb.Type_UINT64 + + if useVarbinaryShardingKeyType { + shardingColumnType = "varbinary(64)" + shardingKeyType = querypb.Type_VARBINARY + } + + // Initialize Cluster + err = clusterInstance.LaunchCluster(keyspace, []cluster.Shard{*shard0, *shard1, *shard2, *shard3}) + require.Nil(t, err) + assert.Equal(t, len(clusterInstance.Keyspaces[0].Shards), 4) + + //Start MySql + var mysqlCtlProcessList []*exec.Cmd + for _, shard := range clusterInstance.Keyspaces[0].Shards { + for _, tablet := range shard.Vttablets { + fmt.Println("Starting MySql for tablet ", tablet.Alias) + if proc, err := tablet.MysqlctlProcess.StartProcess(); err != nil { + t.Fatal(err) + } else { + mysqlCtlProcessList = append(mysqlCtlProcessList, proc) + } + } + } + + // Wait for mysql processes to start + for _, proc := range mysqlCtlProcessList { + if err := proc.Wait(); err != nil { + t.Fatal(err) + } + } + + // Rebuild keyspace Graph + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", keyspaceName) + require.Nil(t, err) + + // Get Keyspace and verify the structure + srvKeyspace := sharding.GetSrvKeyspace(t, cell1, keyspaceName, *clusterInstance) + assert.Equal(t, "", srvKeyspace.GetShardingColumnName()) + + //Start Tablets and Wait for the Process + for _, shard := range clusterInstance.Keyspaces[0].Shards { + for _, tablet := range shard.Vttablets { + // Init Tablet + err := clusterInstance.VtctlclientProcess.InitTablet(tablet, tablet.Cell, keyspaceName, hostname, shard.Name) + require.Nil(t, err) + + // Start the tablet + err = tablet.VttabletProcess.Setup() + require.Nil(t, err) + + // Create Database + _, err = tablet.VttabletProcess.QueryTablet(fmt.Sprintf("create database vt_%s", + keyspace.Name), keyspace.Name, false) + require.Nil(t, err) + } + } + + // Init Shard Master + err = clusterInstance.VtctlclientProcess.ExecuteCommand("InitShardMaster", + "-force", fmt.Sprintf("%s/%s", keyspaceName, shard0.Name), shard0Master.Alias) + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("InitShardMaster", + "-force", fmt.Sprintf("%s/%s", keyspaceName, shard1.Name), shard1Master.Alias) + require.Nil(t, err) + + // Init Shard Master on Split Shards + err = clusterInstance.VtctlclientProcess.ExecuteCommand("InitShardMaster", + "-force", fmt.Sprintf("%s/%s", keyspaceName, shard2.Name), shard2Master.Alias) + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("InitShardMaster", + "-force", fmt.Sprintf("%s/%s", keyspaceName, shard3.Name), shard3Master.Alias) + require.Nil(t, err) + + // Wait for tablets to come in Service state + err = shard0Master.VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + err = shard1Master.VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + err = shard2Master.VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + err = shard3Master.VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + + // keyspace/shard name fields + shard0Ks := fmt.Sprintf("%s/%s", keyspaceName, shard0.Name) + shard1Ks := fmt.Sprintf("%s/%s", keyspaceName, shard1.Name) + shard2Ks := fmt.Sprintf("%s/%s", keyspaceName, shard2.Name) + shard3Ks := fmt.Sprintf("%s/%s", keyspaceName, shard3.Name) + + // check for shards + result, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("FindAllShardsInKeyspace", keyspaceName) + require.Nil(t, err) + resultMap := make(map[string]interface{}) + err = json.Unmarshal([]byte(result), &resultMap) + require.Nil(t, err) + assert.Equal(t, 4, len(resultMap), "No of shards should be 4") + + // Apply Schema + err = clusterInstance.VtctlclientProcess.ApplySchema(keyspaceName, fmt.Sprintf(createTabletTemplate, "resharding1", shardingColumnType)) + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ApplySchema(keyspaceName, fmt.Sprintf(createTabletTemplate, "resharding2", shardingColumnType)) + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ApplySchema(keyspaceName, fmt.Sprintf(createTableBindataTemplate, "resharding3", shardingColumnType)) + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ApplySchema(keyspaceName, fmt.Sprintf(createViewTemplate, "view1", "resharding3")) + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ApplySchema(keyspaceName, fmt.Sprintf(createNoPkTable, shardingColumnType)) + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ApplySchema(keyspaceName, fmt.Sprintf(createTimestampTable, shardingColumnType)) + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ApplySchema(keyspaceName, createUnrelatedTable) + require.Nil(t, err) + + // Apply VSchema + err = clusterInstance.VtctlclientProcess.ApplyVSchema(keyspaceName, vSchema) + require.Nil(t, err) + + // Insert Data + insertStartupValues(t) + + // run a health check on source replicas so they respond to discovery + // (for binlog players) and on the source rdonlys (for workers) + for _, shard := range keyspace.Shards { + for _, tablet := range shard.Vttablets { + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", tablet.Alias) + require.Nil(t, err) + } + } + + // Rebuild keyspace Graph + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", keyspaceName) + require.Nil(t, err) + + // check srv keyspace + expectedPartitions := map[topodata.TabletType][]string{} + expectedPartitions[topodata.TabletType_MASTER] = []string{shard0.Name, shard1.Name} + expectedPartitions[topodata.TabletType_REPLICA] = []string{shard0.Name, shard1.Name} + expectedPartitions[topodata.TabletType_RDONLY] = []string{shard0.Name, shard1.Name} + sharding.CheckSrvKeyspace(t, cell1, keyspaceName, "", 0, expectedPartitions, *clusterInstance) + + // disable shard1Replica2, so we're sure filtered replication will go from shard1Replica1 + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", shard1Replica2.Alias, "spare") + require.Nil(t, err) + + err = shard1Replica2.VttabletProcess.WaitForTabletType("NOT_SERVING") + require.Nil(t, err) + + // we need to create the schema, and the worker will do data copying + err = clusterInstance.VtctlclientProcess.ExecuteCommand("CopySchemaShard", "--exclude_tables", "unrelated", + shard1.Rdonly().Alias, fmt.Sprintf("%s/%s", keyspaceName, shard2.Name)) + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("CopySchemaShard", "--exclude_tables", "unrelated", + shard1.Rdonly().Alias, fmt.Sprintf("%s/%s", keyspaceName, shard3.Name)) + require.Nil(t, err) + + // Run vtworker as daemon for the following SplitClone commands. -use_v3_resharding_mode default is true + err = clusterInstance.StartVtworker(cell1, "--command_display_interval", "10ms") + require.Nil(t, err) + + // Copy the data from the source to the destination shards. + // --max_tps is only specified to enable the throttler and ensure that the + // code is executed. But the intent here is not to throttle the test, hence + // the rate limit is set very high. + + // Initial clone (online). + err = clusterInstance.VtworkerProcess.ExecuteCommand("SplitClone", + "--offline=false", + "--exclude_tables", "unrelated", + "--chunk_count", "10", + "--min_rows_per_chunk", "1", + "--min_healthy_rdonly_tablets", "1", + "--max_tps", "9999", + shard1Ks) + require.Nil(t, err) + + // Check values in the split shard + checkValues(t, *shard2.MasterTablet(), []string{"INT64(86)", "INT64(2)", `VARCHAR("msg2")`, fmt.Sprintf("UINT64(%d)", key2)}, + 2, true, tableName, fixedParentID, keyspaceName, shardingKeyType, nil) + checkValues(t, *shard3.MasterTablet(), []string{"INT64(86)", "INT64(2)", `VARCHAR("msg2")`, fmt.Sprintf("UINT64(%d)", key2)}, + 2, false, tableName, fixedParentID, keyspaceName, shardingKeyType, nil) + + // Reset vtworker such that we can run the next command. + err = clusterInstance.VtworkerProcess.ExecuteCommand("Reset") + require.Nil(t, err) + + // Test the correct handling of keyspace_id changes which happen after the first clone. + sql := fmt.Sprintf("update resharding1 set custom_ksid_col=%d WHERE id=2", key3) + _, err = shard1Master.VttabletProcess.QueryTablet(sql, keyspaceName, true) + require.Nil(t, err) + + err = clusterInstance.VtworkerProcess.ExecuteCommand("SplitClone", + "--offline=false", + "--exclude_tables", "unrelated", + "--chunk_count", "10", + "--min_rows_per_chunk", "1", + "--min_healthy_rdonly_tablets", "1", + "--max_tps", "9999", + shard1Ks) + require.Nil(t, err) + + checkValues(t, *shard2.MasterTablet(), []string{"INT64(86)", "INT64(2)", `VARCHAR("msg2")`, fmt.Sprintf("UINT64(%d)", key3)}, + 2, false, tableName, fixedParentID, keyspaceName, shardingKeyType, nil) + checkValues(t, *shard3.MasterTablet(), []string{"INT64(86)", "INT64(2)", `VARCHAR("msg2")`, fmt.Sprintf("UINT64(%d)", key3)}, + 2, true, tableName, fixedParentID, keyspaceName, shardingKeyType, nil) + + err = clusterInstance.VtworkerProcess.ExecuteCommand("Reset") + require.Nil(t, err) + + // Move row 2 back to shard 2 from shard 3 by changing the keyspace_id again + sql = fmt.Sprintf("update resharding1 set custom_ksid_col=%d WHERE id=2", key2) + _, err = shard1Master.VttabletProcess.QueryTablet(sql, keyspaceName, true) + require.Nil(t, err) + + err = clusterInstance.VtworkerProcess.ExecuteCommand("SplitClone", + "--offline=false", + "--exclude_tables", "unrelated", + "--chunk_count", "10", + "--min_rows_per_chunk", "1", + "--min_healthy_rdonly_tablets", "1", + "--max_tps", "9999", + shard1Ks) + require.Nil(t, err) + + checkValues(t, *shard2.MasterTablet(), []string{"INT64(86)", "INT64(2)", `VARCHAR("msg2")`, fmt.Sprintf("UINT64(%d)", key2)}, + 2, true, tableName, fixedParentID, keyspaceName, shardingKeyType, nil) + checkValues(t, *shard3.MasterTablet(), []string{"INT64(86)", "INT64(2)", `VARCHAR("msg2")`, fmt.Sprintf("UINT64(%d)", key2)}, + 2, false, tableName, fixedParentID, keyspaceName, shardingKeyType, nil) + + // Reset vtworker such that we can run the next command. + err = clusterInstance.VtworkerProcess.ExecuteCommand("Reset") + require.Nil(t, err) + + // Modify the destination shard. SplitClone will revert the changes. + + // Delete row 2 (provokes an insert). + _, err = shard2Master.VttabletProcess.QueryTablet("delete from resharding1 where id=2", keyspaceName, true) + require.Nil(t, err) + // Update row 3 (provokes an update). + _, err = shard3Master.VttabletProcess.QueryTablet("update resharding1 set msg='msg-not-3' where id=3", keyspaceName, true) + require.Nil(t, err) + + // Insert row 4 and 5 (provokes a delete). + insertValue(t, shard3.MasterTablet(), keyspaceName, tableName, 4, "msg4", key3) + insertValue(t, shard3.MasterTablet(), keyspaceName, tableName, 5, "msg5", key3) + + err = clusterInstance.VtworkerProcess.ExecuteCommand("SplitClone", + "--exclude_tables", "unrelated", + "--chunk_count", "10", + "--min_rows_per_chunk", "1", + "--min_healthy_rdonly_tablets", "1", + "--max_tps", "9999", + shard1Ks) + require.Nil(t, err) + + // Change tablet, which was taken offline, back to rdonly. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", shard1Rdonly.Alias, "rdonly") + require.Nil(t, err) + + // Terminate worker daemon because it is no longer needed. + err = clusterInstance.VtworkerProcess.TearDown() + require.Nil(t, err) + + // Check startup values + checkStartupValues(t, shardingKeyType) + + // check the schema too + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ValidateSchemaKeyspace", "--exclude_tables=unrelated", keyspaceName) + require.Nil(t, err) + + // Verify vreplication table entries + qr, err := shard2Master.VttabletProcess.QueryTabletWithDB("select * from vreplication", "_vt") + require.Nil(t, err) + assert.Equal(t, 1, len(qr.Rows)) + assert.Contains(t, fmt.Sprintf("%v", qr.Rows), "SplitClone") + assert.Contains(t, fmt.Sprintf("%v", qr.Rows), `"keyspace:\"ks\" shard:\"80-\" key_range: "`) + + qr, err = shard3.MasterTablet().VttabletProcess.QueryTabletWithDB("select * from vreplication", "_vt") + require.Nil(t, err) + assert.Equal(t, 1, len(qr.Rows)) + assert.Contains(t, fmt.Sprintf("%v", qr.Rows), "SplitClone") + assert.Contains(t, fmt.Sprintf("%v", qr.Rows), `"keyspace:\"ks\" shard:\"80-\" key_range: "`) + + // check the binlog players are running and exporting vars + sharding.CheckDestinationMaster(t, *shard2Master, []string{shard1Ks}, *clusterInstance) + sharding.CheckDestinationMaster(t, *shard3Master, []string{shard1Ks}, *clusterInstance) + + // When the binlog players/filtered replication is turned on, the query + // service must be turned off on the destination masters. + // The tested behavior is a safeguard to prevent that somebody can + // accidentally modify data on the destination masters while they are not + // migrated yet and the source shards are still the source of truth. + err = shard2Master.VttabletProcess.WaitForTabletType("NOT_SERVING") + require.Nil(t, err) + err = shard3Master.VttabletProcess.WaitForTabletType("NOT_SERVING") + require.Nil(t, err) + + // check that binlog server exported the stats vars + sharding.CheckBinlogServerVars(t, *shard1Replica1, 0, 0, false) + + // Check that the throttler was enabled. + // The stream id is hard-coded as 1, which is the first id generated through auto-inc. + sharding.CheckThrottlerService(t, fmt.Sprintf("%s:%d", hostname, shard2Master.GrpcPort), + []string{"BinlogPlayer/1"}, 9999, *clusterInstance) + sharding.CheckThrottlerService(t, fmt.Sprintf("%s:%d", hostname, shard3Master.GrpcPort), + []string{"BinlogPlayer/1"}, 9999, *clusterInstance) + + // testing filtered replication: insert a bunch of data on shard 1, check we get most of it after a few seconds, + // wait for binlog server timeout, check we get all of it. + log.Debug("Inserting lots of data on source shard") + insertLots(100, 0, *shard1Master, tableName, fixedParentID, keyspaceName) + log.Debug("Executing MultiValue Insert Queries") + execMultiShardDmls(t, keyspaceName) + + // Checking 100 percent of data is sent quickly + assert.True(t, checkLotsTimeout(t, 100, 0, tableName, keyspaceName, shardingKeyType)) + // Checking no data was sent the wrong way + checkLotsNotPresent(t, 100, 0, tableName, keyspaceName, shardingKeyType) + + // Checking MultiValue Insert Queries + checkMultiShardValues(t, keyspaceName, shardingKeyType) + sharding.CheckBinlogPlayerVars(t, *shard2Master, []string{shard1Ks}, 30) + sharding.CheckBinlogPlayerVars(t, *shard3Master, []string{shard1Ks}, 30) + + sharding.CheckBinlogServerVars(t, *shard1Replica1, 100, 100, false) + + // use vtworker to compare the data (after health-checking the destination + // rdonly tablets so discovery works) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", shard3Rdonly.Alias) + require.Nil(t, err) + + // use vtworker to compare the data + clusterInstance.VtworkerProcess.Cell = cell1 + + // Compare using SplitDiff + log.Debug("Running vtworker SplitDiff") + err = clusterInstance.VtworkerProcess.ExecuteVtworkerCommand(clusterInstance.GetAndReservePort(), + clusterInstance.GetAndReservePort(), + "--use_v3_resharding_mode=true", + "SplitDiff", + "--exclude_tables", "unrelated", + "--min_healthy_rdonly_tablets", "1", + shard3Ks) + require.Nil(t, err) + + // Compare using MultiSplitDiff + log.Debug("Running vtworker MultiSplitDiff") + err = clusterInstance.VtworkerProcess.ExecuteVtworkerCommand(clusterInstance.GetAndReservePort(), + clusterInstance.GetAndReservePort(), + "--use_v3_resharding_mode=true", + "MultiSplitDiff", + "--exclude_tables", "unrelated", + shard1Ks) + require.Nil(t, err) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", shard1Rdonly.Alias, "rdonly") + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", shard3Rdonly.Alias, "rdonly") + require.Nil(t, err) + + // get status for destination master tablets, make sure we have it all + sharding.CheckRunningBinlogPlayer(t, *shard2Master, 436, 216) + sharding.CheckRunningBinlogPlayer(t, *shard3Master, 456, 216) + + // tests a failover switching serving to a different replica + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", shard1Replica2.Alias, "replica") + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", shard1Replica1.Alias, "spare") + require.Nil(t, err) + + err = shard1Replica2.VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + err = shard1Replica1.VttabletProcess.WaitForTabletType("NOT_SERVING") + require.Nil(t, err) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", shard1Replica2.Alias) + require.Nil(t, err) + + // test data goes through again + log.Debug("Inserting lots of data on source shard") + insertLots(100, 100, *shard1Master, tableName, fixedParentID, keyspaceName) + log.Debug("Checking 100 percent of data was sent quickly") + assert.True(t, checkLotsTimeout(t, 100, 100, tableName, keyspaceName, shardingKeyType)) + + sharding.CheckBinlogServerVars(t, *shard1Replica2, 80, 80, false) + + // check we can't migrate the master just yet + err = clusterInstance.VtctlclientProcess.ExecuteCommand("MigrateServedTypes", shard1Ks, "master") + require.Error(t, err, "MigrateServedTypes should fail") + + // check query service is off on master 2 and master 3, as filtered replication is enabled. + // Even health check that is enabled on master 3 should not interfere (we run it to be sure). + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", shard3Master.Alias) + require.Nil(t, err) + + for _, master := range []cluster.Vttablet{*shard2Master, *shard3Master} { + sharding.CheckTabletQueryService(t, master, "NOT_SERVING", false, *clusterInstance) + streamHealth, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput( + "VtTabletStreamHealth", + "-count", "1", master.Alias) + require.Nil(t, err) + log.Debug("Got health: ", streamHealth) + + var streamHealthResponse querypb.StreamHealthResponse + err = json.Unmarshal([]byte(streamHealth), &streamHealthResponse) + require.Nil(t, err) + assert.Equal(t, streamHealthResponse.Serving, false) + assert.NotNil(t, streamHealthResponse.RealtimeStats) + + } + + // check the destination master 3 is healthy, even though its query + // service is not running (if not healthy this would exception out) + sharding.VerifyTabletHealth(t, *shard3Master, hostname) + + // now serve rdonly from the split shards, in cell1 only + err = clusterInstance.VtctlclientProcess.ExecuteCommand( + "MigrateServedTypes", fmt.Sprintf("--cells=%s", cell1), + shard1Ks, "rdonly") + require.Nil(t, err) + + // check srv keyspace + expectedPartitions = map[topodata.TabletType][]string{} + expectedPartitions[topodata.TabletType_MASTER] = []string{shard0.Name, shard1.Name} + expectedPartitions[topodata.TabletType_RDONLY] = []string{shard0.Name, shard2.Name, shard3.Name} + expectedPartitions[topodata.TabletType_REPLICA] = []string{shard0.Name, shard1.Name} + sharding.CheckSrvKeyspace(t, cell1, keyspaceName, "", 0, expectedPartitions, *clusterInstance) + + // Cell 2 is not affected + expectedPartitions = map[topodata.TabletType][]string{} + expectedPartitions[topodata.TabletType_MASTER] = []string{shard0.Name, shard1.Name} + expectedPartitions[topodata.TabletType_RDONLY] = []string{shard0.Name, shard1.Name} + expectedPartitions[topodata.TabletType_REPLICA] = []string{shard0.Name, shard1.Name} + sharding.CheckSrvKeyspace(t, cell2, keyspaceName, "", 0, expectedPartitions, *clusterInstance) + + sharding.CheckTabletQueryService(t, *shard0RdonlyZ2, "SERVING", false, *clusterInstance) + sharding.CheckTabletQueryService(t, *shard1RdonlyZ2, "SERVING", false, *clusterInstance) + sharding.CheckTabletQueryService(t, *shard1Rdonly, "NOT_SERVING", true, *clusterInstance) + + // Shouldn't be able to rebuild keyspace graph while migration is on going + // (i.e there are records that have tablet controls set) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", keyspaceName) + require.Error(t, err, "Error expected") + + // rerun migrate to ensure it doesn't fail + // skip refresh to make it go faster + err = clusterInstance.VtctlclientProcess.ExecuteCommand( + "MigrateServedTypes", + fmt.Sprintf("--cells=%s", cell1), + "-skip-refresh-state=true", + shard1Ks, "rdonly") + require.Nil(t, err) + + // now serve rdonly from the split shards, everywhere + err = clusterInstance.VtctlclientProcess.ExecuteCommand( + "MigrateServedTypes", + shard1Ks, "rdonly") + require.Nil(t, err) + + expectedPartitions = map[topodata.TabletType][]string{} + expectedPartitions[topodata.TabletType_MASTER] = []string{shard0.Name, shard1.Name} + expectedPartitions[topodata.TabletType_RDONLY] = []string{shard0.Name, shard2.Name, shard3.Name} + expectedPartitions[topodata.TabletType_REPLICA] = []string{shard0.Name, shard1.Name} + sharding.CheckSrvKeyspace(t, cell1, keyspaceName, "", 0, expectedPartitions, *clusterInstance) + // Cell 2 is also changed + sharding.CheckSrvKeyspace(t, cell2, keyspaceName, "", 0, expectedPartitions, *clusterInstance) + + sharding.CheckTabletQueryService(t, *shard0RdonlyZ2, "SERVING", false, *clusterInstance) + sharding.CheckTabletQueryService(t, *shard1RdonlyZ2, "NOT_SERVING", true, *clusterInstance) + sharding.CheckTabletQueryService(t, *shard1Rdonly, "NOT_SERVING", true, *clusterInstance) + + // rerun migrate to ensure it doesn't fail + // skip refresh to make it go faster + err = clusterInstance.VtctlclientProcess.ExecuteCommand( + "MigrateServedTypes", + "-skip-refresh-state=true", + shard1Ks, "rdonly") + require.Nil(t, err) + + // then serve replica from the split shards + destinationShards := []cluster.Shard{*shard2, *shard3} + err = clusterInstance.VtctlclientProcess.ExecuteCommand( + "MigrateServedTypes", shard1Ks, "replica") + require.Nil(t, err) + + expectedPartitions = map[topodata.TabletType][]string{} + expectedPartitions[topodata.TabletType_MASTER] = []string{shard0.Name, shard1.Name} + expectedPartitions[topodata.TabletType_RDONLY] = []string{shard0.Name, shard2.Name, shard3.Name} + expectedPartitions[topodata.TabletType_REPLICA] = []string{shard0.Name, shard2.Name, shard3.Name} + sharding.CheckSrvKeyspace(t, cell1, keyspaceName, "", 0, expectedPartitions, *clusterInstance) + + // move replica back and forth + err = clusterInstance.VtctlclientProcess.ExecuteCommand( + "MigrateServedTypes", "-reverse", + shard1Ks, "replica") + require.Nil(t, err) + + // After a backwards migration, queryservice should be enabled on + // source and disabled on destinations + sharding.CheckTabletQueryService(t, *shard1Replica2, "SERVING", false, *clusterInstance) + + // Destination tablets would have query service disabled for other reasons than the migration, + // so check the shard record instead of the tablets directly. + sharding.CheckShardQueryServices(t, *clusterInstance, destinationShards, cell1, keyspaceName, + topodata.TabletType_REPLICA, false) + sharding.CheckShardQueryServices(t, *clusterInstance, destinationShards, cell2, keyspaceName, + topodata.TabletType_REPLICA, false) + + expectedPartitions = map[topodata.TabletType][]string{} + expectedPartitions[topodata.TabletType_MASTER] = []string{shard0.Name, shard1.Name} + expectedPartitions[topodata.TabletType_RDONLY] = []string{shard0.Name, shard2.Name, shard3.Name} + expectedPartitions[topodata.TabletType_REPLICA] = []string{shard0.Name, shard1.Name} + sharding.CheckSrvKeyspace(t, cell1, keyspaceName, "", 0, expectedPartitions, *clusterInstance) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand( + "MigrateServedTypes", shard1Ks, "replica") + require.Nil(t, err) + // After a forwards migration, queryservice should be disabled on + // source and enabled on destinations + sharding.CheckTabletQueryService(t, *shard1Replica2, "NOT_SERVING", true, *clusterInstance) + // Destination tablets would have query service disabled for other reasons than the migration, + // so check the shard record instead of the tablets directly + sharding.CheckShardQueryServices(t, *clusterInstance, destinationShards, cell1, keyspaceName, + topodata.TabletType_REPLICA, true) + sharding.CheckShardQueryServices(t, *clusterInstance, destinationShards, cell2, keyspaceName, + topodata.TabletType_REPLICA, true) + + expectedPartitions = map[topodata.TabletType][]string{} + expectedPartitions[topodata.TabletType_MASTER] = []string{shard0.Name, shard1.Name} + expectedPartitions[topodata.TabletType_RDONLY] = []string{shard0.Name, shard2.Name, shard3.Name} + expectedPartitions[topodata.TabletType_REPLICA] = []string{shard0.Name, shard2.Name, shard3.Name} + sharding.CheckSrvKeyspace(t, cell1, keyspaceName, "", 0, expectedPartitions, *clusterInstance) + + // reparent shard2 to shard2Replica1, then insert more data and see it flow through still + err = clusterInstance.VtctlclientProcess.ExecuteCommand("PlannedReparentShard", "-keyspace_shard", shard2Ks, + "-new_master", shard2Replica1.Alias) + require.Nil(t, err) + + // update our test variables to point at the new master + tmp := shard2Master + shard2Master = shard2Replica1 + shard2Replica1 = tmp + + // Insert another set of the data and see it flow through + insertLots(100, 200, *shard1.MasterTablet(), tableName, fixedParentID, keyspaceName) + // Checking 100 percent of data is sent fairly quickly + assert.True(t, checkLotsTimeout(t, 100, 200, tableName, keyspaceName, shardingKeyType)) + + // Compare using SplitDiff + log.Debug("Running vtworker SplitDiff") + err = clusterInstance.VtworkerProcess.ExecuteVtworkerCommand(clusterInstance.GetAndReservePort(), + clusterInstance.GetAndReservePort(), + "--use_v3_resharding_mode=true", + "SplitDiff", + "--exclude_tables", "unrelated", + "--min_healthy_rdonly_tablets", "1", + shard3Ks) + require.Nil(t, err) + + // Compare using MultiSplitDiff + log.Debug("Running vtworker MultiSplitDiff") + err = clusterInstance.VtworkerProcess.ExecuteVtworkerCommand(clusterInstance.GetAndReservePort(), + clusterInstance.GetAndReservePort(), + "--use_v3_resharding_mode=true", + "MultiSplitDiff", + "--exclude_tables", "unrelated", + shard1Ks) + require.Nil(t, err) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", shard1Rdonly.Alias, "rdonly") + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", shard3Rdonly.Alias, "rdonly") + require.Nil(t, err) + + // going to migrate the master now + + // mock with the SourceShard records to test 'vtctl SourceShardDelete' and 'vtctl SourceShardAdd' + err = clusterInstance.VtctlclientProcess.ExecuteCommand("SourceShardDelete", shard3Ks, "1") + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("SourceShardAdd", "--key_range=80-", + shard3Ks, "1", shard1Ks) + require.Nil(t, err) + + // CancelResharding should fail because migration has started. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("CancelResharding", shard1Ks, "1") + require.Error(t, err) + + // do a Migrate that will fail waiting for replication + // which should cause the Migrate to be canceled and the source + // master to be serving again. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("MigrateServedTypes", + "-filtered_replication_wait_time", "0s", shard1Ks, "master") + require.Error(t, err) + + expectedPartitions = map[topodata.TabletType][]string{} + expectedPartitions[topodata.TabletType_MASTER] = []string{shard0.Name, shard1.Name} + expectedPartitions[topodata.TabletType_RDONLY] = []string{shard0.Name, shard2.Name, shard3.Name} + expectedPartitions[topodata.TabletType_REPLICA] = []string{shard0.Name, shard2.Name, shard3.Name} + sharding.CheckSrvKeyspace(t, cell1, keyspaceName, "", 0, expectedPartitions, *clusterInstance) + + sharding.CheckTabletQueryService(t, *shard1Master, "SERVING", false, *clusterInstance) + + // sabotage master migration and make it fail in an unfinished state. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("SetShardTabletControl", + "-blacklisted_tables=t", + shard3Ks, "master") + require.Nil(t, err) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("MigrateServedTypes", + shard1Ks, "master") + require.Error(t, err) + + // Query service is disabled in source shard as failure occurred after point of no return + sharding.CheckTabletQueryService(t, *shard1Master, "NOT_SERVING", true, *clusterInstance) + + // Global topology records should not change as migration did not succeed + shardInfo := sharding.GetShardInfo(t, shard1Ks, *clusterInstance) + assert.True(t, shardInfo.GetIsMasterServing(), "source shards should be set in destination shard") + + shardInfo = sharding.GetShardInfo(t, shard3Ks, *clusterInstance) + assert.Equal(t, 1, len(shardInfo.GetSourceShards()), "source shards should be set in destination shard") + assert.False(t, shardInfo.GetIsMasterServing(), "source shards should be set in destination shard") + + shardInfo = sharding.GetShardInfo(t, shard2Ks, *clusterInstance) + assert.Equal(t, 1, len(shardInfo.GetSourceShards()), "source shards should be set in destination shard") + assert.False(t, shardInfo.GetIsMasterServing(), "source shards should be set in destination shard") + + // remove sabotage, but make it fail early. This should not result in the source master serving, + // because this failure is past the point of no return. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("SetShardTabletControl", "-blacklisted_tables=t", + "-remove", shard3Ks, "master") + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("MigrateServedTypes", + "-filtered_replication_wait_time", "0s", shard1Ks, "master") + require.Error(t, err) + + sharding.CheckTabletQueryService(t, *shard1Master, "NOT_SERVING", true, *clusterInstance) + + // do the migration that's expected to succeed + err = clusterInstance.VtctlclientProcess.ExecuteCommand("MigrateServedTypes", + shard1Ks, "master") + require.Nil(t, err) + expectedPartitions = map[topodata.TabletType][]string{} + expectedPartitions[topodata.TabletType_MASTER] = []string{shard0.Name, shard2.Name, shard3.Name} + expectedPartitions[topodata.TabletType_RDONLY] = []string{shard0.Name, shard2.Name, shard3.Name} + expectedPartitions[topodata.TabletType_REPLICA] = []string{shard0.Name, shard2.Name, shard3.Name} + sharding.CheckSrvKeyspace(t, cell1, keyspaceName, "", 0, expectedPartitions, *clusterInstance) + + sharding.CheckTabletQueryService(t, *shard1Master, "NOT_SERVING", true, *clusterInstance) + + // check destination shards are serving + sharding.CheckTabletQueryService(t, *shard2Master, "SERVING", false, *clusterInstance) + sharding.CheckTabletQueryService(t, *shard3Master, "SERVING", false, *clusterInstance) + + // check the binlog players are gone now + err = shard2Master.VttabletProcess.WaitForBinLogPlayerCount(0) + require.Nil(t, err) + err = shard3Master.VttabletProcess.WaitForBinLogPlayerCount(0) + require.Nil(t, err) + + // test reverse_replication + // start with inserting a row in each destination shard + insertValue(t, shard2Master, keyspaceName, "resharding2", 2, "msg2", key2) + insertValue(t, shard3Master, keyspaceName, "resharding2", 3, "msg3", key3) + + // ensure the rows are not present yet + checkValues(t, *shard1Master, []string{"INT64(86)", "INT64(2)", `VARCHAR("msg2")`, fmt.Sprintf("UINT64(%d)", key2)}, + 2, false, "resharding2", fixedParentID, keyspaceName, shardingKeyType, nil) + checkValues(t, *shard1Master, []string{"INT64(86)", "INT64(3)", `VARCHAR("msg3")`, fmt.Sprintf("UINT64(%d)", key3)}, + 3, false, "resharding2", fixedParentID, keyspaceName, shardingKeyType, nil) + + // repeat the migration with reverse_replication + err = clusterInstance.VtctlclientProcess.ExecuteCommand("MigrateServedTypes", "-reverse_replication=true", + shard1Ks, "master") + require.Nil(t, err) + // look for the rows in the original master after a short wait + time.Sleep(1 * time.Second) + checkValues(t, *shard1Master, []string{"INT64(86)", "INT64(2)", `VARCHAR("msg2")`, fmt.Sprintf("UINT64(%d)", key2)}, + 2, true, "resharding2", fixedParentID, keyspaceName, shardingKeyType, nil) + checkValues(t, *shard1Master, []string{"INT64(86)", "INT64(3)", `VARCHAR("msg3")`, fmt.Sprintf("UINT64(%d)", key3)}, + 3, true, "resharding2", fixedParentID, keyspaceName, shardingKeyType, nil) + + // retry the migration to ensure it now fails + err = clusterInstance.VtctlclientProcess.ExecuteCommand( + "MigrateServedTypes", + "-reverse_replication=true", + shard1Ks, "master") + require.Error(t, err) + + // CancelResharding should now succeed + err = clusterInstance.VtctlclientProcess.ExecuteCommand("CancelResharding", shard1Ks) + require.Nil(t, err) + err = shard1Master.VttabletProcess.WaitForBinLogPlayerCount(0) + require.Nil(t, err) + + // delete the original tablets in the original shard + for _, tablet := range []cluster.Vttablet{*shard1Master, *shard1Replica1, *shard1Replica2, *shard1Rdonly, *shard1RdonlyZ2} { + _ = tablet.MysqlctlProcess.Stop() + _ = tablet.VttabletProcess.TearDown() + } + + for _, tablet := range []cluster.Vttablet{*shard1Replica1, *shard1Replica2, *shard1Rdonly, *shard1RdonlyZ2} { + err = clusterInstance.VtctlclientProcess.ExecuteCommand("DeleteTablet", tablet.Alias) + require.Nil(t, err) + } + err = clusterInstance.VtctlclientProcess.ExecuteCommand("DeleteTablet", "-allow_master", shard1Master.Alias) + require.Nil(t, err) + + // rebuild the serving graph, all mentions of the old shards should be gone + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", keyspaceName) + require.Nil(t, err) + + // test RemoveShardCell + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RemoveShardCell", shard0Ks, cell1) + require.Error(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RemoveShardCell", shard1Ks, cell1) + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RemoveShardCell", shard1Ks, cell2) + require.Nil(t, err) + + shardInfo = sharding.GetShardInfo(t, shard1Ks, *clusterInstance) + assert.Empty(t, shardInfo.GetTabletControls(), "cells not in shard ") + + // delete the original shard + err = clusterInstance.VtctlclientProcess.ExecuteCommand("DeleteShard", shard1Ks) + require.Nil(t, err) + + // make sure we can't delete the destination shard now that it's serving + err = clusterInstance.VtctlclientProcess.ExecuteCommand("DeleteShard", shard2Ks) + require.Error(t, err) + +} + +func insertStartupValues(t *testing.T) { + insertSQL := fmt.Sprintf(insertTabletTemplateKsID, "resharding1", fixedParentID, 1, "msg1", key1, key1, 1) + sharding.InsertToTablet(t, insertSQL, *shard0.MasterTablet(), keyspaceName, false) + + insertSQL = fmt.Sprintf(insertTabletTemplateKsID, "resharding1", fixedParentID, 2, "msg2", key2, key2, 2) + sharding.InsertToTablet(t, insertSQL, *shard1.MasterTablet(), keyspaceName, false) + + insertSQL = fmt.Sprintf(insertTabletTemplateKsID, "resharding1", fixedParentID, 3, "msg3", key3, key3, 3) + sharding.InsertToTablet(t, insertSQL, *shard1.MasterTablet(), keyspaceName, false) + + insertSQL = fmt.Sprintf(insertTabletTemplateKsID, "resharding3", fixedParentID, 1, "a", key1, key1, 1) + sharding.InsertToTablet(t, insertSQL, *shard0.MasterTablet(), keyspaceName, false) + + insertSQL = fmt.Sprintf(insertTabletTemplateKsID, "resharding3", fixedParentID, 2, "b", key2, key2, 2) + sharding.InsertToTablet(t, insertSQL, *shard1.MasterTablet(), keyspaceName, false) + + insertSQL = fmt.Sprintf(insertTabletTemplateKsID, "resharding3", fixedParentID, 3, "c", key3, key3, 3) + sharding.InsertToTablet(t, insertSQL, *shard1.MasterTablet(), keyspaceName, false) + + insertSQL = fmt.Sprintf(insertTabletTemplateKsID, "no_pk", fixedParentID, 1, "msg1", key5, key5, 1) + sharding.InsertToTablet(t, insertSQL, *shard1.MasterTablet(), keyspaceName, false) +} + +func insertValue(t *testing.T, tablet *cluster.Vttablet, keyspaceName string, tableName string, id int, msg string, ksID uint64) { + insertSQL := fmt.Sprintf(insertTabletTemplateKsID, tableName, fixedParentID, id, msg, ksID, ksID, id) + sharding.InsertToTablet(t, insertSQL, *tablet, keyspaceName, false) +} + +func execMultiShardDmls(t *testing.T, keyspaceName string) { + ids := []int{10000001, 10000002, 10000003} + msgs := []string{"msg-id10000001", "msg-id10000002", "msg-id10000003"} + ksIds := []uint64{key2, key3, key4} + sharding.InsertMultiValues(t, *shard1.MasterTablet(), keyspaceName, "resharding1", fixedParentID, ids, msgs, ksIds) + + ids = []int{10000004, 10000005} + msgs = []string{"msg-id10000004", "msg-id10000005"} + ksIds = []uint64{key3, key4} + sharding.InsertMultiValues(t, *shard1.MasterTablet(), keyspaceName, "resharding1", fixedParentID, ids, msgs, ksIds) + + ids = []int{10000011, 10000012, 10000013} + msgs = []string{"msg-id10000011", "msg-id10000012", "msg-id10000013"} + ksIds = []uint64{key2, key3, key4} + sharding.InsertMultiValues(t, *shard1.MasterTablet(), keyspaceName, "resharding1", fixedParentID, ids, msgs, ksIds) + + // This update targets two shards. + sql := `update resharding1 set msg="update1" where parent_id=86 and id in (10000011,10000012)` + _, _ = shard1.MasterTablet().VttabletProcess.QueryTablet(sql, keyspaceName, true) + + // This update targets one shard. + sql = `update resharding1 set msg="update1" where parent_id=86 and id in (10000013)` + _, _ = shard1.MasterTablet().VttabletProcess.QueryTablet(sql, keyspaceName, true) + + ids = []int{10000014, 10000015, 10000016} + msgs = []string{"msg-id10000014", "msg-id10000015", "msg-id10000016"} + ksIds = []uint64{key2, key3, key4} + sharding.InsertMultiValues(t, *shard1.MasterTablet(), keyspaceName, "resharding1", fixedParentID, ids, msgs, ksIds) + + // This delete targets two shards. + sql = `delete from resharding1 where parent_id =86 and id in (10000014, 10000015)` + _, _ = shard1.MasterTablet().VttabletProcess.QueryTablet(sql, keyspaceName, true) + // This delete targets one shard. + sql = `delete from resharding1 where parent_id =86 and id in (10000016)` + _, _ = shard1.MasterTablet().VttabletProcess.QueryTablet(sql, keyspaceName, true) + + // repeat DMLs for table with msg as bit(8) + ids = []int{10000001, 10000002, 10000003} + msgs = []string{"a", "b", "c"} + ksIds = []uint64{key2, key3, key4} + sharding.InsertMultiValues(t, *shard1.MasterTablet(), keyspaceName, "resharding3", fixedParentID, ids, msgs, ksIds) + + ids = []int{10000004, 10000005} + msgs = []string{"d", "e"} + ksIds = []uint64{key3, key4} + sharding.InsertMultiValues(t, *shard1.MasterTablet(), keyspaceName, "resharding3", fixedParentID, ids, msgs, ksIds) + + ids = []int{10000011, 10000012, 10000013} + msgs = []string{"k", "l", "m"} + ksIds = []uint64{key2, key3, key4} + sharding.InsertMultiValues(t, *shard1.MasterTablet(), keyspaceName, "resharding3", fixedParentID, ids, msgs, ksIds) + + // This update targets two shards. + sql = `update resharding3 set msg="g" where parent_id=86 and id in (10000011, 10000012)` + _, _ = shard1.MasterTablet().VttabletProcess.QueryTablet(sql, keyspaceName, true) + + // This update targets one shard. + sql = `update resharding3 set msg="h" where parent_id=86 and id in (10000013)` + _, _ = shard1.MasterTablet().VttabletProcess.QueryTablet(sql, keyspaceName, true) + + ids = []int{10000014, 10000015, 10000016} + msgs = []string{"n", "o", "p"} + ksIds = []uint64{key2, key3, key4} + sharding.InsertMultiValues(t, *shard1.MasterTablet(), keyspaceName, "resharding3", fixedParentID, ids, msgs, ksIds) + + // This delete targets two shards. + sql = `delete from resharding3 where parent_id =86 and id in (10000014, 10000015)` + _, _ = shard1.MasterTablet().VttabletProcess.QueryTablet(sql, keyspaceName, true) + // This delete targets one shard. + sql = `delete from resharding3 where parent_id =86 and id in (10000016)` + _, _ = shard1.MasterTablet().VttabletProcess.QueryTablet(sql, keyspaceName, true) + +} + +func checkStartupValues(t *testing.T, shardingKeyType querypb.Type) { + // check first value is in the right shard + for _, tablet := range shard2.Vttablets { + checkValues(t, *tablet, []string{"INT64(86)", "INT64(2)", `VARCHAR("msg2")`, fmt.Sprintf("UINT64(%d)", key2)}, + 2, true, "resharding1", fixedParentID, keyspaceName, shardingKeyType, nil) + checkValues(t, *tablet, []string{"INT64(86)", "INT64(2)", `BIT("b")`, fmt.Sprintf("UINT64(%d)", key2)}, + 2, true, "resharding3", fixedParentID, keyspaceName, shardingKeyType, nil) + } + for _, tablet := range shard3.Vttablets { + checkValues(t, *tablet, []string{"INT64(86)", "INT64(2)", `VARCHAR("msg2")`, fmt.Sprintf("UINT64(%d)", key2)}, + 2, false, "resharding1", fixedParentID, keyspaceName, shardingKeyType, nil) + checkValues(t, *tablet, []string{"INT64(86)", "INT64(2)", `BIT("b")`, fmt.Sprintf("UINT64(%d)", key2)}, + 2, false, "resharding3", fixedParentID, keyspaceName, shardingKeyType, nil) + } + // check first value is in the right shard + for _, tablet := range shard2.Vttablets { + checkValues(t, *tablet, []string{"INT64(86)", "INT64(3)", `VARCHAR("msg3")`, fmt.Sprintf("UINT64(%d)", key3)}, + 3, false, "resharding1", fixedParentID, keyspaceName, shardingKeyType, nil) + checkValues(t, *tablet, []string{"INT64(86)", "INT64(3)", `BIT("c")`, fmt.Sprintf("UINT64(%d)", key3)}, + 3, false, "resharding3", fixedParentID, keyspaceName, shardingKeyType, nil) + } + for _, tablet := range shard3.Vttablets { + checkValues(t, *tablet, []string{"INT64(86)", "INT64(3)", `VARCHAR("msg3")`, fmt.Sprintf("UINT64(%d)", key3)}, + 3, true, "resharding1", fixedParentID, keyspaceName, shardingKeyType, nil) + checkValues(t, *tablet, []string{"INT64(86)", "INT64(3)", `BIT("c")`, fmt.Sprintf("UINT64(%d)", key3)}, + 3, true, "resharding3", fixedParentID, keyspaceName, shardingKeyType, nil) + } + + // Check for no_pk table + for _, tablet := range shard2.Vttablets { + checkValues(t, *tablet, []string{"INT64(86)", "INT64(1)", `VARCHAR("msg1")`, fmt.Sprintf("UINT64(%d)", key5)}, + 1, true, "no_pk", fixedParentID, keyspaceName, shardingKeyType, nil) + } + for _, tablet := range shard3.Vttablets { + checkValues(t, *tablet, []string{"INT64(86)", "INT64(1)", `BIT("msg1")`, fmt.Sprintf("UINT64(%d)", key5)}, + 1, false, "no_pk", fixedParentID, keyspaceName, shardingKeyType, nil) + } +} + +// checkLotsNotPresent verifies that no rows should be present in vttablet +func checkLotsNotPresent(t *testing.T, count uint64, base uint64, table string, keyspaceName string, keyType querypb.Type) { + shard2Replica2 := *shard2.Vttablets[2] + shard3Replica1 := *shard3.Vttablets[1] + + ctx := context.Background() + dbParams := getDBparams(shard2Replica2, keyspaceName) + dbConn1, _ := mysql.Connect(ctx, &dbParams) + defer dbConn1.Close() + + dbParams = getDBparams(shard3Replica1, keyspaceName) + dbConn2, _ := mysql.Connect(ctx, &dbParams) + defer dbConn2.Close() + + var i uint64 + //var count uint64 = 1000 + for i = 0; i < count; i++ { + assert.False(t, checkValues(t, shard3Replica1, []string{"INT64(86)", + fmt.Sprintf("INT64(%d)", 10000+base+i), + fmt.Sprintf(`VARCHAR("msg-range1-%d")`, 10000+base+i), + fmt.Sprintf("UINT64(%d)", key5)}, + 10000+base+i, false, table, fixedParentID, keyspaceName, keyType, dbConn2)) + + assert.False(t, checkValues(t, shard2Replica2, []string{"INT64(86)", + fmt.Sprintf("INT64(%d)", 20000+base+i), + fmt.Sprintf(`VARCHAR("msg-range2-%d")`, 20000+base+i), + fmt.Sprintf("UINT64(%d)", key4)}, + 20000+base+i, false, table, fixedParentID, keyspaceName, keyType, dbConn1)) + } +} + +// checkLotsTimeout waits till all values are inserted +func checkLotsTimeout(t *testing.T, count uint64, base uint64, table string, keyspaceName string, keyType querypb.Type) bool { + timeout := time.Now().Add(10 * time.Second) + for time.Now().Before(timeout) { + percentFound := checkLots(t, count, base, table, keyspaceName, keyType) + if percentFound == 100 { + return true + } + time.Sleep(300 * time.Millisecond) + } + return false +} + +func checkLots(t *testing.T, count uint64, base uint64, table string, keyspaceName string, keyType querypb.Type) float32 { + shard2Replica2 := *shard2.Vttablets[2] + shard3Replica1 := *shard3.Vttablets[1] + + ctx := context.Background() + dbParams := getDBparams(shard2Replica2, keyspaceName) + dbConn1, _ := mysql.Connect(ctx, &dbParams) + defer dbConn1.Close() + + dbParams = getDBparams(shard3Replica1, keyspaceName) + dbConn2, _ := mysql.Connect(ctx, &dbParams) + defer dbConn2.Close() + + var isFound bool + var totalFound int + var i uint64 + for i = 0; i < count; i++ { + isFound = checkValues(t, shard2Replica2, []string{"INT64(86)", + fmt.Sprintf("INT64(%d)", 10000+base+i), + fmt.Sprintf(`VARCHAR("msg-range1-%d")`, 10000+base+i), + fmt.Sprintf("UINT64(%d)", key5)}, + 10000+base+i, true, table, fixedParentID, keyspaceName, keyType, dbConn1) + if isFound { + totalFound++ + } + + isFound = checkValues(t, shard3Replica1, []string{"INT64(86)", + fmt.Sprintf("INT64(%d)", 20000+base+i), + fmt.Sprintf(`VARCHAR("msg-range2-%d")`, 20000+base+i), + fmt.Sprintf("UINT64(%d)", key4)}, + 20000+base+i, true, table, fixedParentID, keyspaceName, keyType, dbConn2) + if isFound { + totalFound++ + } + } + return float32(totalFound * 100 / int(count) / 2) +} + +func checkValues(t *testing.T, vttablet cluster.Vttablet, values []string, id uint64, exists bool, tableName string, + parentID int, ks string, keyType querypb.Type, dbConn *mysql.Conn) bool { + query := fmt.Sprintf("select parent_id, id, msg, custom_ksid_col from %s where parent_id = %d and id = %d", tableName, parentID, id) + var result *sqltypes.Result + var err error + if dbConn != nil { + result, err = dbConn.ExecuteFetch(query, 1000, true) + require.Nil(t, err) + } else { + result, err = vttablet.VttabletProcess.QueryTablet(query, ks, true) + require.Nil(t, err) + } + + isFound := false + if exists && len(result.Rows) > 0 { + isFound = assert.Equal(t, result.Rows[0][0].String(), values[0]) + isFound = isFound && assert.Equal(t, result.Rows[0][1].String(), values[1]) + isFound = isFound && assert.Equal(t, result.Rows[0][2].String(), values[2]) + if keyType == querypb.Type_VARBINARY { + r := strings.NewReplacer("UINT64(", "VARBINARY(\"", ")", "\")") + expected := r.Replace(values[3]) + isFound = isFound && assert.Equal(t, result.Rows[0][3].String(), expected) + } else { + isFound = isFound && assert.Equal(t, result.Rows[0][3].String(), values[3]) + } + + } else { + assert.Equal(t, len(result.Rows), 0) + } + return isFound +} + +func checkMultiShardValues(t *testing.T, keyspaceName string, keyType querypb.Type) { + //Shard2 master, replica1 and replica 2 + shard2Tablets := []cluster.Vttablet{*shard2.Vttablets[0], *shard2.Vttablets[1], *shard2.Vttablets[2]} + checkMultiDbs(t, shard2Tablets, "resharding1", keyspaceName, keyType, 10000001, "msg-id10000001", key2, true) + checkMultiDbs(t, shard2Tablets, "resharding1", keyspaceName, keyType, 10000002, "msg-id10000002", key3, false) + checkMultiDbs(t, shard2Tablets, "resharding1", keyspaceName, keyType, 10000003, "msg-id10000003", key4, false) + checkMultiDbs(t, shard2Tablets, "resharding1", keyspaceName, keyType, 10000004, "msg-id10000004", key3, false) + checkMultiDbs(t, shard2Tablets, "resharding1", keyspaceName, keyType, 10000005, "msg-id10000005", key4, false) + + //Shard 3 master and replica + shard3Tablets := []cluster.Vttablet{*shard3.Vttablets[0], *shard3.Vttablets[1]} + checkMultiDbs(t, shard3Tablets, "resharding1", keyspaceName, keyType, 10000001, "msg-id10000001", key2, false) + checkMultiDbs(t, shard3Tablets, "resharding1", keyspaceName, keyType, 10000002, "msg-id10000002", key3, true) + checkMultiDbs(t, shard3Tablets, "resharding1", keyspaceName, keyType, 10000003, "msg-id10000003", key4, true) + checkMultiDbs(t, shard3Tablets, "resharding1", keyspaceName, keyType, 10000004, "msg-id10000004", key3, true) + checkMultiDbs(t, shard3Tablets, "resharding1", keyspaceName, keyType, 10000005, "msg-id10000005", key4, true) + + // Updated values + checkMultiDbs(t, shard2Tablets, "resharding1", keyspaceName, keyType, 10000011, "update1", key2, true) + checkMultiDbs(t, shard3Tablets, "resharding1", keyspaceName, keyType, 10000012, "update1", key3, true) + checkMultiDbs(t, shard3Tablets, "resharding1", keyspaceName, keyType, 10000013, "update2", key4, true) + + allTablets := []cluster.Vttablet{*shard2.Vttablets[0], *shard2.Vttablets[1], *shard2.Vttablets[2], *shard3.Vttablets[0], *shard3.Vttablets[1]} + checkMultiDbs(t, allTablets, "resharding1", keyspaceName, keyType, 10000014, "msg-id10000014", key2, false) + checkMultiDbs(t, allTablets, "resharding1", keyspaceName, keyType, 10000015, "msg-id10000015", key3, false) + checkMultiDbs(t, allTablets, "resharding1", keyspaceName, keyType, 10000016, "msg-id10000016", key6, false) + + // checks for bit(8) table + checkMultiDbs(t, shard2Tablets, "resharding3", keyspaceName, keyType, 10000001, "a", key2, true) + checkMultiDbs(t, shard2Tablets, "resharding3", keyspaceName, keyType, 10000002, "b", key3, false) + checkMultiDbs(t, shard2Tablets, "resharding3", keyspaceName, keyType, 10000003, "c", key4, false) + checkMultiDbs(t, shard2Tablets, "resharding3", keyspaceName, keyType, 10000004, "d", key3, false) + checkMultiDbs(t, shard2Tablets, "resharding3", keyspaceName, keyType, 10000005, "e", key4, false) + + checkMultiDbs(t, shard3Tablets, "resharding3", keyspaceName, keyType, 10000001, "a", key2, false) + checkMultiDbs(t, shard3Tablets, "resharding3", keyspaceName, keyType, 10000002, "b", key3, true) + checkMultiDbs(t, shard3Tablets, "resharding3", keyspaceName, keyType, 10000003, "c", key4, true) + checkMultiDbs(t, shard3Tablets, "resharding3", keyspaceName, keyType, 10000004, "d", key3, true) + checkMultiDbs(t, shard3Tablets, "resharding3", keyspaceName, keyType, 10000005, "e", key4, true) + + // updated values + checkMultiDbs(t, shard2Tablets, "resharding3", keyspaceName, keyType, 10000011, "g", key2, true) + checkMultiDbs(t, shard3Tablets, "resharding3", keyspaceName, keyType, 10000012, "g", key3, true) + checkMultiDbs(t, shard3Tablets, "resharding3", keyspaceName, keyType, 10000013, "h", key4, true) + + checkMultiDbs(t, allTablets, "resharding3", keyspaceName, keyType, 10000014, "n", key2, false) + checkMultiDbs(t, allTablets, "resharding3", keyspaceName, keyType, 10000015, "o", key3, false) + checkMultiDbs(t, allTablets, "resharding3", keyspaceName, keyType, 10000016, "p", key6, false) + +} + +// checkMultiDbs checks the row in multiple dbs +func checkMultiDbs(t *testing.T, vttablets []cluster.Vttablet, tableName string, keyspaceName string, + keyType querypb.Type, id int, msg string, ksID uint64, presentInDb bool) { + + for _, tablet := range vttablets { + checkValues(t, tablet, []string{"INT64(86)", + fmt.Sprintf("INT64(%d)", id), + fmt.Sprintf(`VARCHAR("%s")`, msg), + fmt.Sprintf("UINT64(%d)", ksID)}, + ksID, presentInDb, tableName, fixedParentID, keyspaceName, keyType, nil) + } +} + +// insertLots inserts multiple values to vttablet +func insertLots(count uint64, base uint64, vttablet cluster.Vttablet, table string, parentID int, ks string) { + ctx := context.Background() + dbParams := getDBparams(vttablet, ks) + dbConn, _ := mysql.Connect(ctx, &dbParams) + defer dbConn.Close() + + var query1, query2 string + var i uint64 + for i = 0; i < count; i++ { + query1 = fmt.Sprintf(insertTabletTemplateKsID, table, parentID, 10000+base+i, + fmt.Sprintf("msg-range1-%d", 10000+base+i), key5, key5, 10000+base+i) + query2 = fmt.Sprintf(insertTabletTemplateKsID, table, parentID, 20000+base+i, + fmt.Sprintf("msg-range2-%d", 20000+base+i), key4, key4, 20000+base+i) + + insertToTabletUsingSameConn(query1, dbConn) + insertToTabletUsingSameConn(query2, dbConn) + } +} + +// insertToTabletUsingSameConn inserts a single row to vttablet using existing connection +func insertToTabletUsingSameConn(query string, dbConn *mysql.Conn) { + _, err := dbConn.ExecuteFetch(query, 1000, true) + if err != nil { + fmt.Println(err) + } +} + +func getDBparams(vttablet cluster.Vttablet, ks string) mysql.ConnParams { + dbParams := mysql.ConnParams{ + Uname: "vt_dba", + UnixSocket: path.Join(vttablet.VttabletProcess.Directory, "mysql.sock"), + DbName: "vt_" + ks, + } + return dbParams +} diff --git a/go/test/endtoend/sharding/resharding/string/resharding_string_test.go b/go/test/endtoend/sharding/resharding/string/resharding_string_test.go new file mode 100644 index 00000000000..ccff0481b77 --- /dev/null +++ b/go/test/endtoend/sharding/resharding/string/resharding_string_test.go @@ -0,0 +1,29 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package v3 + +import ( + "testing" + + sharding "vitess.io/vitess/go/test/endtoend/sharding/resharding" +) + +// TestReshardingString - using a VARBINARY column for resharding. +func TestReshardingString(t *testing.T) { + sharding.TestResharding(t, true) + +} diff --git a/go/test/endtoend/sharding/resharding/v3/resharding_v3_test.go b/go/test/endtoend/sharding/resharding/v3/resharding_v3_test.go new file mode 100644 index 00000000000..6805b1c759a --- /dev/null +++ b/go/test/endtoend/sharding/resharding/v3/resharding_v3_test.go @@ -0,0 +1,29 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package v3 + +import ( + "testing" + + sharding "vitess.io/vitess/go/test/endtoend/sharding/resharding" +) + +// TestV3ReSharding - main tests resharding using a INT column +func TestV3ReSharding(t *testing.T) { + sharding.TestResharding(t, false) + +} diff --git a/go/test/endtoend/sharding/verticalsplit/vertical_split_test.go b/go/test/endtoend/sharding/verticalsplit/vertical_split_test.go new file mode 100644 index 00000000000..594df68c590 --- /dev/null +++ b/go/test/endtoend/sharding/verticalsplit/vertical_split_test.go @@ -0,0 +1,739 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package verticalsplit + +import ( + "context" + "flag" + "fmt" + "os/exec" + "path" + "reflect" + "strings" + "testing" + "time" + + "vitess.io/vitess/go/json2" + "vitess.io/vitess/go/vt/vtgate/vtgateconn" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/test/endtoend/cluster" + "vitess.io/vitess/go/test/endtoend/sharding" + "vitess.io/vitess/go/vt/log" + "vitess.io/vitess/go/vt/proto/topodata" + _ "vitess.io/vitess/go/vt/vtgate/grpcvtgateconn" +) + +var ( + clusterInstance *cluster.LocalProcessCluster + sourceKeyspace = "source_keyspace" + destinationKeyspace = "destination_keyspace" + hostname = "localhost" + cellj = "test_nj" + shardName = "0" + createTabletTemplate = ` + create table %s( + id bigint not null, + msg varchar(64), + primary key (id), + index by_msg (msg) + ) Engine=InnoDB;` + createViewTemplate = "create view %s(id, msg) as select id, msg from %s;" + createMoving3NoPkTable = ` + create table moving3_no_pk ( + id bigint not null, + msg varchar(64) + ) Engine=InnoDB;` + tableArr = []string{"moving1", "moving2", "staying1", "staying2"} + insertIndex = 0 + moving1First int + moving2First int + staying1First int + staying2First int + moving3NoPkFirst int +) + +func TestVerticalSplit(t *testing.T) { + defer cluster.PanicHandler(t) + flag.Parse() + code, err := initializeCluster() + if err != nil { + t.Errorf("setup failed with status code %d", code) + } + defer teardownCluster() + + // Adding another cell in the same cluster + err = clusterInstance.TopoProcess.ManageTopoDir("mkdir", "/vitess/"+"test_ca") + require.Nil(t, err) + err = clusterInstance.VtctlProcess.AddCellInfo("test_ca") + require.Nil(t, err) + err = clusterInstance.TopoProcess.ManageTopoDir("mkdir", "/vitess/"+"test_ny") + require.Nil(t, err) + err = clusterInstance.VtctlProcess.AddCellInfo("test_ny") + require.Nil(t, err) + + require.Nil(t, err, "error should be Nil") + + // source keyspace, with 4 tables + sourceShard := clusterInstance.Keyspaces[0].Shards[0] + sourceMasterTablet := *sourceShard.Vttablets[0] + sourceReplicaTablet := *sourceShard.Vttablets[1] + sourceRdOnlyTablet1 := *sourceShard.Vttablets[2] + sourceRdOnlyTablet2 := *sourceShard.Vttablets[3] + sourceKs := fmt.Sprintf("%s/%s", sourceKeyspace, shardName) + + // source tablets init + for _, tablet := range []cluster.Vttablet{sourceMasterTablet, sourceReplicaTablet, sourceRdOnlyTablet1, sourceRdOnlyTablet2} { + err = clusterInstance.VtctlclientProcess.InitTablet(&tablet, cellj, sourceKeyspace, hostname, sourceShard.Name) + require.Nil(t, err) + err = tablet.VttabletProcess.CreateDB(sourceKeyspace) + require.Nil(t, err) + } + + // destination keyspace, with just two tables + destinationShard := clusterInstance.Keyspaces[1].Shards[0] + destinationMasterTablet := *destinationShard.Vttablets[0] + destinationReplicaTablet := *destinationShard.Vttablets[1] + destinationRdOnlyTablet1 := *destinationShard.Vttablets[2] + destinationRdOnlyTablet2 := *destinationShard.Vttablets[3] + + // destination tablets init + for _, tablet := range []cluster.Vttablet{destinationMasterTablet, destinationReplicaTablet, destinationRdOnlyTablet1, destinationRdOnlyTablet2} { + err = clusterInstance.VtctlclientProcess.InitTablet(&tablet, cellj, destinationKeyspace, hostname, destinationShard.Name) + require.Nil(t, err) + err = tablet.VttabletProcess.CreateDB(destinationKeyspace) + require.Nil(t, err) + } + + // RebuildKeyspaceGraph source keyspace + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", sourceKeyspace) + require.Nil(t, err) + + // RebuildKeyspaceGraph destination keyspace + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", destinationKeyspace) + require.Nil(t, err) + + // source schema + for _, tablet := range []cluster.Vttablet{sourceMasterTablet, sourceReplicaTablet, sourceRdOnlyTablet1, sourceRdOnlyTablet2} { + for _, tableName := range tableArr { + _, err := tablet.VttabletProcess.QueryTablet(fmt.Sprintf(createTabletTemplate, tableName), sourceKeyspace, true) + require.Nil(t, err) + } + _, err := tablet.VttabletProcess.QueryTablet(fmt.Sprintf(createViewTemplate, "view1", "moving1"), sourceKeyspace, true) + require.Nil(t, err) + + // RBR (default behaviour) only because Vitess requires the primary key for query rewrites if + // it is running with statement based replication. + _, err = tablet.VttabletProcess.QueryTablet(createMoving3NoPkTable, sourceKeyspace, true) + require.Nil(t, err) + } + + // destination schema + // Insert data directly because vtgate would redirect us. + for _, tablet := range []cluster.Vttablet{destinationMasterTablet, destinationReplicaTablet, destinationRdOnlyTablet1, destinationRdOnlyTablet2} { + _, err = tablet.VttabletProcess.QueryTablet(fmt.Sprintf(createTabletTemplate, "extra1"), destinationKeyspace, true) + require.Nil(t, err) + } + + // source and destination master and replica tablets will be started + for _, tablet := range []cluster.Vttablet{sourceMasterTablet, sourceReplicaTablet, destinationMasterTablet, destinationReplicaTablet} { + _ = tablet.VttabletProcess.Setup() + } + + // rdonly tablets will be started + for _, tablet := range []cluster.Vttablet{sourceRdOnlyTablet1, sourceRdOnlyTablet2, destinationRdOnlyTablet1, destinationRdOnlyTablet2} { + _ = tablet.VttabletProcess.Setup() + } + + // check SrvKeyspace + ksServedFrom := "ServedFrom(master): source_keyspace\nServedFrom(rdonly): source_keyspace\nServedFrom(replica): source_keyspace\n" + checkSrvKeyspaceServedFrom(t, cellj, destinationKeyspace, ksServedFrom, *clusterInstance) + + // reparent to make the tablets work (we use health check, fix their types) + err = clusterInstance.VtctlclientProcess.InitShardMaster(sourceKeyspace, shardName, cellj, sourceMasterTablet.TabletUID) + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.InitShardMaster(destinationKeyspace, shardName, cellj, destinationMasterTablet.TabletUID) + require.Nil(t, err) + + sourceMasterTablet.Type = "master" + destinationMasterTablet.Type = "master" + + for _, tablet := range []cluster.Vttablet{sourceReplicaTablet, destinationReplicaTablet} { + _ = tablet.VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + } + for _, tablet := range []cluster.Vttablet{sourceRdOnlyTablet1, sourceRdOnlyTablet2, destinationRdOnlyTablet1, destinationRdOnlyTablet2} { + _ = tablet.VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + } + + for _, tablet := range []cluster.Vttablet{sourceMasterTablet, destinationMasterTablet, sourceReplicaTablet, destinationReplicaTablet, sourceRdOnlyTablet1, sourceRdOnlyTablet2, destinationRdOnlyTablet1, destinationRdOnlyTablet2} { + assert.Equal(t, tablet.VttabletProcess.GetTabletStatus(), "SERVING") + } + + err = clusterInstance.StartVtgate() + require.Nil(t, err) + + vtParams := mysql.ConnParams{ + Host: clusterInstance.Hostname, + Port: clusterInstance.VtgateMySQLPort, + } + + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + require.Nil(t, err) + defer conn.Close() + + err = clusterInstance.VtgateProcess.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.master", sourceKeyspace, shardName), 1) + require.Nil(t, err) + err = clusterInstance.VtgateProcess.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.replica", sourceKeyspace, shardName), 1) + require.Nil(t, err) + err = clusterInstance.VtgateProcess.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.rdonly", sourceKeyspace, shardName), 2) + require.Nil(t, err) + err = clusterInstance.VtgateProcess.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.master", destinationKeyspace, shardName), 1) + require.Nil(t, err) + err = clusterInstance.VtgateProcess.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.replica", destinationKeyspace, shardName), 1) + require.Nil(t, err) + err = clusterInstance.VtgateProcess.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.rdonly", destinationKeyspace, shardName), 2) + require.Nil(t, err) + + // create the schema on the source keyspace, add some values + insertInitialValues(t, conn, sourceMasterTablet, destinationMasterTablet) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("CopySchemaShard", "--tables", "/moving/,view1", sourceRdOnlyTablet1.Alias, "destination_keyspace/0") + require.Nil(t, err, "CopySchemaShard failed") + + // starting vtworker + httpPort := clusterInstance.GetAndReservePort() + grpcPort := clusterInstance.GetAndReservePort() + clusterInstance.VtworkerProcess = *cluster.VtworkerProcessInstance( + httpPort, + grpcPort, + clusterInstance.TopoPort, + clusterInstance.Hostname, + clusterInstance.TmpDirectory) + + err = clusterInstance.VtworkerProcess.ExecuteVtworkerCommand(httpPort, grpcPort, + "--cell", cellj, + "--command_display_interval", "10ms", + "--use_v3_resharding_mode=true", + "VerticalSplitClone", + "--tables", "/moving/,view1", + "--chunk_count", "10", + "--min_rows_per_chunk", "1", + "--min_healthy_tablets", "1", "destination_keyspace/0") + require.Nil(t, err) + + // test Cancel first + err = clusterInstance.VtctlclientProcess.ExecuteCommand("CancelResharding", "destination_keyspace/0") + require.Nil(t, err) + err = destinationMasterTablet.VttabletProcess.WaitForBinLogPlayerCount(0) + require.Nil(t, err) + // master should be in serving state after cancel + sharding.CheckTabletQueryServices(t, []cluster.Vttablet{destinationMasterTablet}, "SERVING", false, *clusterInstance) + + // redo VerticalSplitClone + err = clusterInstance.VtworkerProcess.ExecuteVtworkerCommand(clusterInstance.GetAndReservePort(), clusterInstance.GetAndReservePort(), + "--cell", cellj, + "--command_display_interval", "10ms", + "--use_v3_resharding_mode=true", + "VerticalSplitClone", + "--tables", "/moving/,view1", + "--chunk_count", "10", + "--min_rows_per_chunk", "1", + "--min_healthy_tablets", "1", "destination_keyspace/0") + require.Nil(t, err) + + // check values are present + checkValues(t, &destinationMasterTablet, destinationKeyspace, "vt_destination_keyspace", "moving1", moving1First, 100) + checkValues(t, &destinationMasterTablet, destinationKeyspace, "vt_destination_keyspace", "moving2", moving2First, 100) + checkValues(t, &destinationMasterTablet, destinationKeyspace, "vt_destination_keyspace", "view1", moving1First, 100) + checkValues(t, &destinationMasterTablet, destinationKeyspace, "vt_destination_keyspace", "moving3_no_pk", moving3NoPkFirst, 100) + + // Verify vreplication table entries + dbParams := mysql.ConnParams{ + Uname: "vt_dba", + UnixSocket: path.Join(destinationMasterTablet.VttabletProcess.Directory, "mysql.sock"), + } + dbParams.DbName = "_vt" + dbConn, err := mysql.Connect(ctx, &dbParams) + require.Nil(t, err) + qr, err := dbConn.ExecuteFetch("select * from vreplication", 1000, true) + require.Nil(t, err, "error should be Nil") + assert.Equal(t, 1, len(qr.Rows)) + assert.Contains(t, fmt.Sprintf("%v", qr.Rows), "SplitClone") + assert.Contains(t, fmt.Sprintf("%v", qr.Rows), `keyspace:\"source_keyspace\" shard:\"0\" tables:\"/moving/\" tables:\"view1\`) + dbConn.Close() + + // check the binlog player is running and exporting vars + sharding.CheckDestinationMaster(t, destinationMasterTablet, []string{sourceKs}, *clusterInstance) + + // check that binlog server exported the stats vars + sharding.CheckBinlogServerVars(t, sourceReplicaTablet, 0, 0, true) + + // add values to source, make sure they're replicated + moving1FirstAdd1 := insertValues(t, conn, sourceKeyspace, "moving1", 100) + _ = insertValues(t, conn, sourceKeyspace, "staying1", 100) + moving2FirstAdd1 := insertValues(t, conn, sourceKeyspace, "moving2", 100) + checkValuesTimeout(t, destinationMasterTablet, "moving1", moving1FirstAdd1, 100, 30) + checkValuesTimeout(t, destinationMasterTablet, "moving2", moving2FirstAdd1, 100, 30) + sharding.CheckBinlogPlayerVars(t, destinationMasterTablet, []string{sourceKs}, 30) + sharding.CheckBinlogServerVars(t, sourceReplicaTablet, 100, 100, true) + + // use vtworker to compare the data + log.Info("Running vtworker VerticalSplitDiff") + err = clusterInstance.VtworkerProcess.ExecuteVtworkerCommand(clusterInstance.GetAndReservePort(), + clusterInstance.GetAndReservePort(), + "--use_v3_resharding_mode=true", + "--cell", "test_nj", + "VerticalSplitDiff", + "--min_healthy_rdonly_tablets", "1", + "destination_keyspace/0") + require.Nil(t, err) + + // get status for destination master tablet, make sure we have it all + sharding.CheckRunningBinlogPlayer(t, destinationMasterTablet, 700, 300) + + // check query service is off on destination master, as filtered + // replication is enabled. Even health check should not interfere. + destinationMasterTabletVars := destinationMasterTablet.VttabletProcess.GetVars() + assert.NotNil(t, destinationMasterTabletVars) + assert.Contains(t, reflect.ValueOf(destinationMasterTabletVars["TabletStateName"]).String(), "NOT_SERVING") + + // check we can't migrate the master just yet + err = clusterInstance.VtctlclientProcess.ExecuteCommand("MigrateServedFrom", "destination_keyspace/0", "master") + require.Error(t, err) + + // migrate rdonly only in test_ny cell, make sure nothing is migrated + // in test_nj + err = clusterInstance.VtctlclientProcess.ExecuteCommand("MigrateServedFrom", "--cells=test_ny", "destination_keyspace/0", "rdonly") + require.Nil(t, err) + + // check SrvKeyspace + checkSrvKeyspaceServedFrom(t, cellj, destinationKeyspace, ksServedFrom, *clusterInstance) + checkBlacklistedTables(t, sourceMasterTablet, sourceKeyspace, nil) + checkBlacklistedTables(t, sourceReplicaTablet, sourceKeyspace, nil) + checkBlacklistedTables(t, sourceRdOnlyTablet1, sourceKeyspace, nil) + checkBlacklistedTables(t, sourceRdOnlyTablet2, sourceKeyspace, nil) + + // migrate test_nj only, using command line manual fix command, + // and restore it back. + keyspaceJSON, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("GetKeyspace", "destination_keyspace") + require.Nil(t, err) + + validateKeyspaceJSON(t, keyspaceJSON, []string{"test_ca", "test_nj"}) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("SetKeyspaceServedFrom", "-source=source_keyspace", "-remove", "-cells=test_nj,test_ca", "destination_keyspace", "rdonly") + require.Nil(t, err) + + // again validating keyspaceJSON + keyspaceJSON, err = clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("GetKeyspace", "destination_keyspace") + require.Nil(t, err) + + validateKeyspaceJSON(t, keyspaceJSON, nil) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("SetKeyspaceServedFrom", "-source=source_keyspace", "destination_keyspace", "rdonly") + require.Nil(t, err) + + keyspaceJSON, err = clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("GetKeyspace", "destination_keyspace") + require.Nil(t, err) + + validateKeyspaceJSON(t, keyspaceJSON, []string{}) + + // now serve rdonly from the destination shards + err = clusterInstance.VtctlclientProcess.ExecuteCommand("MigrateServedFrom", "destination_keyspace/0", "rdonly") + require.Nil(t, err) + checkSrvKeyspaceServedFrom(t, cellj, destinationKeyspace, "ServedFrom(master): source_keyspace\nServedFrom(replica): source_keyspace\n", *clusterInstance) + checkBlacklistedTables(t, sourceMasterTablet, sourceKeyspace, nil) + checkBlacklistedTables(t, sourceReplicaTablet, sourceKeyspace, nil) + checkBlacklistedTables(t, sourceRdOnlyTablet1, sourceKeyspace, []string{"/moving/", "view1"}) + checkBlacklistedTables(t, sourceRdOnlyTablet2, sourceKeyspace, []string{"/moving/", "view1"}) + + grpcAddress := fmt.Sprintf("%s:%d", "localhost", clusterInstance.VtgateProcess.GrpcPort) + gconn, err := vtgateconn.Dial(ctx, grpcAddress) + require.Nil(t, err) + defer gconn.Close() + + checkClientConnRedirectionExecuteKeyrange(ctx, t, gconn, destinationKeyspace, []topodata.TabletType{topodata.TabletType_MASTER, topodata.TabletType_REPLICA}, []string{"moving1", "moving2"}) + + // then serve replica from the destination shards + err = clusterInstance.VtctlclientProcess.ExecuteCommand("MigrateServedFrom", "destination_keyspace/0", "replica") + require.Nil(t, err) + checkSrvKeyspaceServedFrom(t, cellj, destinationKeyspace, "ServedFrom(master): source_keyspace\n", *clusterInstance) + checkBlacklistedTables(t, sourceMasterTablet, sourceKeyspace, nil) + checkBlacklistedTables(t, sourceReplicaTablet, sourceKeyspace, []string{"/moving/", "view1"}) + checkBlacklistedTables(t, sourceRdOnlyTablet1, sourceKeyspace, []string{"/moving/", "view1"}) + checkBlacklistedTables(t, sourceRdOnlyTablet2, sourceKeyspace, []string{"/moving/", "view1"}) + checkClientConnRedirectionExecuteKeyrange(ctx, t, gconn, destinationKeyspace, []topodata.TabletType{topodata.TabletType_MASTER}, []string{"moving1", "moving2"}) + + // move replica back and forth + err = clusterInstance.VtctlclientProcess.ExecuteCommand("MigrateServedFrom", "-reverse", "destination_keyspace/0", "replica") + require.Nil(t, err) + checkSrvKeyspaceServedFrom(t, cellj, destinationKeyspace, "ServedFrom(master): source_keyspace\nServedFrom(replica): source_keyspace\n", *clusterInstance) + checkBlacklistedTables(t, sourceMasterTablet, sourceKeyspace, nil) + checkBlacklistedTables(t, sourceReplicaTablet, sourceKeyspace, nil) + checkBlacklistedTables(t, sourceRdOnlyTablet1, sourceKeyspace, []string{"/moving/", "view1"}) + checkBlacklistedTables(t, sourceRdOnlyTablet2, sourceKeyspace, []string{"/moving/", "view1"}) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("MigrateServedFrom", "destination_keyspace/0", "replica") + require.Nil(t, err) + checkSrvKeyspaceServedFrom(t, cellj, destinationKeyspace, "ServedFrom(master): source_keyspace\n", *clusterInstance) + checkBlacklistedTables(t, sourceMasterTablet, sourceKeyspace, nil) + checkBlacklistedTables(t, sourceReplicaTablet, sourceKeyspace, []string{"/moving/", "view1"}) + checkBlacklistedTables(t, sourceRdOnlyTablet1, sourceKeyspace, []string{"/moving/", "view1"}) + checkBlacklistedTables(t, sourceRdOnlyTablet2, sourceKeyspace, []string{"/moving/", "view1"}) + checkClientConnRedirectionExecuteKeyrange(ctx, t, gconn, destinationKeyspace, []topodata.TabletType{topodata.TabletType_MASTER}, []string{"moving1", "moving2"}) + + // Cancel should fail now + err = clusterInstance.VtctlclientProcess.ExecuteCommand("CancelResharding", "destination_keyspace/0") + require.Error(t, err) + + // then serve master from the destination shards + err = clusterInstance.VtctlclientProcess.ExecuteCommand("MigrateServedFrom", "destination_keyspace/0", "master") + checkSrvKeyspaceServedFrom(t, cellj, destinationKeyspace, "", *clusterInstance) + checkBlacklistedTables(t, sourceMasterTablet, sourceKeyspace, []string{"/moving/", "view1"}) + checkBlacklistedTables(t, sourceReplicaTablet, sourceKeyspace, []string{"/moving/", "view1"}) + checkBlacklistedTables(t, sourceRdOnlyTablet1, sourceKeyspace, []string{"/moving/", "view1"}) + checkBlacklistedTables(t, sourceRdOnlyTablet2, sourceKeyspace, []string{"/moving/", "view1"}) + + // check the binlog player is gone now + _ = destinationMasterTablet.VttabletProcess.WaitForBinLogPlayerCount(0) + + // check the stats are correct + checkStats(t) + + // now remove the tables on the source shard. The blacklisted tables + // in the source shard won't match any table, make sure that works. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ApplySchema", "-sql=drop view view1", "source_keyspace") + require.Nil(t, err) + + for _, table := range []string{"moving1", "moving2"} { + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ApplySchema", "--sql=drop table "+table, "source_keyspace") + require.Nil(t, err) + } + for _, tablet := range []cluster.Vttablet{sourceMasterTablet, sourceReplicaTablet, sourceRdOnlyTablet1, sourceRdOnlyTablet2} { + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ReloadSchema", tablet.Alias) + require.Nil(t, err) + } + qr, _ = sourceMasterTablet.VttabletProcess.QueryTablet("select count(1) from staying1", sourceKeyspace, true) + assert.Equal(t, 1, len(qr.Rows), fmt.Sprintf("cannot read staying1: got %d", len(qr.Rows))) + + // test SetShardTabletControl + verifyVtctlSetShardTabletControl(t) + +} + +func verifyVtctlSetShardTabletControl(t *testing.T) { + // clear the rdonly entry: + err := clusterInstance.VtctlclientProcess.ExecuteCommand("SetShardTabletControl", "--remove", "source_keyspace/0", "rdonly") + require.Nil(t, err) + assertTabletControls(t, clusterInstance, []topodata.TabletType{topodata.TabletType_MASTER, topodata.TabletType_REPLICA}) + + // re-add rdonly: + err = clusterInstance.VtctlclientProcess.ExecuteCommand("SetShardTabletControl", "--blacklisted_tables=/moving/,view1", "source_keyspace/0", "rdonly") + require.Nil(t, err) + assertTabletControls(t, clusterInstance, []topodata.TabletType{topodata.TabletType_MASTER, topodata.TabletType_REPLICA, topodata.TabletType_RDONLY}) + + //and then clear all entries: + err = clusterInstance.VtctlclientProcess.ExecuteCommand("SetShardTabletControl", "--remove", "source_keyspace/0", "rdonly") + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("SetShardTabletControl", "--remove", "source_keyspace/0", "replica") + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("SetShardTabletControl", "--remove", "source_keyspace/0", "master") + require.Nil(t, err) + + shardJSON, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("GetShard", "source_keyspace/0") + var shardJSONData topodata.Shard + err = json2.Unmarshal([]byte(shardJSON), &shardJSONData) + assert.Empty(t, shardJSONData.TabletControls) + +} + +func assertTabletControls(t *testing.T, clusterInstance *cluster.LocalProcessCluster, aliases []topodata.TabletType) { + shardJSON, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("GetShard", "source_keyspace/0") + require.Nil(t, err) + var shardJSONData topodata.Shard + err = json2.Unmarshal([]byte(shardJSON), &shardJSONData) + require.Nil(t, err) + assert.Equal(t, len(shardJSONData.TabletControls), len(aliases)) + for _, tc := range shardJSONData.TabletControls { + assert.Contains(t, aliases, tc.TabletType) + assert.Equal(t, []string{"/moving/", "view1"}, tc.BlacklistedTables) + } +} + +func checkStats(t *testing.T) { + + resultMap, err := clusterInstance.VtgateProcess.GetVars() + require.Nil(t, err) + resultVtTabletCall, _ := resultMap["VttabletCall"] + resultVtTabletCallMap, _ := resultVtTabletCall.(map[string]interface{}) + resultHistograms, _ := resultVtTabletCallMap["Histograms"] + resultHistogramsMap, _ := resultHistograms.(map[string]interface{}) + resultTablet, _ := resultHistogramsMap["Execute.source_keyspace.0.replica"] + resultTableMap, _ := resultTablet.(map[string]interface{}) + resultCountStr := fmt.Sprintf("%v", reflect.ValueOf(resultTableMap["Count"])) + assert.Equal(t, "2", resultCountStr, fmt.Sprintf("unexpected value for VttabletCall(Execute.source_keyspace.0.replica) inside %s", resultCountStr)) + + // Verify master reads done by self._check_client_conn_redirection(). + resultVtgateAPI, _ := resultMap["VtgateApi"] + resultVtgateAPIMap, _ := resultVtgateAPI.(map[string]interface{}) + resultAPIHistograms, _ := resultVtgateAPIMap["Histograms"] + resultAPIHistogramsMap, _ := resultAPIHistograms.(map[string]interface{}) + resultTabletDestination, _ := resultAPIHistogramsMap["ExecuteKeyRanges.destination_keyspace.master"] + resultTabletDestinationMap, _ := resultTabletDestination.(map[string]interface{}) + resultCountStrDestination := fmt.Sprintf("%v", reflect.ValueOf(resultTabletDestinationMap["Count"])) + assert.Equal(t, "6", resultCountStrDestination, fmt.Sprintf("unexpected value for VtgateApi(ExecuteKeyRanges.destination_keyspace.master) inside %s)", resultCountStrDestination)) + + assert.Empty(t, resultMap["VtgateApiErrorCounts"]) + +} + +func insertInitialValues(t *testing.T, conn *mysql.Conn, sourceMasterTablet cluster.Vttablet, destinationMasterTablet cluster.Vttablet) { + moving1First = insertValues(t, conn, sourceKeyspace, "moving1", 100) + moving2First = insertValues(t, conn, sourceKeyspace, "moving2", 100) + staying1First = insertValues(t, conn, sourceKeyspace, "staying1", 100) + staying2First = insertValues(t, conn, sourceKeyspace, "staying2", 100) + checkValues(t, &sourceMasterTablet, sourceKeyspace, "vt_source_keyspace", "moving1", moving1First, 100) + checkValues(t, &sourceMasterTablet, sourceKeyspace, "vt_source_keyspace", "moving2", moving2First, 100) + checkValues(t, &sourceMasterTablet, sourceKeyspace, "vt_source_keyspace", "staying1", staying1First, 100) + checkValues(t, &sourceMasterTablet, sourceKeyspace, "vt_source_keyspace", "staying2", staying2First, 100) + checkValues(t, &sourceMasterTablet, sourceKeyspace, "vt_source_keyspace", "view1", moving1First, 100) + + moving3NoPkFirst = insertValues(t, conn, sourceKeyspace, "moving3_no_pk", 100) + checkValues(t, &sourceMasterTablet, sourceKeyspace, "vt_source_keyspace", "moving3_no_pk", moving3NoPkFirst, 100) + + // Insert data directly because vtgate would redirect us. + _, err := destinationMasterTablet.VttabletProcess.QueryTablet(fmt.Sprintf("insert into %s (id, msg) values(%d, 'value %d')", "extra1", 1, 1), destinationKeyspace, true) + require.Nil(t, err) + checkValues(t, &destinationMasterTablet, destinationKeyspace, "vt_destination_keyspace", "extra1", 1, 1) +} + +func checkClientConnRedirectionExecuteKeyrange(ctx context.Context, t *testing.T, conn *vtgateconn.VTGateConn, keyspace string, servedFromDbTypes []topodata.TabletType, movedTables []string) { + var testKeyRange = &topodata.KeyRange{ + Start: []byte{}, + End: []byte{}, + } + keyRanges := []*topodata.KeyRange{testKeyRange} + // check that the ServedFrom indirection worked correctly. + for _, tableType := range servedFromDbTypes { + for _, table := range movedTables { + _, err := conn.ExecuteKeyRanges(ctx, fmt.Sprintf("select * from %s", table), keyspace, keyRanges, nil, tableType, nil) + require.Nil(t, err) + } + } +} + +func checkValues(t *testing.T, tablet *cluster.Vttablet, keyspace string, dbname string, table string, first int, count int) { + log.Info("Checking %d values from %s/%s starting at %d", count, dbname, table, first) + qr, _ := tablet.VttabletProcess.QueryTablet(fmt.Sprintf("select id, msg from %s where id>=%d order by id limit %d", table, first, count), keyspace, true) + assert.Equal(t, count, len(qr.Rows), fmt.Sprintf("got wrong number of rows: %d != %d", len(qr.Rows), count)) + i := 0 + for i < count { + result, _ := sqltypes.ToInt64(qr.Rows[i][0]) + assert.Equal(t, int64(first+i), result, fmt.Sprintf("got wrong number of rows: %d != %d", len(qr.Rows), first+i)) + assert.Contains(t, qr.Rows[i][1].String(), fmt.Sprintf("value %d", first+i), fmt.Sprintf("invalid msg[%d]: 'value %d' != '%s'", i, first+i, qr.Rows[i][1].String())) + i++ + } +} + +func checkValuesTimeout(t *testing.T, tablet cluster.Vttablet, table string, first int, count int, timeoutInSec int) bool { + for i := 0; i < timeoutInSec; i-- { + qr, err := tablet.VttabletProcess.QueryTablet(fmt.Sprintf("select id, msg from %s where id>=%d order by id limit %d", table, first, count), destinationKeyspace, true) + if err != nil { + require.Nil(t, err, "select failed on master tablet") + } + if len(qr.Rows) == count { + return true + } + time.Sleep(1 * time.Second) + } + return true +} + +func checkBlacklistedTables(t *testing.T, tablet cluster.Vttablet, keyspace string, expected []string) { + tabletStatus := tablet.VttabletProcess.GetStatus() + if expected != nil { + assert.Contains(t, tabletStatus, fmt.Sprintf("BlacklistedTables: %s", strings.Join(expected, " "))) + } else { + assert.NotContains(t, tabletStatus, "BlacklistedTables") + } + + // check we can or cannot access the tables + for _, table := range []string{"moving1", "moving2"} { + if expected != nil && strings.Contains(strings.Join(expected, " "), "moving") { + // table is blacklisted, should get error + err := clusterInstance.VtctlclientProcess.ExecuteCommand("VtTabletExecute", "-json", tablet.Alias, fmt.Sprintf("select count(1) from %s", table)) + require.Error(t, err, "disallowed due to rule: enforce blacklisted tables") + } else { + // table is not blacklisted, should just work + _, err := tablet.VttabletProcess.QueryTablet(fmt.Sprintf("select count(1) from %s", table), keyspace, true) + require.Nil(t, err) + } + } +} + +func insertValues(t *testing.T, conn *mysql.Conn, keyspace string, table string, count int) int { + result := insertIndex + i := 0 + for i < count { + execQuery(t, conn, "begin") + execQuery(t, conn, "use `"+keyspace+":0`") + execQuery(t, conn, fmt.Sprintf("insert into %s (id, msg) values(%d, 'value %d')", table, insertIndex, insertIndex)) + execQuery(t, conn, "commit") + insertIndex++ + i++ + } + return result +} + +func teardownCluster() { + clusterInstance.Teardown() +} + +func execQuery(t *testing.T, conn *mysql.Conn, query string) *sqltypes.Result { + t.Helper() + qr, err := conn.ExecuteFetch(query, 1000, true) + require.Nil(t, err) + return qr +} + +// CheckSrvKeyspaceServedFrom verifies the servedFrom with expected +func checkSrvKeyspaceServedFrom(t *testing.T, cell string, ksname string, expected string, ci cluster.LocalProcessCluster) { + srvKeyspace := sharding.GetSrvKeyspace(t, cell, ksname, ci) + tabletTypeKeyspaceMap := make(map[string]string) + result := "" + if srvKeyspace.GetServedFrom() != nil { + for _, servedFrom := range srvKeyspace.GetServedFrom() { + tabletTy := strings.ToLower(servedFrom.GetTabletType().String()) + tabletTypeKeyspaceMap[tabletTy] = servedFrom.GetKeyspace() + } + } + if tabletTypeKeyspaceMap["master"] != "" { + result = result + fmt.Sprintf("ServedFrom(%s): %s\n", "master", tabletTypeKeyspaceMap["master"]) + } + if tabletTypeKeyspaceMap["rdonly"] != "" { + result = result + fmt.Sprintf("ServedFrom(%s): %s\n", "rdonly", tabletTypeKeyspaceMap["rdonly"]) + } + if tabletTypeKeyspaceMap["replica"] != "" { + result = result + fmt.Sprintf("ServedFrom(%s): %s\n", "replica", tabletTypeKeyspaceMap["replica"]) + } + assert.Equal(t, expected, result, fmt.Sprintf("Mismatch in srv keyspace for cell %s keyspace %s, expected:\n %s\ngot:\n%s", cell, ksname, expected, result)) + assert.Equal(t, "", srvKeyspace.GetShardingColumnName(), fmt.Sprintf("Got a sharding_column_name in SrvKeyspace: %s", srvKeyspace.GetShardingColumnName())) + assert.Equal(t, "UNSET", srvKeyspace.GetShardingColumnType().String(), fmt.Sprintf("Got a sharding_column_type in SrvKeyspace: %s", srvKeyspace.GetShardingColumnType().String())) +} + +func initializeCluster() (int, error) { + var mysqlProcesses []*exec.Cmd + clusterInstance = cluster.NewCluster(cellj, hostname) + + // Start topo server + if err := clusterInstance.StartTopo(); err != nil { + return 1, err + } + + for _, keyspaceStr := range []string{sourceKeyspace, destinationKeyspace} { + KeyspacePtr := &cluster.Keyspace{Name: keyspaceStr} + keyspace := *KeyspacePtr + if keyspaceStr == sourceKeyspace { + if err := clusterInstance.VtctlProcess.CreateKeyspace(keyspace.Name); err != nil { + return 1, err + } + } else { + if err := clusterInstance.VtctlclientProcess.ExecuteCommand("CreateKeyspace", "--served_from", "master:source_keyspace,replica:source_keyspace,rdonly:source_keyspace", "destination_keyspace"); err != nil { + return 1, err + } + } + shard := &cluster.Shard{ + Name: shardName, + } + for i := 0; i < 4; i++ { + // instantiate vttablet object with reserved ports + tabletUID := clusterInstance.GetAndReserveTabletUID() + var tablet *cluster.Vttablet = nil + if i == 0 { + tablet = clusterInstance.GetVttabletInstance("replica", tabletUID, cellj) + } else if i == 1 { + tablet = clusterInstance.GetVttabletInstance("replica", tabletUID, cellj) + } else { + tablet = clusterInstance.GetVttabletInstance("rdonly", tabletUID, cellj) + } + // Start Mysqlctl process + tablet.MysqlctlProcess = *cluster.MysqlCtlProcessInstance(tablet.TabletUID, tablet.MySQLPort, clusterInstance.TmpDirectory) + if proc, err := tablet.MysqlctlProcess.StartProcess(); err != nil { + return 1, err + } else { + mysqlProcesses = append(mysqlProcesses, proc) + } + // start vttablet process + tablet.VttabletProcess = cluster.VttabletProcessInstance(tablet.HTTPPort, + tablet.GrpcPort, + tablet.TabletUID, + clusterInstance.Cell, + shardName, + keyspace.Name, + clusterInstance.VtctldProcess.Port, + tablet.Type, + clusterInstance.TopoProcess.Port, + clusterInstance.Hostname, + clusterInstance.TmpDirectory, + clusterInstance.VtTabletExtraArgs, + clusterInstance.EnableSemiSync) + tablet.Alias = tablet.VttabletProcess.TabletPath + + shard.Vttablets = append(shard.Vttablets, tablet) + } + keyspace.Shards = append(keyspace.Shards, *shard) + clusterInstance.Keyspaces = append(clusterInstance.Keyspaces, keyspace) + } + for _, proc := range mysqlProcesses { + err := proc.Wait() + if err != nil { + return 1, err + } + } + return 0, nil +} + +func validateKeyspaceJSON(t *testing.T, keyspaceJSON string, cellsArr []string) { + var keyspace topodata.Keyspace + err := json2.Unmarshal([]byte(keyspaceJSON), &keyspace) + require.Nil(t, err) + found := false + for _, servedFrom := range keyspace.GetServedFroms() { + if strings.ToLower(servedFrom.GetTabletType().String()) == "rdonly" { + found = true + if cellsArr != nil { + if len(cellsArr) > 0 { + for _, eachCell := range cellsArr { + assert.Contains(t, strings.Join(servedFrom.GetCells(), " "), eachCell) + } + } else { + assert.Equal(t, []string{}, servedFrom.GetCells()) + } + } + } + } + if cellsArr != nil { + assert.Equal(t, true, found) + } else { + assert.Equal(t, false, found) + } +} diff --git a/go/test/endtoend/tabletmanager/commands_test.go b/go/test/endtoend/tabletmanager/commands_test.go new file mode 100644 index 00000000000..f8111896c1a --- /dev/null +++ b/go/test/endtoend/tabletmanager/commands_test.go @@ -0,0 +1,235 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package tabletmanager + +import ( + "context" + "encoding/json" + "fmt" + "reflect" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/stretchr/testify/assert" + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/test/endtoend/cluster" +) + +// TabletCommands tests the basic tablet commands +func TestTabletCommands(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + + masterConn, err := mysql.Connect(ctx, &masterTabletParams) + require.Nil(t, err) + defer masterConn.Close() + + replicaConn, err := mysql.Connect(ctx, &replicaTabletParams) + require.Nil(t, err) + defer replicaConn.Close() + + // Sanity Check + exec(t, masterConn, "delete from t1") + exec(t, masterConn, "insert into t1(id, value) values(1,'a'), (2,'b')") + checkDataOnReplica(t, replicaConn, `[[VARCHAR("a")] [VARCHAR("b")]]`) + + // test exclude_field_names to vttablet works as expected + sql := "select id, value from t1" + args := []string{ + "VtTabletExecute", + "-options", "included_fields:TYPE_ONLY", + "-json", + masterTablet.Alias, + sql, + } + result, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput(args...) + require.Nil(t, err) + assertExcludeFields(t, result) + + // make sure direct dba queries work + sql = "select * from t1" + result, err = clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("ExecuteFetchAsDba", "-json", masterTablet.Alias, sql) + require.Nil(t, err) + assertExecuteFetch(t, result) + + // check Ping / RefreshState / RefreshStateByShard + err = clusterInstance.VtctlclientProcess.ExecuteCommand("Ping", masterTablet.Alias) + require.Nil(t, err, "error should be Nil") + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RefreshState", masterTablet.Alias) + require.Nil(t, err, "error should be Nil") + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RefreshStateByShard", keyspaceShard) + require.Nil(t, err, "error should be Nil") + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RefreshStateByShard", "--cells="+cell, keyspaceShard) + require.Nil(t, err, "error should be Nil") + + // Check basic actions. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("SetReadOnly", masterTablet.Alias) + require.Nil(t, err, "error should be Nil") + qr := exec(t, masterConn, "show variables like 'read_only'") + got := fmt.Sprintf("%v", qr.Rows) + want := "[[VARCHAR(\"read_only\") VARCHAR(\"ON\")]]" + assert.Equal(t, want, got) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("SetReadWrite", masterTablet.Alias) + require.Nil(t, err, "error should be Nil") + qr = exec(t, masterConn, "show variables like 'read_only'") + got = fmt.Sprintf("%v", qr.Rows) + want = "[[VARCHAR(\"read_only\") VARCHAR(\"OFF\")]]" + assert.Equal(t, want, got) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("Validate") + require.Nil(t, err, "error should be Nil") + err = clusterInstance.VtctlclientProcess.ExecuteCommand("Validate", "-ping-tablets=true") + require.Nil(t, err, "error should be Nil") + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ValidateKeyspace", keyspaceName) + require.Nil(t, err, "error should be Nil") + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ValidateKeyspace", "-ping-tablets=true", keyspaceName) + require.Nil(t, err, "error should be Nil") + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ValidateShard", "-ping-tablets=false", keyspaceShard) + require.Nil(t, err, "error should be Nil") + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ValidateShard", "-ping-tablets=true", keyspaceShard) + require.Nil(t, err, "error should be Nil") + +} + +func assertExcludeFields(t *testing.T, qr string) { + resultMap := make(map[string]interface{}) + err := json.Unmarshal([]byte(qr), &resultMap) + require.Nil(t, err) + + rowsAffected := resultMap["rows_affected"] + want := float64(2) + assert.Equal(t, want, rowsAffected) + + fields := resultMap["fields"] + assert.NotContainsf(t, fields, "name", "name should not be in field list") +} + +func assertExecuteFetch(t *testing.T, qr string) { + resultMap := make(map[string]interface{}) + err := json.Unmarshal([]byte(qr), &resultMap) + require.Nil(t, err) + + rows := reflect.ValueOf(resultMap["rows"]) + got := rows.Len() + want := int(2) + assert.Equal(t, want, got) + + fields := reflect.ValueOf(resultMap["fields"]) + got = fields.Len() + want = int(2) + assert.Equal(t, want, got) +} + +// ActionAndTimeout test +func TestActionAndTimeout(t *testing.T) { + + defer cluster.PanicHandler(t) + err := clusterInstance.VtctlclientProcess.ExecuteCommand("Sleep", masterTablet.Alias, "5s") + require.Nil(t, err) + time.Sleep(1 * time.Second) + + // try a frontend RefreshState that should timeout as the tablet is busy running the other one + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RefreshState", masterTablet.Alias, "-wait-time", "2s") + assert.Error(t, err, "timeout as tablet is in Sleep") +} + +func TestHook(t *testing.T) { + // test a regular program works + defer cluster.PanicHandler(t) + runHookAndAssert(t, []string{ + "ExecuteHook", masterTablet.Alias, "test.sh", "--flag1", "--param1=hello"}, "0", false, "") + + // test stderr output + runHookAndAssert(t, []string{ + "ExecuteHook", masterTablet.Alias, "test.sh", "--to-stderr"}, "0", false, "ERR: --to-stderr\n") + + // test commands that fail + runHookAndAssert(t, []string{ + "ExecuteHook", masterTablet.Alias, "test.sh", "--exit-error"}, "1", false, "ERROR: exit status 1\n") + + // test hook that is not present + runHookAndAssert(t, []string{ + "ExecuteHook", masterTablet.Alias, "not_here.sh", "--exit-error"}, "-1", false, "missing hook") + + // test hook with invalid name + + runHookAndAssert(t, []string{ + "ExecuteHook", masterTablet.Alias, "/bin/ls"}, "-1", true, "hook name cannot have") +} + +func runHookAndAssert(t *testing.T, params []string, expectedStatus string, expectedError bool, expectedStderr string) { + + hr, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput(params...) + if expectedError { + assert.Error(t, err, "Expected error") + } else { + require.Nil(t, err) + + resultMap := make(map[string]interface{}) + err = json.Unmarshal([]byte(hr), &resultMap) + require.Nil(t, err) + + exitStatus := reflect.ValueOf(resultMap["ExitStatus"]).Float() + status := fmt.Sprintf("%.0f", exitStatus) + assert.Equal(t, expectedStatus, status) + + stderr := reflect.ValueOf(resultMap["Stderr"]).String() + assert.Contains(t, stderr, expectedStderr) + } + +} + +func TestShardReplicationFix(t *testing.T) { + // make sure the replica is in the replication graph, 2 nodes: 1 master, 1 replica + defer cluster.PanicHandler(t) + result, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("GetShardReplication", cell, keyspaceShard) + require.Nil(t, err, "error should be Nil") + assertNodeCount(t, result, int(3)) + + // Manually add a bogus entry to the replication graph, and check it is removed by ShardReplicationFix + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ShardReplicationAdd", keyspaceShard, fmt.Sprintf("%s-9000", cell)) + require.Nil(t, err, "error should be Nil") + + result, err = clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("GetShardReplication", cell, keyspaceShard) + require.Nil(t, err, "error should be Nil") + assertNodeCount(t, result, int(4)) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ShardReplicationFix", cell, keyspaceShard) + require.Nil(t, err, "error should be Nil") + result, err = clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("GetShardReplication", cell, keyspaceShard) + require.Nil(t, err, "error should be Nil") + assertNodeCount(t, result, int(3)) +} + +func assertNodeCount(t *testing.T, result string, want int) { + resultMap := make(map[string]interface{}) + err := json.Unmarshal([]byte(result), &resultMap) + require.Nil(t, err) + + nodes := reflect.ValueOf(resultMap["nodes"]) + got := nodes.Len() + assert.Equal(t, want, got) +} diff --git a/go/test/endtoend/tabletmanager/custom_rule_topo_test.go b/go/test/endtoend/tabletmanager/custom_rule_topo_test.go new file mode 100644 index 00000000000..31a697249d0 --- /dev/null +++ b/go/test/endtoend/tabletmanager/custom_rule_topo_test.go @@ -0,0 +1,128 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ +package tabletmanager + +import ( + "context" + "encoding/json" + "io/ioutil" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/stretchr/testify/assert" + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/test/endtoend/cluster" +) + +func TestTopoCustomRule(t *testing.T) { + + defer cluster.PanicHandler(t) + ctx := context.Background() + masterConn, err := mysql.Connect(ctx, &masterTabletParams) + require.Nil(t, err) + defer masterConn.Close() + replicaConn, err := mysql.Connect(ctx, &replicaTabletParams) + require.Nil(t, err) + defer replicaConn.Close() + + // Insert data for sanity checks + exec(t, masterConn, "delete from t1") + exec(t, masterConn, "insert into t1(id, value) values(11,'r'), (12,'s')") + checkDataOnReplica(t, replicaConn, `[[VARCHAR("r")] [VARCHAR("s")]]`) + + // create empty topoCustomRuleFile. + topoCustomRuleFile := "/tmp/rules.json" + topoCustomRulePath := "/keyspaces/ks/configs/CustomRules" + data := []byte("[]\n") + err = ioutil.WriteFile(topoCustomRuleFile, data, 0777) + require.Nil(t, err) + + // Copy config file into topo. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("TopoCp", "-to_topo", topoCustomRuleFile, topoCustomRulePath) + require.Nil(t, err, "error should be Nil") + + // Set extra tablet args for topo custom rule + clusterInstance.VtTabletExtraArgs = []string{ + "-topocustomrule_path", topoCustomRulePath, + } + + // Start a new Tablet + rTablet := clusterInstance.GetVttabletInstance("replica", 0, "") + + // Init Tablets + err = clusterInstance.VtctlclientProcess.InitTablet(rTablet, cell, keyspaceName, hostname, shardName) + require.Nil(t, err, "error should be Nil") + + // Start Mysql Processes + err = cluster.StartMySQL(ctx, rTablet, username, clusterInstance.TmpDirectory) + require.Nil(t, err, "error should be Nil") + + // Start Vttablet + err = clusterInstance.StartVttablet(rTablet, "SERVING", false, cell, keyspaceName, hostname, shardName) + require.Nil(t, err, "error should be Nil") + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("Validate") + require.Nil(t, err, "error should be Nil") + + // Verify that query is working + result, err := vtctlExec("select id, value from t1", rTablet.Alias) + require.Nil(t, err) + resultMap := make(map[string]interface{}) + err = json.Unmarshal([]byte(result), &resultMap) + require.Nil(t, err) + + rowsAffected := resultMap["rows_affected"] + want := float64(2) + assert.Equal(t, want, rowsAffected) + + // Now update the topocustomrule file. + data = []byte(`[{ + "Name": "rule1", + "Description": "disallow select on table t1", + "TableNames" : ["t1"], + "Query" : "(select)|(SELECT)" + }]`) + err = ioutil.WriteFile(topoCustomRuleFile, data, 0777) + require.Nil(t, err) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("TopoCp", "-to_topo", topoCustomRuleFile, topoCustomRulePath) + require.Nil(t, err, "error should be Nil") + + // And wait until the query fails with the right error. + timeout := time.Now().Add(10 * time.Second) + for time.Now().Before(timeout) { + result, err := vtctlExec("select id, value from t1", rTablet.Alias) + if err != nil { + assert.Contains(t, result, "disallow select on table t1") + break + } + time.Sleep(300 * time.Millisecond) + } + + // Empty the table + exec(t, masterConn, "delete from t1") + // Reset the VtTabletExtraArgs + clusterInstance.VtTabletExtraArgs = []string{} + // Tear down custom processes + killTablets(t, rTablet) +} + +func vtctlExec(sql string, tabletAlias string) (string, error) { + args := []string{"VtTabletExecute", "-json", tabletAlias, sql} + return clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput(args...) +} diff --git a/go/test/endtoend/tabletmanager/dbnameoverride/tablet_master_test.go b/go/test/endtoend/tabletmanager/dbnameoverride/tablet_master_test.go new file mode 100644 index 00000000000..88fcbc76743 --- /dev/null +++ b/go/test/endtoend/tabletmanager/dbnameoverride/tablet_master_test.go @@ -0,0 +1,121 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ +package master + +import ( + "context" + "flag" + "os" + "testing" + + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/mysql" + + "vitess.io/vitess/go/test/endtoend/cluster" +) + +var ( + clusterInstance *cluster.LocalProcessCluster + vtParams mysql.ConnParams + hostname = "localhost" + keyspaceName = "ks" + cell = "zone1" + sqlSchema = ` + create table t1( + id bigint, + value varchar(16), + primary key(id) + ) Engine=InnoDB; +` + + vSchema = ` + { + "sharded": true, + "vindexes": { + "hash": { + "type": "hash" + } + }, + "tables": { + "t1": { + "column_vindexes": [ + { + "column": "id", + "name": "hash" + } + ] + } + } + }` +) + +const dbName = "myDbName" + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitCode := func() int { + clusterInstance = cluster.NewCluster(cell, hostname) + defer clusterInstance.Teardown() + + // Start topo server + err := clusterInstance.StartTopo() + if err != nil { + return 1 + } + + // Set extra tablet args for lock timeout + clusterInstance.VtTabletExtraArgs = []string{ + "-init_db_name_override", dbName, + } + + // Start keyspace + keyspace := &cluster.Keyspace{ + Name: keyspaceName, + SchemaSQL: sqlSchema, + VSchema: vSchema, + } + + if err = clusterInstance.StartUnshardedKeyspace(*keyspace, 1, false); err != nil { + return 1 + } + + if err = clusterInstance.StartVtgate(); err != nil { + return 1 + } + vtParams = mysql.ConnParams{ + Host: clusterInstance.Hostname, + Port: clusterInstance.VtgateMySQLPort, + } + + return m.Run() + }() + os.Exit(exitCode) +} + +func TestDbNameOverride(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + require.Nil(t, err) + defer conn.Close() + qr, err := conn.ExecuteFetch("SELECT database() FROM information_schema.tables WHERE table_schema = database()", 1000, true) + + require.Nil(t, err) + require.Equal(t, 1, len(qr.Rows), "did not get enough rows back") + require.Equal(t, dbName, qr.Rows[0][0].ToString()) +} diff --git a/go/test/endtoend/tabletmanager/lock_unlock_test.go b/go/test/endtoend/tabletmanager/lock_unlock_test.go new file mode 100644 index 00000000000..ac413dc6f9c --- /dev/null +++ b/go/test/endtoend/tabletmanager/lock_unlock_test.go @@ -0,0 +1,179 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package tabletmanager + +import ( + "context" + "fmt" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/stretchr/testify/assert" + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/test/endtoend/cluster" +) + +// TestLockAndUnlock tests the lock ability by locking a replica and asserting it does not see changes +func TestLockAndUnlock(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + + masterConn, err := mysql.Connect(ctx, &masterTabletParams) + require.Nil(t, err) + defer masterConn.Close() + + replicaConn, err := mysql.Connect(ctx, &replicaTabletParams) + require.Nil(t, err) + defer replicaConn.Close() + + // first make sure that our writes to the master make it to the replica + exec(t, masterConn, "delete from t1") + exec(t, masterConn, "insert into t1(id, value) values(1,'a'), (2,'b')") + checkDataOnReplica(t, replicaConn, `[[VARCHAR("a")] [VARCHAR("b")]]`) + + // now lock the replica + err = tmcLockTables(ctx, replicaTablet.GrpcPort) + require.Nil(t, err) + // make sure that writing to the master does not show up on the replica while locked + exec(t, masterConn, "insert into t1(id, value) values(3,'c')") + checkDataOnReplica(t, replicaConn, `[[VARCHAR("a")] [VARCHAR("b")]]`) + + // finally, make sure that unlocking the replica leads to the previous write showing up + err = tmcUnlockTables(ctx, replicaTablet.GrpcPort) + require.Nil(t, err) + checkDataOnReplica(t, replicaConn, `[[VARCHAR("a")] [VARCHAR("b")] [VARCHAR("c")]]`) + + // Unlocking when we do not have a valid lock should lead to an exception being raised + err = tmcUnlockTables(ctx, replicaTablet.GrpcPort) + want := "tables were not locked" + if err == nil || !strings.Contains(err.Error(), want) { + t.Errorf("Table unlock: %v, must contain %s", err, want) + } + + // Clean the table for further testing + exec(t, masterConn, "delete from t1") +} + +// TestStartSlaveUntilAfter tests by writing three rows, noting the gtid after each, and then replaying them one by one +func TestStartSlaveUntilAfter(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + + masterConn, err := mysql.Connect(ctx, &masterTabletParams) + require.Nil(t, err) + defer masterConn.Close() + + replicaConn, err := mysql.Connect(ctx, &replicaTabletParams) + require.Nil(t, err) + defer replicaConn.Close() + + //first we stop replication to the replica, so we can move forward step by step. + err = tmcStopSlave(ctx, replicaTablet.GrpcPort) + require.Nil(t, err) + + exec(t, masterConn, "insert into t1(id, value) values(1,'a')") + pos1, err := tmcMasterPosition(ctx, masterTablet.GrpcPort) + require.Nil(t, err) + + exec(t, masterConn, "insert into t1(id, value) values(2,'b')") + pos2, err := tmcMasterPosition(ctx, masterTablet.GrpcPort) + require.Nil(t, err) + + exec(t, masterConn, "insert into t1(id, value) values(3,'c')") + pos3, err := tmcMasterPosition(ctx, masterTablet.GrpcPort) + require.Nil(t, err) + + // Now, we'll resume stepwise position by position and make sure that we see the expected data + checkDataOnReplica(t, replicaConn, `[]`) + + // starts the mysql replication until + timeout := 10 * time.Second + err = tmcStartSlaveUntilAfter(ctx, replicaTablet.GrpcPort, pos1, timeout) + require.Nil(t, err) + // first row should be visible + checkDataOnReplica(t, replicaConn, `[[VARCHAR("a")]]`) + + err = tmcStartSlaveUntilAfter(ctx, replicaTablet.GrpcPort, pos2, timeout) + require.Nil(t, err) + checkDataOnReplica(t, replicaConn, `[[VARCHAR("a")] [VARCHAR("b")]]`) + + err = tmcStartSlaveUntilAfter(ctx, replicaTablet.GrpcPort, pos3, timeout) + require.Nil(t, err) + checkDataOnReplica(t, replicaConn, `[[VARCHAR("a")] [VARCHAR("b")] [VARCHAR("c")]]`) + + // Strat replication to the replica + err = tmcStartSlave(ctx, replicaTablet.GrpcPort) + require.Nil(t, err) + // Clean the table for further testing + exec(t, masterConn, "delete from t1") +} + +// TestLockAndTimeout tests that the lock times out and updates can be seen after timeout +func TestLockAndTimeout(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + + masterConn, err := mysql.Connect(ctx, &masterTabletParams) + require.Nil(t, err) + defer masterConn.Close() + + replicaConn, err := mysql.Connect(ctx, &replicaTabletParams) + require.Nil(t, err) + defer replicaConn.Close() + + // first make sure that our writes to the master make it to the replica + exec(t, masterConn, "insert into t1(id, value) values(1,'a')") + checkDataOnReplica(t, replicaConn, `[[VARCHAR("a")]]`) + + // now lock the replica + err = tmcLockTables(ctx, replicaTablet.GrpcPort) + require.Nil(t, err) + + // make sure that writing to the master does not show up on the replica while locked + exec(t, masterConn, "insert into t1(id, value) values(2,'b')") + checkDataOnReplica(t, replicaConn, `[[VARCHAR("a")]]`) + + // the tests sets the lock timeout to 5 seconds, so sleeping 8 should be safe + time.Sleep(8 * time.Second) + checkDataOnReplica(t, replicaConn, `[[VARCHAR("a")] [VARCHAR("b")]]`) + + // Clean the table for further testing + exec(t, masterConn, "delete from t1") +} + +func checkDataOnReplica(t *testing.T, replicaConn *mysql.Conn, want string) { + startTime := time.Now() + for { + qr := exec(t, replicaConn, "select value from t1") + got := fmt.Sprintf("%v", qr.Rows) + + if time.Since(startTime) > 3*time.Second /* timeout */ { + assert.Equal(t, want, got) + break + } + + if got == want { + assert.Equal(t, want, got) + break + } else { + time.Sleep(300 * time.Millisecond /* interval at which to check again */) + } + } +} diff --git a/go/test/endtoend/tabletmanager/main_test.go b/go/test/endtoend/tabletmanager/main_test.go new file mode 100644 index 00000000000..4cf93e30085 --- /dev/null +++ b/go/test/endtoend/tabletmanager/main_test.go @@ -0,0 +1,195 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package tabletmanager + +import ( + "context" + "flag" + "fmt" + "os" + "path" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/test/endtoend/cluster" + tabletpb "vitess.io/vitess/go/vt/proto/topodata" + tmc "vitess.io/vitess/go/vt/vttablet/grpctmclient" +) + +var ( + clusterInstance *cluster.LocalProcessCluster + tmClient *tmc.Client + masterTabletParams mysql.ConnParams + replicaTabletParams mysql.ConnParams + masterTablet cluster.Vttablet + replicaTablet cluster.Vttablet + rdonlyTablet cluster.Vttablet + hostname = "localhost" + keyspaceName = "ks" + shardName = "0" + keyspaceShard = "ks/" + shardName + dbName = "vt_" + keyspaceName + username = "vt_dba" + cell = "zone1" + sqlSchema = ` + create table t1( + id bigint, + value varchar(16), + primary key(id) + ) Engine=InnoDB; +` + + vSchema = ` + { + "sharded": true, + "vindexes": { + "hash": { + "type": "hash" + } + }, + "tables": { + "t1": { + "column_vindexes": [ + { + "column": "id", + "name": "hash" + } + ] + } + } + }` +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitCode := func() int { + clusterInstance = cluster.NewCluster(cell, hostname) + defer clusterInstance.Teardown() + + // Start topo server + err := clusterInstance.StartTopo() + if err != nil { + return 1 + } + + // List of users authorized to execute vschema ddl operations + clusterInstance.VtGateExtraArgs = []string{"-vschema_ddl_authorized_users=%"} + // Set extra tablet args for lock timeout + clusterInstance.VtTabletExtraArgs = []string{ + "-lock_tables_timeout", "5s", + "-watch_replication_stream", + "-enable_replication_reporter", + } + // We do not need semiSync for this test case. + clusterInstance.EnableSemiSync = false + + // Start keyspace + keyspace := &cluster.Keyspace{ + Name: keyspaceName, + SchemaSQL: sqlSchema, + VSchema: vSchema, + } + + if err = clusterInstance.StartUnshardedKeyspace(*keyspace, 1, true); err != nil { + return 1 + } + + // Start vtgate + if err = clusterInstance.StartVtgate(); err != nil { + return 1 + } + + // Collect table paths and ports + tablets := clusterInstance.Keyspaces[0].Shards[0].Vttablets + for _, tablet := range tablets { + if tablet.Type == "master" { + masterTablet = *tablet + } else if tablet.Type != "rdonly" { + replicaTablet = *tablet + } else { + rdonlyTablet = *tablet + } + } + + // Set mysql tablet params + masterTabletParams = mysql.ConnParams{ + Uname: username, + DbName: dbName, + UnixSocket: path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("/vt_%010d/mysql.sock", masterTablet.TabletUID)), + } + replicaTabletParams = mysql.ConnParams{ + Uname: username, + DbName: dbName, + UnixSocket: path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("/vt_%010d/mysql.sock", replicaTablet.TabletUID)), + } + + // create tablet manager client + tmClient = tmc.NewClient() + + return m.Run() + }() + os.Exit(exitCode) +} + +func exec(t *testing.T, conn *mysql.Conn, query string) *sqltypes.Result { + t.Helper() + qr, err := conn.ExecuteFetch(query, 1000, true) + require.Nil(t, err) + return qr +} + +func tmcLockTables(ctx context.Context, tabletGrpcPort int) error { + vtablet := getTablet(tabletGrpcPort) + return tmClient.LockTables(ctx, vtablet) +} + +func tmcUnlockTables(ctx context.Context, tabletGrpcPort int) error { + vtablet := getTablet(tabletGrpcPort) + return tmClient.UnlockTables(ctx, vtablet) +} + +func tmcStopSlave(ctx context.Context, tabletGrpcPort int) error { + vtablet := getTablet(tabletGrpcPort) + return tmClient.StopSlave(ctx, vtablet) +} + +func tmcStartSlave(ctx context.Context, tabletGrpcPort int) error { + vtablet := getTablet(tabletGrpcPort) + return tmClient.StartSlave(ctx, vtablet) +} + +func tmcMasterPosition(ctx context.Context, tabletGrpcPort int) (string, error) { + vtablet := getTablet(tabletGrpcPort) + return tmClient.MasterPosition(ctx, vtablet) +} + +func tmcStartSlaveUntilAfter(ctx context.Context, tabletGrpcPort int, positon string, waittime time.Duration) error { + vtablet := getTablet(tabletGrpcPort) + return tmClient.StartSlaveUntilAfter(ctx, vtablet, positon, waittime) +} + +func getTablet(tabletGrpcPort int) *tabletpb.Tablet { + portMap := make(map[string]int32) + portMap["grpc"] = int32(tabletGrpcPort) + return &tabletpb.Tablet{Hostname: hostname, PortMap: portMap} +} diff --git a/go/test/endtoend/tabletmanager/master/tablet_master_test.go b/go/test/endtoend/tabletmanager/master/tablet_master_test.go new file mode 100644 index 00000000000..d92c941172c --- /dev/null +++ b/go/test/endtoend/tabletmanager/master/tablet_master_test.go @@ -0,0 +1,257 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ +package master + +import ( + "encoding/json" + "flag" + "fmt" + "net/http" + "os" + "testing" + + "vitess.io/vitess/go/json2" + + "vitess.io/vitess/go/test/endtoend/cluster" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + querypb "vitess.io/vitess/go/vt/proto/query" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" +) + +var ( + clusterInstance *cluster.LocalProcessCluster + masterTablet cluster.Vttablet + replicaTablet cluster.Vttablet + hostname = "localhost" + keyspaceName = "ks" + shardName = "0" + cell = "zone1" + sqlSchema = ` + create table t1( + id bigint, + value varchar(16), + primary key(id) + ) Engine=InnoDB; +` + + vSchema = ` + { + "sharded": true, + "vindexes": { + "hash": { + "type": "hash" + } + }, + "tables": { + "t1": { + "column_vindexes": [ + { + "column": "id", + "name": "hash" + } + ] + } + } + }` +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitCode := func() int { + clusterInstance = cluster.NewCluster(cell, hostname) + defer clusterInstance.Teardown() + + // Start topo server + err := clusterInstance.StartTopo() + if err != nil { + return 1 + } + + // Set extra tablet args for lock timeout + clusterInstance.VtTabletExtraArgs = []string{ + "-lock_tables_timeout", "5s", + "-watch_replication_stream", + "-enable_replication_reporter", + } + // We do not need semiSync for this test case. + clusterInstance.EnableSemiSync = false + + // Start keyspace + keyspace := &cluster.Keyspace{ + Name: keyspaceName, + SchemaSQL: sqlSchema, + VSchema: vSchema, + } + + if err = clusterInstance.StartUnshardedKeyspace(*keyspace, 1, false); err != nil { + return 1 + } + + // Collect table paths and ports + tablets := clusterInstance.Keyspaces[0].Shards[0].Vttablets + for _, tablet := range tablets { + if tablet.Type == "master" { + masterTablet = *tablet + } else if tablet.Type != "rdonly" { + replicaTablet = *tablet + } + } + + return m.Run() + }() + os.Exit(exitCode) +} + +func TestRepeatedInitShardMaster(t *testing.T) { + defer cluster.PanicHandler(t) + // Test that using InitShardMaster can go back and forth between 2 hosts. + + // Make replica tablet as master + err := clusterInstance.VtctlclientProcess.InitShardMaster(keyspaceName, shardName, cell, replicaTablet.TabletUID) + require.Nil(t, err) + + // Run health check on both, make sure they are both healthy. + // Also make sure the types are correct. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", masterTablet.Alias) + require.Nil(t, err) + checkHealth(t, masterTablet.HTTPPort, false) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", replicaTablet.Alias) + require.Nil(t, err) + checkHealth(t, replicaTablet.HTTPPort, false) + + checkTabletType(t, masterTablet.Alias, "REPLICA") + checkTabletType(t, replicaTablet.Alias, "MASTER") + + // Come back to the original tablet. + err = clusterInstance.VtctlclientProcess.InitShardMaster(keyspaceName, shardName, cell, masterTablet.TabletUID) + require.Nil(t, err) + + // Run health check on both, make sure they are both healthy. + // Also make sure the types are correct. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", masterTablet.Alias) + require.Nil(t, err) + checkHealth(t, masterTablet.HTTPPort, false) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", replicaTablet.Alias) + require.Nil(t, err) + checkHealth(t, replicaTablet.HTTPPort, false) + + checkTabletType(t, masterTablet.Alias, "MASTER") + checkTabletType(t, replicaTablet.Alias, "REPLICA") +} + +func TestMasterRestartSetsTERTimestamp(t *testing.T) { + defer cluster.PanicHandler(t) + // Test that TER timestamp is set when we restart the MASTER vttablet. + // TER = TabletExternallyReparented. + // See StreamHealthResponse.tablet_externally_reparented_timestamp for details. + + // Make replica as master + err := clusterInstance.VtctlclientProcess.InitShardMaster(keyspaceName, shardName, cell, replicaTablet.TabletUID) + require.Nil(t, err) + + err = replicaTablet.VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + + // Capture the current TER. + result, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput( + "VtTabletStreamHealth", "-count", "1", replicaTablet.Alias) + require.Nil(t, err) + + var streamHealthRes1 querypb.StreamHealthResponse + err = json.Unmarshal([]byte(result), &streamHealthRes1) + require.Nil(t, err) + actualType := streamHealthRes1.GetTarget().GetTabletType() + tabletType := topodatapb.TabletType_value["MASTER"] + got := fmt.Sprintf("%d", actualType) + want := fmt.Sprintf("%d", tabletType) + assert.Equal(t, want, got) + assert.NotNil(t, streamHealthRes1.GetTabletExternallyReparentedTimestamp()) + assert.True(t, streamHealthRes1.GetTabletExternallyReparentedTimestamp() > 0, + "TER on MASTER must be set after InitShardMaster") + + // Restart the MASTER vttablet and test again + + // kill the newly promoted master tablet + err = replicaTablet.VttabletProcess.TearDown() + require.Nil(t, err) + + // Start Vttablet + err = clusterInstance.StartVttablet(&replicaTablet, "SERVING", false, cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + // Make sure that the TER did not change + result, err = clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput( + "VtTabletStreamHealth", "-count", "1", replicaTablet.Alias) + require.Nil(t, err) + + var streamHealthRes2 querypb.StreamHealthResponse + err = json.Unmarshal([]byte(result), &streamHealthRes2) + require.Nil(t, err) + + actualType = streamHealthRes2.GetTarget().GetTabletType() + tabletType = topodatapb.TabletType_value["MASTER"] + got = fmt.Sprintf("%d", actualType) + want = fmt.Sprintf("%d", tabletType) + assert.Equal(t, want, got) + + assert.NotNil(t, streamHealthRes2.GetTabletExternallyReparentedTimestamp()) + assert.True(t, streamHealthRes2.GetTabletExternallyReparentedTimestamp() == streamHealthRes1.GetTabletExternallyReparentedTimestamp(), + fmt.Sprintf("When the MASTER vttablet was restarted, "+ + "the TER timestamp must be set by reading the old value from the tablet record. Old: %d, New: %d", + streamHealthRes1.GetTabletExternallyReparentedTimestamp(), + streamHealthRes2.GetTabletExternallyReparentedTimestamp())) + + // Reset master + err = clusterInstance.VtctlclientProcess.InitShardMaster(keyspaceName, shardName, cell, masterTablet.TabletUID) + require.Nil(t, err) + err = masterTablet.VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + +} + +func checkHealth(t *testing.T, port int, shouldError bool) { + url := fmt.Sprintf("http://localhost:%d/healthz", port) + resp, err := http.Get(url) + require.Nil(t, err) + if shouldError { + assert.True(t, resp.StatusCode > 400) + } else { + assert.Equal(t, 200, resp.StatusCode) + } +} + +func checkTabletType(t *testing.T, tabletAlias string, typeWant string) { + result, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("GetTablet", tabletAlias) + require.Nil(t, err) + + var tablet topodatapb.Tablet + err = json2.Unmarshal([]byte(result), &tablet) + require.Nil(t, err) + + actualType := tablet.GetType() + got := fmt.Sprintf("%d", actualType) + + tabletType := topodatapb.TabletType_value[typeWant] + want := fmt.Sprintf("%d", tabletType) + + assert.Equal(t, want, got) +} diff --git a/go/test/endtoend/tabletmanager/qps_test.go b/go/test/endtoend/tabletmanager/qps_test.go new file mode 100644 index 00000000000..41f218f79ed --- /dev/null +++ b/go/test/endtoend/tabletmanager/qps_test.go @@ -0,0 +1,89 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ +package tabletmanager + +import ( + "context" + "encoding/json" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/stretchr/testify/assert" + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/test/endtoend/cluster" + querypb "vitess.io/vitess/go/vt/proto/query" +) + +func TestQPS(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + + vtParams := mysql.ConnParams{ + Host: "localhost", + Port: clusterInstance.VtgateMySQLPort, + } + vtGateConn, err := mysql.Connect(ctx, &vtParams) + require.Nil(t, err) + defer vtGateConn.Close() + + replicaConn, err := mysql.Connect(ctx, &replicaTabletParams) + require.Nil(t, err) + defer replicaConn.Close() + + // Sanity Check + exec(t, vtGateConn, "delete from t1") + exec(t, vtGateConn, "insert into t1(id, value) values(1,'a'), (2,'b')") + checkDataOnReplica(t, replicaConn, `[[VARCHAR("a")] [VARCHAR("b")]]`) + + // Test that VtTabletStreamHealth reports a QPS >0.0. + // Therefore, issue several reads first. + // NOTE: This may be potentially flaky because we'll observe a QPS >0.0 + // exactly "once" for the duration of one sampling interval (5s) and + // after that we'll see 0.0 QPS rates again. If this becomes actually + // flaky, we need to read continuously in a separate thread. + + n := 0 + for n < 15 { + n++ + // Run queries via vtGate so that they are counted. + exec(t, vtGateConn, "select * from t1") + } + + // This may take up to 5 seconds to become true because we sample the query + // counts for the rates only every 5 seconds. + + var qpsIncreased bool + timeout := time.Now().Add(12 * time.Second) + for time.Now().Before(timeout) { + result, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("VtTabletStreamHealth", "-count", "1", masterTablet.Alias) + require.Nil(t, err) + var streamHealthResponse querypb.StreamHealthResponse + + err = json.Unmarshal([]byte(result), &streamHealthResponse) + require.Nil(t, err) + + realTimeStats := streamHealthResponse.GetRealtimeStats() + qps := realTimeStats.GetQps() + if qps > 0.0 { + qpsIncreased = true + break + } + time.Sleep(100 * time.Millisecond) + } + assert.True(t, qpsIncreased, "qps should be more that 0") +} diff --git a/go/test/endtoend/tabletmanager/tablet_health_test.go b/go/test/endtoend/tabletmanager/tablet_health_test.go new file mode 100644 index 00000000000..79fa182acd5 --- /dev/null +++ b/go/test/endtoend/tabletmanager/tablet_health_test.go @@ -0,0 +1,464 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package tabletmanager + +import ( + "bufio" + "context" + "fmt" + "net/http" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/stretchr/testify/assert" + "vitess.io/vitess/go/json2" + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/test/endtoend/cluster" + querypb "vitess.io/vitess/go/vt/proto/query" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" +) + +// TabletReshuffle test if a vttablet can be pointed at an existing mysql +func TestTabletReshuffle(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + + masterConn, err := mysql.Connect(ctx, &masterTabletParams) + require.Nil(t, err) + defer masterConn.Close() + + replicaConn, err := mysql.Connect(ctx, &replicaTabletParams) + require.Nil(t, err) + defer replicaConn.Close() + + // Sanity Check + exec(t, masterConn, "delete from t1") + exec(t, masterConn, "insert into t1(id, value) values(1,'a'), (2,'b')") + checkDataOnReplica(t, replicaConn, `[[VARCHAR("a")] [VARCHAR("b")]]`) + + //Create new tablet + rTablet := clusterInstance.GetVttabletInstance("replica", 0, "") + + //Init Tablets + err = clusterInstance.VtctlclientProcess.InitTablet(rTablet, cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + // mycnf_server_id prevents vttablet from reading the mycnf + // Pointing to masterTablet's socket file + clusterInstance.VtTabletExtraArgs = []string{ + "-lock_tables_timeout", "5s", + "-mycnf_server_id", fmt.Sprintf("%d", rTablet.TabletUID), + "-db_socket", fmt.Sprintf("%s/mysql.sock", masterTablet.VttabletProcess.Directory), + } + // SupportsBackup=False prevents vttablet from trying to restore + // Start vttablet process + err = clusterInstance.StartVttablet(rTablet, "SERVING", false, cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + sql := "select value from t1" + args := []string{ + "VtTabletExecute", + "-options", "included_fields:TYPE_ONLY", + "-json", + rTablet.Alias, + sql, + } + result, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput(args...) + require.Nil(t, err) + assertExcludeFields(t, result) + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("Backup", rTablet.Alias) + assert.Error(t, err, "cannot perform backup without my.cnf") + + // Reset the VtTabletExtraArgs + clusterInstance.VtTabletExtraArgs = []string{} + killTablets(t, rTablet) +} + +func TestHealthCheck(t *testing.T) { + // Add one replica that starts not initialized + // (for the replica, we let vttablet do the InitTablet) + defer cluster.PanicHandler(t) + ctx := context.Background() + + rTablet := clusterInstance.GetVttabletInstance("replica", 0, "") + + // Start Mysql Processes and return connection + replicaConn, err := cluster.StartMySQLAndGetConnection(ctx, rTablet, username, clusterInstance.TmpDirectory) + require.Nil(t, err) + + defer replicaConn.Close() + + // Create database in mysql + exec(t, replicaConn, fmt.Sprintf("create database vt_%s", keyspaceName)) + + //Init Replica Tablet + err = clusterInstance.VtctlclientProcess.InitTablet(rTablet, cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + // start vttablet process, should be in SERVING state as we already have a master + err = clusterInstance.StartVttablet(rTablet, "SERVING", false, cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + masterConn, err := mysql.Connect(ctx, &masterTabletParams) + require.Nil(t, err) + defer masterConn.Close() + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", rTablet.Alias) + require.Nil(t, err) + checkHealth(t, rTablet.HTTPPort, false) + + // Make sure the master is still master + checkTabletType(t, masterTablet.Alias, "MASTER") + exec(t, masterConn, "stop slave") + + // stop replication, make sure we don't go unhealthy. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("StopSlave", rTablet.Alias) + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", rTablet.Alias) + require.Nil(t, err) + + // make sure the health stream is updated + result, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("VtTabletStreamHealth", "-count", "1", rTablet.Alias) + require.Nil(t, err) + verifyStreamHealth(t, result) + + // then restart replication, make sure we stay healthy + err = clusterInstance.VtctlclientProcess.ExecuteCommand("StopSlave", rTablet.Alias) + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", rTablet.Alias) + require.Nil(t, err) + checkHealth(t, rTablet.HTTPPort, false) + + // now test VtTabletStreamHealth returns the right thing + result, err = clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("VtTabletStreamHealth", "-count", "2", rTablet.Alias) + require.Nil(t, err) + scanner := bufio.NewScanner(strings.NewReader(result)) + for scanner.Scan() { + // fmt.Println() // Println will add back the final '\n' + verifyStreamHealth(t, scanner.Text()) + } + + // Manual cleanup of processes + killTablets(t, rTablet) +} + +func checkHealth(t *testing.T, port int, shouldError bool) { + url := fmt.Sprintf("http://localhost:%d/healthz", port) + resp, err := http.Get(url) + require.Nil(t, err) + if shouldError { + assert.True(t, resp.StatusCode > 400) + } else { + assert.Equal(t, 200, resp.StatusCode) + } +} + +func checkTabletType(t *testing.T, tabletAlias string, typeWant string) { + result, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("GetTablet", tabletAlias) + require.Nil(t, err) + + var tablet topodatapb.Tablet + err = json2.Unmarshal([]byte(result), &tablet) + require.Nil(t, err) + + actualType := tablet.GetType() + got := fmt.Sprintf("%d", actualType) + + tabletType := topodatapb.TabletType_value[typeWant] + want := fmt.Sprintf("%d", tabletType) + + assert.Equal(t, want, got) +} + +func verifyStreamHealth(t *testing.T, result string) { + var streamHealthResponse querypb.StreamHealthResponse + err := json2.Unmarshal([]byte(result), &streamHealthResponse) + require.Nil(t, err) + serving := streamHealthResponse.GetServing() + UID := streamHealthResponse.GetTabletAlias().GetUid() + realTimeStats := streamHealthResponse.GetRealtimeStats() + secondsBehindMaster := realTimeStats.GetSecondsBehindMaster() + assert.True(t, serving, "Tablet should be in serving state") + assert.True(t, UID > 0, "Tablet should contain uid") + // secondsBehindMaster varies till 7200 so setting safe limit + assert.True(t, secondsBehindMaster < 10000, "Slave should not be behind master") +} + +func TestHealthCheckDrainedStateDoesNotShutdownQueryService(t *testing.T) { + // This test is similar to test_health_check, but has the following differences: + // - the second tablet is an 'rdonly' and not a 'replica' + // - the second tablet will be set to 'drained' and we expect that + // - the query service won't be shutdown + + //Wait if tablet is not in service state + defer cluster.PanicHandler(t) + err := rdonlyTablet.VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + + // Check tablet health + checkHealth(t, rdonlyTablet.HTTPPort, false) + assert.Equal(t, "SERVING", rdonlyTablet.VttabletProcess.GetTabletStatus()) + + // Change from rdonly to drained and stop replication. (These + // actions are similar to the SplitClone vtworker command + // implementation.) The tablet will stay healthy, and the + // query service is still running. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", rdonlyTablet.Alias, "drained") + require.Nil(t, err) + // Trying to drain the same tablet again, should error + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", rdonlyTablet.Alias, "drained") + assert.Error(t, err, "already drained") + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("StopSlave", rdonlyTablet.Alias) + require.Nil(t, err) + // Trigger healthcheck explicitly to avoid waiting for the next interval. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", rdonlyTablet.Alias) + require.Nil(t, err) + + checkTabletType(t, rdonlyTablet.Alias, "DRAINED") + + // Query service is still running. + err = rdonlyTablet.VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + + // Restart replication. Tablet will become healthy again. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeSlaveType", rdonlyTablet.Alias, "rdonly") + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("StartSlave", rdonlyTablet.Alias) + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", rdonlyTablet.Alias) + require.Nil(t, err) + checkHealth(t, rdonlyTablet.HTTPPort, false) +} + +func TestIgnoreHealthError(t *testing.T) { + // This test verify the tablet health by Ignoring the error + // For this case we need a healthy tablet in a shard without any master. + // When we try to make a connection to such tablet we get "no slave status" error. + // We will then ignore this error and verify if the status report the tablet as Healthy. + + // Create a new shard + defer cluster.PanicHandler(t) + newShard := &cluster.Shard{ + Name: "1", + } + + // Start mysql process + tablet := clusterInstance.GetVttabletInstance("replica", 0, "") + tablet.MysqlctlProcess = *cluster.MysqlCtlProcessInstance(tablet.TabletUID, tablet.MySQLPort, clusterInstance.TmpDirectory) + err := tablet.MysqlctlProcess.Start() + require.Nil(t, err) + + // start vttablet process + tablet.VttabletProcess = cluster.VttabletProcessInstance(tablet.HTTPPort, + tablet.GrpcPort, + tablet.TabletUID, + clusterInstance.Cell, + newShard.Name, + clusterInstance.Keyspaces[0].Name, + clusterInstance.VtctldProcess.Port, + tablet.Type, + clusterInstance.TopoProcess.Port, + clusterInstance.Hostname, + clusterInstance.TmpDirectory, + clusterInstance.VtTabletExtraArgs, + clusterInstance.EnableSemiSync) + tablet.Alias = tablet.VttabletProcess.TabletPath + newShard.Vttablets = append(newShard.Vttablets, tablet) + + clusterInstance.Keyspaces[0].Shards = append(clusterInstance.Keyspaces[0].Shards, *newShard) + + // Init Tablet + err = clusterInstance.VtctlclientProcess.InitTablet(tablet, cell, keyspaceName, hostname, newShard.Name) + require.Nil(t, err) + + // create database + err = tablet.VttabletProcess.CreateDB(keyspaceName) + require.Nil(t, err) + + // Start Vttablet, it should be NOT_SERVING as there is no master + err = clusterInstance.StartVttablet(tablet, "NOT_SERVING", false, cell, keyspaceName, hostname, newShard.Name) + require.Nil(t, err) + + // Force it healthy. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("IgnoreHealthError", tablet.Alias, ".*no slave status.*") + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", tablet.Alias) + require.Nil(t, err) + err = tablet.VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + checkHealth(t, tablet.HTTPPort, false) + + // Turn off the force-healthy. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("IgnoreHealthError", tablet.Alias, "") + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", tablet.Alias) + require.Nil(t, err) + err = tablet.VttabletProcess.WaitForTabletType("NOT_SERVING") + require.Nil(t, err) + checkHealth(t, tablet.HTTPPort, true) + + // Tear down custom processes + killTablets(t, tablet) +} + +func TestNoMysqlHealthCheck(t *testing.T) { + // This test starts a vttablet with no mysql port, while mysql is down. + // It makes sure vttablet will start properly and be unhealthy. + // Then we start mysql, and make sure vttablet becomes healthy. + defer cluster.PanicHandler(t) + ctx := context.Background() + + rTablet := clusterInstance.GetVttabletInstance("replica", 0, "") + mTablet := clusterInstance.GetVttabletInstance("replica", 0, "") + + // Start Mysql Processes and return connection + masterConn, err := cluster.StartMySQLAndGetConnection(ctx, mTablet, username, clusterInstance.TmpDirectory) + require.Nil(t, err) + defer masterConn.Close() + + replicaConn, err := cluster.StartMySQLAndGetConnection(ctx, rTablet, username, clusterInstance.TmpDirectory) + require.Nil(t, err) + defer replicaConn.Close() + + // Create database in mysql + exec(t, masterConn, fmt.Sprintf("create database vt_%s", keyspaceName)) + exec(t, replicaConn, fmt.Sprintf("create database vt_%s", keyspaceName)) + + //Get the gtid to ensure we bring master and slave at same position + qr := exec(t, masterConn, "SELECT @@GLOBAL.gtid_executed") + gtid := string(qr.Rows[0][0].Raw()) + + // Ensure master ans salve are at same position + exec(t, replicaConn, "STOP SLAVE") + exec(t, replicaConn, "RESET MASTER") + exec(t, replicaConn, "RESET SLAVE") + exec(t, replicaConn, fmt.Sprintf("SET GLOBAL gtid_purged='%s'", gtid)) + exec(t, replicaConn, fmt.Sprintf("CHANGE MASTER TO MASTER_HOST='%s', MASTER_PORT=%d, MASTER_USER='vt_repl', MASTER_AUTO_POSITION = 1", hostname, mTablet.MySQLPort)) + exec(t, replicaConn, "START SLAVE") + + // now shutdown all mysqld + err = rTablet.MysqlctlProcess.Stop() + require.Nil(t, err) + err = mTablet.MysqlctlProcess.Stop() + require.Nil(t, err) + + //Init Tablets + err = clusterInstance.VtctlclientProcess.InitTablet(mTablet, cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + err = clusterInstance.VtctlclientProcess.InitTablet(rTablet, cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + // Start vttablet process, should be in NOT_SERVING state as mysqld is not running + err = clusterInstance.StartVttablet(mTablet, "NOT_SERVING", false, cell, keyspaceName, hostname, shardName) + require.Nil(t, err, "error should be Nil") + err = clusterInstance.StartVttablet(rTablet, "NOT_SERVING", false, cell, keyspaceName, hostname, shardName) + require.Nil(t, err, "error should be Nil") + + // Check Health should fail as Mysqld is not found + checkHealth(t, mTablet.HTTPPort, true) + checkHealth(t, rTablet.HTTPPort, true) + + // Tell slave to not try to repair replication in healthcheck. + // The StopSlave will ultimately fail because mysqld is not running, + // But vttablet should remember that it's not supposed to fix replication. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("StopSlave", rTablet.Alias) + assert.Error(t, err, "Fail as mysqld not running") + + //The above notice to not fix replication should survive tablet restart. + err = rTablet.VttabletProcess.TearDown() + require.Nil(t, err) + err = rTablet.VttabletProcess.Setup() + require.Nil(t, err) + + // restart mysqld + rTablet.MysqlctlProcess.InitMysql = false + err = rTablet.MysqlctlProcess.Start() + require.Nil(t, err) + mTablet.MysqlctlProcess.InitMysql = false + err = mTablet.MysqlctlProcess.Start() + require.Nil(t, err) + + // the master should still be healthy + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", mTablet.Alias) + require.Nil(t, err) + checkHealth(t, mTablet.HTTPPort, false) + + // the slave will now be healthy, but report a very high replication + // lag, because it can't figure out what it exactly is. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RunHealthCheck", rTablet.Alias) + require.Nil(t, err) + assert.Equal(t, "SERVING", rTablet.VttabletProcess.GetTabletStatus()) + checkHealth(t, rTablet.HTTPPort, false) + + result, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("VtTabletStreamHealth", "-count", "1", rTablet.Alias) + require.Nil(t, err) + var streamHealthResponse querypb.StreamHealthResponse + err = json2.Unmarshal([]byte(result), &streamHealthResponse) + require.Nil(t, err) + realTimeStats := streamHealthResponse.GetRealtimeStats() + secondsBehindMaster := realTimeStats.GetSecondsBehindMaster() + assert.True(t, secondsBehindMaster == 7200) + + // restart replication, wait until health check goes small + // (a value of zero is default and won't be in structure) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("StartSlave", rTablet.Alias) + require.Nil(t, err) + + timeout := time.Now().Add(10 * time.Second) + for time.Now().Before(timeout) { + result, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("VtTabletStreamHealth", "-count", "1", rTablet.Alias) + require.Nil(t, err) + var streamHealthResponse querypb.StreamHealthResponse + err = json2.Unmarshal([]byte(result), &streamHealthResponse) + require.Nil(t, err) + realTimeStats := streamHealthResponse.GetRealtimeStats() + secondsBehindMaster := realTimeStats.GetSecondsBehindMaster() + if secondsBehindMaster < 30 { + break + } else { + time.Sleep(100 * time.Millisecond) + } + } + + // wait for the tablet to fix its mysql port + result, err = clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("GetTablet", rTablet.Alias) + require.Nil(t, err) + var tablet topodatapb.Tablet + err = json2.Unmarshal([]byte(result), &tablet) + require.Nil(t, err) + portMap := tablet.GetPortMap() + mysqlPort := int(portMap["mysql"]) + assert.True(t, mysqlPort == rTablet.MySQLPort, "mysql port in tablet record") + + // Tear down custom processes + killTablets(t, rTablet, mTablet) +} + +func killTablets(t *testing.T, tablets ...*cluster.Vttablet) { + for _, tablet := range tablets { + //Stop Mysqld + tablet.MysqlctlProcess.Stop() + + //Tear down Tablet + tablet.VttabletProcess.TearDown() + } +} diff --git a/go/test/endtoend/tabletmanager/tablet_security_policy_test.go b/go/test/endtoend/tabletmanager/tablet_security_policy_test.go new file mode 100644 index 00000000000..9bf78382040 --- /dev/null +++ b/go/test/endtoend/tabletmanager/tablet_security_policy_test.go @@ -0,0 +1,159 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ +package tabletmanager + +import ( + "context" + "fmt" + "io/ioutil" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/test/endtoend/cluster" +) + +func TestFallbackSecurityPolicy(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + mTablet := clusterInstance.GetVttabletInstance("replica", 0, "") + + //Init Tablets + err := clusterInstance.VtctlclientProcess.InitTablet(mTablet, cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + // Start Mysql Processes + err = cluster.StartMySQL(ctx, mTablet, username, clusterInstance.TmpDirectory) + require.Nil(t, err) + + // Requesting an unregistered security_policy should fallback to deny-all. + clusterInstance.VtTabletExtraArgs = []string{"-security_policy", "bogus"} + err = clusterInstance.StartVttablet(mTablet, "NOT_SERVING", false, cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + // It should deny ADMIN role. + url := fmt.Sprintf("http://localhost:%d/streamqueryz/terminate", mTablet.HTTPPort) + assertNotAllowedURLTest(t, url) + + // It should deny MONITORING role. + url = fmt.Sprintf("http://localhost:%d/debug/health", mTablet.HTTPPort) + assertNotAllowedURLTest(t, url) + + // It should deny DEBUGGING role. + url = fmt.Sprintf("http://localhost:%d/queryz", mTablet.HTTPPort) + assertNotAllowedURLTest(t, url) + + // Reset the VtTabletExtraArgs + clusterInstance.VtTabletExtraArgs = []string{} + // Tear down custom processes + killTablets(t, mTablet) +} + +func assertNotAllowedURLTest(t *testing.T, url string) { + resp, err := http.Get(url) + require.Nil(t, err) + + body, err := ioutil.ReadAll(resp.Body) + require.Nil(t, err) + defer resp.Body.Close() + + assert.True(t, resp.StatusCode > 400) + assert.Contains(t, string(body), "Access denied: not allowed") +} + +func assertAllowedURLTest(t *testing.T, url string) { + resp, err := http.Get(url) + require.Nil(t, err) + + body, err := ioutil.ReadAll(resp.Body) + require.Nil(t, err) + defer resp.Body.Close() + + assert.NotContains(t, string(body), "Access denied: not allowed") +} + +func TestDenyAllSecurityPolicy(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + mTablet := clusterInstance.GetVttabletInstance("replica", 0, "") + + //Init Tablets + err := clusterInstance.VtctlclientProcess.InitTablet(mTablet, cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + // Start Mysql Processes + err = cluster.StartMySQL(ctx, mTablet, username, clusterInstance.TmpDirectory) + require.Nil(t, err) + + // Requesting a deny-all security_policy. + clusterInstance.VtTabletExtraArgs = []string{"-security_policy", "deny-all"} + err = clusterInstance.StartVttablet(mTablet, "NOT_SERVING", false, cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + // It should deny ADMIN role. + url := fmt.Sprintf("http://localhost:%d/streamqueryz/terminate", mTablet.HTTPPort) + assertNotAllowedURLTest(t, url) + + // It should deny MONITORING role. + url = fmt.Sprintf("http://localhost:%d/debug/health", mTablet.HTTPPort) + assertNotAllowedURLTest(t, url) + + // It should deny DEBUGGING role. + url = fmt.Sprintf("http://localhost:%d/queryz", mTablet.HTTPPort) + assertNotAllowedURLTest(t, url) + + // Reset the VtTabletExtraArgs + clusterInstance.VtTabletExtraArgs = []string{} + // Tear down custom processes + killTablets(t, mTablet) +} + +func TestReadOnlySecurityPolicy(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + mTablet := clusterInstance.GetVttabletInstance("replica", 0, "") + + //Init Tablets + err := clusterInstance.VtctlclientProcess.InitTablet(mTablet, cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + // Start Mysql Processes + err = cluster.StartMySQL(ctx, mTablet, username, clusterInstance.TmpDirectory) + require.Nil(t, err) + + // Requesting a read-only security_policy. + clusterInstance.VtTabletExtraArgs = []string{"-security_policy", "read-only"} + err = clusterInstance.StartVttablet(mTablet, "NOT_SERVING", false, cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + // It should deny ADMIN role. + url := fmt.Sprintf("http://localhost:%d/streamqueryz/terminate", mTablet.HTTPPort) + assertNotAllowedURLTest(t, url) + + // It should deny MONITORING role. + url = fmt.Sprintf("http://localhost:%d/debug/health", mTablet.HTTPPort) + assertAllowedURLTest(t, url) + + // It should deny DEBUGGING role. + url = fmt.Sprintf("http://localhost:%d/queryz", mTablet.HTTPPort) + assertAllowedURLTest(t, url) + + // Reset the VtTabletExtraArgs + clusterInstance.VtTabletExtraArgs = []string{} + // Tear down custom processes + killTablets(t, mTablet) +} diff --git a/go/test/endtoend/tabletmanager/tablet_test.go b/go/test/endtoend/tabletmanager/tablet_test.go new file mode 100644 index 00000000000..50ab6a75730 --- /dev/null +++ b/go/test/endtoend/tabletmanager/tablet_test.go @@ -0,0 +1,88 @@ +/* +Copyright 2020 The Vitess Authors. + +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. +*/ + +package tabletmanager + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/test/endtoend/cluster" + "vitess.io/vitess/go/vt/log" +) + +// TestLocalMetadata tests the contents of local_metadata table after vttablet startup +func TestLocalMetadata(t *testing.T) { + defer cluster.PanicHandler(t) + // by default tablets are started with -restore_from_backup + // so metadata should exist + cluster.VerifyLocalMetadata(t, &replicaTablet, keyspaceName, shardName, cell) + + // Create new tablet + rTablet := clusterInstance.GetVttabletInstance("replica", 0, "") + + // Init Tablet + err := clusterInstance.VtctlclientProcess.InitTablet(rTablet, cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + clusterInstance.VtTabletExtraArgs = []string{ + "-lock_tables_timeout", "5s", + "-init_populate_metadata", + } + rTablet.MysqlctlProcess = *cluster.MysqlCtlProcessInstance(rTablet.TabletUID, rTablet.MySQLPort, clusterInstance.TmpDirectory) + err = rTablet.MysqlctlProcess.Start() + require.Nil(t, err) + + log.Info(fmt.Sprintf("Started vttablet %v", rTablet)) + // SupportsBackup=False prevents vttablet from trying to restore + // Start vttablet process + err = clusterInstance.StartVttablet(rTablet, "SERVING", false, cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + cluster.VerifyLocalMetadata(t, rTablet, keyspaceName, shardName, cell) + + // Create another new tablet + rTablet2 := clusterInstance.GetVttabletInstance("replica", 0, "") + + // Init Tablet + err = clusterInstance.VtctlclientProcess.InitTablet(rTablet2, cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + // start with -init_populate_metadata false (default) + clusterInstance.VtTabletExtraArgs = []string{ + "-lock_tables_timeout", "5s", + } + rTablet2.MysqlctlProcess = *cluster.MysqlCtlProcessInstance(rTablet2.TabletUID, rTablet2.MySQLPort, clusterInstance.TmpDirectory) + err = rTablet2.MysqlctlProcess.Start() + require.Nil(t, err) + + log.Info(fmt.Sprintf("Started vttablet %v", rTablet2)) + // SupportsBackup=False prevents vttablet from trying to restore + // Start vttablet process + err = clusterInstance.StartVttablet(rTablet2, "SERVING", false, cell, keyspaceName, hostname, shardName) + require.Nil(t, err) + + // check that tablet did _not_ get populated + qr, err := rTablet2.VttabletProcess.QueryTablet("select * from _vt.local_metadata", keyspaceName, false) + require.Nil(t, err) + require.Nil(t, qr.Rows) + + // Reset the VtTabletExtraArgs and kill tablets + clusterInstance.VtTabletExtraArgs = []string{} + killTablets(t, rTablet, rTablet2) +} diff --git a/go/test/endtoend/vtcombo/vttest_sample_test.go b/go/test/endtoend/vtcombo/vttest_sample_test.go new file mode 100644 index 00000000000..b6e41774cee --- /dev/null +++ b/go/test/endtoend/vtcombo/vttest_sample_test.go @@ -0,0 +1,213 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package vtcombo + +import ( + "context" + "encoding/json" + "flag" + "fmt" + "io/ioutil" + "net/http" + "os" + "os/exec" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + querypb "vitess.io/vitess/go/vt/proto/query" + vttestpb "vitess.io/vitess/go/vt/proto/vttest" + "vitess.io/vitess/go/vt/vtgate/vtgateconn" + "vitess.io/vitess/go/vt/vttest" +) + +var ( + localCluster *vttest.LocalCluster + grpcAddress string + vtctldAddr string + hostname = "localhost" + ks1 = "test_keyspace" + redirected = "redirected" +) + +func TestMain(m *testing.M) { + flag.Parse() + + exitcode, err := func() (int, error) { + + topology := new(vttestpb.VTTestTopology) + topology.Keyspaces = []*vttestpb.Keyspace{ + { + Name: ks1, + Shards: []*vttestpb.Shard{ + {Name: "-80"}, + {Name: "80-"}, + }, + RdonlyCount: 1, + ReplicaCount: 2, + }, + { + Name: redirected, + ServedFrom: ks1, + }, + } + + var cfg vttest.Config + cfg.Topology = topology + cfg.SchemaDir = os.Getenv("VTROOT") + "/test/vttest_schema" + cfg.DefaultSchemaDir = os.Getenv("VTROOT") + "/test/vttest_schema/default" + + localCluster = &vttest.LocalCluster{ + Config: cfg, + } + + err := localCluster.Setup() + defer localCluster.TearDown() + if err != nil { + return 1, err + } + + grpcAddress = fmt.Sprintf("localhost:%d", localCluster.Env.PortForProtocol("vtcombo", "grpc")) + vtctldAddr = fmt.Sprintf("localhost:%d", localCluster.Env.PortForProtocol("vtcombo", "port")) + + return m.Run(), nil + }() + if err != nil { + fmt.Printf("%v\n", err) + os.Exit(1) + } else { + os.Exit(exitcode) + } +} + +func TestStandalone(t *testing.T) { + // validate debug vars + resp, err := http.Get(fmt.Sprintf("http://%s/debug/vars", vtctldAddr)) + require.Nil(t, err) + require.Equal(t, 200, resp.StatusCode) + resultMap := make(map[string]interface{}) + respByte, _ := ioutil.ReadAll(resp.Body) + err = json.Unmarshal(respByte, &resultMap) + require.Nil(t, err) + cmd, _ := resultMap["cmdline"] + require.NotNil(t, cmd, "cmdline is not available in debug vars") + tmp, _ := cmd.([]interface{}) + require.Contains(t, tmp[0], "vtcombo") + + ctx := context.Background() + conn, err := vtgateconn.Dial(ctx, grpcAddress) + require.Nil(t, err) + defer conn.Close() + cur := conn.Session(ks1+":-80@master", nil) + + idStart, rowCount := 1000, 500 + query := "insert into test_table (id, msg, keyspace_id) values (:id, :msg, :keyspace_id)" + _, err = cur.Execute(ctx, "begin", nil) + require.Nil(t, err) + + for i := idStart; i < idStart+rowCount; i++ { + bindVariables := map[string]*querypb.BindVariable{ + "id": {Type: querypb.Type_UINT64, Value: []byte(fmt.Sprint(i))}, + "msg": {Type: querypb.Type_VARCHAR, Value: []byte(fmt.Sprint("test", i))}, + "keyspace_id": {Type: querypb.Type_UINT64, Value: []byte(fmt.Sprint(i))}, + } + _, err = cur.Execute(ctx, query, bindVariables) + require.Nil(t, err) + } + + _, err = cur.Execute(ctx, "commit", nil) + require.Nil(t, err) + + cur = conn.Session(ks1+":-80@rdonly", nil) + bindVariables := map[string]*querypb.BindVariable{ + "id_start": {Type: querypb.Type_UINT64, Value: []byte(fmt.Sprint(idStart))}, + } + res, err := cur.Execute(ctx, "select * from test_table where id >= :id_start", bindVariables) + require.Nil(t, err) + + assert.Equal(t, rowCount, len(res.Rows)) + + cur = conn.Session(redirected+":-80@replica", nil) + bindVariables = map[string]*querypb.BindVariable{ + "id_start": {Type: querypb.Type_UINT64, Value: []byte(fmt.Sprint(idStart))}, + } + res, err = cur.Execute(ctx, "select * from test_table where id = :id_start", bindVariables) + require.Nil(t, err) + require.Equal(t, 1, len(res.Rows)) + assert.Equal(t, "VARCHAR(\"test1000\")", res.Rows[0][1].String()) + + cur = conn.Session(ks1+":80-@master", nil) + _, err = cur.Execute(ctx, "begin", nil) + require.Nil(t, err) + + i := 0x810000000000000 + bindVariables = map[string]*querypb.BindVariable{ + "id": {Type: querypb.Type_UINT64, Value: []byte(fmt.Sprint(i))}, + "msg": {Type: querypb.Type_VARCHAR, Value: []byte(fmt.Sprint("test", i))}, + "keyspace_id": {Type: querypb.Type_UINT64, Value: []byte(fmt.Sprint(i))}, + } + _, err = cur.Execute(ctx, query, bindVariables) + require.Nil(t, err) + + _, err = cur.Execute(ctx, "commit", nil) + require.Nil(t, err) + + tmpCmd := exec.Command("vtctlclient", "-vtctl_client_protocol", "grpc", "-server", grpcAddress, "-stderrthreshold", "0", "ListAllTablets", "test") + + fmt.Println(tmpCmd.Args) + + output, err := tmpCmd.CombinedOutput() + require.Nil(t, err) + + numMaster, numReplica, numRdonly, numDash80, num80Dash := 0, 0, 0, 0, 0 + lines := strings.Split(string(output), "\n") + for _, line := range lines { + if !strings.HasPrefix(line, "test-") { + continue + } + parts := strings.Split(line, " ") + assert.Equal(t, "test_keyspace", parts[1]) + + switch parts[3] { + case "master": + numMaster++ + case "replica": + numReplica++ + case "rdonly": + numRdonly++ + default: + t.Logf("invalid tablet type %s", parts[3]) + } + + switch parts[2] { + case "-80": + numDash80++ + case "80-": + num80Dash++ + default: + t.Logf("invalid shard %s", parts[2]) + } + + } + + assert.Equal(t, 2, numMaster) + assert.Equal(t, 2, numReplica) + assert.Equal(t, 2, numRdonly) + assert.Equal(t, 3, numDash80) + assert.Equal(t, 3, num80Dash) +} diff --git a/go/test/endtoend/vtctldweb/vtctld_web_main_test.go b/go/test/endtoend/vtctldweb/vtctld_web_main_test.go new file mode 100644 index 00000000000..4e70e315824 --- /dev/null +++ b/go/test/endtoend/vtctldweb/vtctld_web_main_test.go @@ -0,0 +1,510 @@ +/* +Copyright 2020 The Vitess Authors. + +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. +*/ + +package vtctldweb + +import ( + "flag" + "fmt" + "math/rand" + "os" + "os/exec" + "strings" + "syscall" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/tebeka/selenium" + "github.com/tebeka/selenium/chrome" + "vitess.io/vitess/go/test/endtoend/cluster" + vttestpb "vitess.io/vitess/go/vt/proto/vttest" + "vitess.io/vitess/go/vt/vttest" +) + +var ( + localCluster *vttest.LocalCluster + hostname = "localhost" + wd selenium.WebDriver + seleniumService *selenium.Service + vtctldAddr string + ks1 = "test_keyspace" + ks2 = "test_keyspace2" + sqlSchema = "CREATE TABLE test_table (\n" + + " `id` BIGINT(20) UNSIGNED NOT NULL,\n" + + " `msg` VARCHAR(64),\n" + + " `keyspace_id` BIGINT(20) UNSIGNED NOT NULL,\n" + + " PRIMARY KEY (id)\n" + + ") ENGINE=InnoDB" +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitcode, err := func() (int, error) { + + // runs Xvfb in background + tearDownXvfb, err := RunXvfb() + if err != nil { + return 1, err + } + defer tearDownXvfb() + + // cluster setup using vtcombo + topology := new(vttestpb.VTTestTopology) + topology.Cells = []string{"test", "test2"} + topology.Keyspaces = []*vttestpb.Keyspace{ + { + Name: ks1, + Shards: []*vttestpb.Shard{ + {Name: "-80"}, + {Name: "80-"}, + }, + RdonlyCount: 2, + ReplicaCount: 2, + }, + { + Name: ks2, + Shards: []*vttestpb.Shard{ + {Name: "0"}, + }, + RdonlyCount: 2, + ReplicaCount: 1, + }, + } + + // create driver here + err = CreateWebDriver(getPort()) + if err != nil { + return 1, err + } + defer TeardownWebDriver() + + var cfg vttest.Config + cfg.Topology = topology + cfg.SchemaDir = os.Getenv("VTROOT") + "/test/vttest_schema" + cfg.DefaultSchemaDir = os.Getenv("VTROOT") + "/test/vttest_schema/default" + + localCluster = &vttest.LocalCluster{ + Config: cfg, + } + + err = localCluster.Setup() + defer localCluster.TearDown() + + vtctldAddr = fmt.Sprintf("http://localhost:%d", localCluster.Env.PortForProtocol("vtcombo", "port")) + if err != nil { + return 1, err + } + + return m.Run(), nil + }() + if err != nil { + fmt.Printf("%v\n", err) + os.Exit(1) + } else { + os.Exit(exitcode) + } +} + +// RunXvfb runs Xvfb command in background and returns the teardown function. +func RunXvfb() (func() error, error) { + + tmpProcess := exec.Command("Xvfb", ":15", "-ac") + + err := tmpProcess.Start() + if err != nil { + return nil, err + } + + exit := make(chan error) + go func() { + exit <- tmpProcess.Wait() + }() + + teardownFunc := func() error { + tmpProcess.Process.Signal(syscall.SIGTERM) + select { + case <-exit: + return nil + case <-time.After(10 * time.Second): + tmpProcess.Process.Kill() + return <-exit + } + } + + os.Setenv("DISPLAY", ":15") + + return teardownFunc, nil +} + +// CreateWebDriver Creates a webdriver object (local or remote for Travis). +func CreateWebDriver(port int) error { + // selenium.SetDebug(true) + + // Set common Options + options := selenium.ChromeDriver(os.Getenv("VTROOT") + "/dist") + + if os.Getenv("CI") == "true" && os.Getenv("TRAVIS") == "true" { + + capabilities := selenium.Capabilities{} + capabilities["tunnel-identifier"] = os.Getenv("TRAVIS_JOB_NUMBER") + capabilities["build"] = os.Getenv("TRAVIS_BUILD_NUMBER") + capabilities["platform"] = "Linux" + capabilities["browserName"] = "chrome" + capabilities["chromeOptions"] = options + + var err error + wd, err = selenium.NewRemote(capabilities, fmt.Sprintf("%s:%s@localhost:4445/wd/hub", os.Getenv("SAUCE_USERNAME"), os.Getenv("SAUCE_ACCESS_KEY"))) + if err != nil { + return err + } + + name, err := wd.CurrentWindowHandle() + return wd.ResizeWindow(name, 1280, 1024) + } + + // Only testing against Chrome for now + cc := selenium.Capabilities{"browserName": "chrome"} + cc.AddChrome(chrome.Capabilities{ + Args: []string{ + "--disable-gpu", + "--no-sandbox", + "--headless", + }, + }) + + os.Setenv("webdriver.chrome.driver", os.Getenv("VTROOT")+"/dist") + + var err error + seleniumService, err = selenium.NewChromeDriverService(os.Getenv("VTROOT")+"/dist/chromedriver/chromedriver", port, options) + if err != nil { + return err + } + + wd, err = selenium.NewRemote(cc, fmt.Sprintf("http://localhost:%d/wd/hub", port)) + if err != nil { + return err + } + name, err := wd.CurrentWindowHandle() + return wd.ResizeWindow(name, 1280, 1024) +} + +func TeardownWebDriver() { + wd.Quit() + if seleniumService != nil { + seleniumService.Stop() + + } +} + +func checkNewView(t *testing.T, keyspaces, cells, types, metrics []string, selectedKs, selectedCell, selectedType, selectedMetric string) { + checkDropdowns(t, keyspaces, cells, types, metrics, selectedKs, selectedCell, selectedType, selectedMetric) + checkHeatMaps(t, selectedKs) +} + +func checkHeatMaps(t *testing.T, selectedKs string) { + elem, err := wd.FindElement(selenium.ByTagName, "vt-status") + require.Nil(t, err) + + elems, err := elem.FindElements(selenium.ByTagName, "vt-heatmap") + require.Nil(t, err) + + if selectedKs == "all" { + availableKs := getDropdownOptions(t, "keyspace") + assert.Equal(t, len(elems), len(availableKs)-1) + for _, elem := range elems { + heading, err := elem.FindElement(selenium.ByID, "keyspaceName") + require.Nil(t, err) + + headingTxt := text(t, heading) + + _, err = elem.FindElement(selenium.ByID, headingTxt) + require.Nil(t, err) + + assert.Contains(t, availableKs, headingTxt) + } + return + } + + assert.Equal(t, 1, len(elems)) + heading, err := elems[0].FindElement(selenium.ByID, "keyspaceName") + require.Nil(t, err) + + headingTxt := text(t, heading) + + _, err = elem.FindElement(selenium.ByID, headingTxt) + require.Nil(t, err) + + assert.Equal(t, selectedKs, headingTxt) +} + +// changeDropdownOptions changes the selected value of dropdown. +func changeDropdownOptions(t *testing.T, dropdownID, dropdownValue string) { + statusContent, err := wd.FindElement(selenium.ByTagName, "vt-status") + require.Nil(t, err) + + dropdown, err := statusContent.FindElement(selenium.ByID, dropdownID) + require.Nil(t, err) + + click(t, dropdown) + options, err := dropdown.FindElements(selenium.ByTagName, "li") + require.Nil(t, err) + + triedOption := []string{} + for _, op := range options { + opTxt := text(t, op) + if opTxt == dropdownValue { + click(t, op) + return + } + + triedOption = append(triedOption, opTxt) + } + ss(t, "option_check") + t.Log("dropdown options change failed", strings.Join(triedOption, ","), dropdownValue) +} + +// checkDropdowns validates the dropdown values and selected value. +func checkDropdowns(t *testing.T, keyspaces, cells, types, metrics []string, selectedKs, selectedCell, selectedType, selectedMetric string) { + + Options := getDropdownOptions(t, "keyspace") + Selected := getDropdownSelection(t, "keyspace") + + assert.Equal(t, keyspaces, Options) + assert.Equal(t, selectedKs, Selected) + + Options = getDropdownOptions(t, "cell") + Selected = getDropdownSelection(t, "cell") + + assert.Equal(t, cells, Options) + assert.Equal(t, selectedCell, Selected) + + Options = getDropdownOptions(t, "type") + Selected = getDropdownSelection(t, "type") + + assert.Equal(t, types, Options) + assert.Equal(t, selectedType, Selected) + + Options = getDropdownOptions(t, "metric") + Selected = getDropdownSelection(t, "metric") + + assert.Equal(t, metrics, Options) + assert.Equal(t, selectedMetric, Selected) + +} + +// get element functions +// getDropdownSelection fetchs selected value for corresponding group. +func getDropdownSelection(t *testing.T, group string) string { + elem, err := wd.FindElement(selenium.ByTagName, "vt-status") + require.Nil(t, err) + elem, err = elem.FindElement(selenium.ByID, group) + require.Nil(t, err) + elem, err = elem.FindElement(selenium.ByTagName, "label") + require.Nil(t, err) + + return text(t, elem) +} + +// getDropdownOptions fetchs list of option available for corresponding group. +func getDropdownOptions(t *testing.T, group string) []string { + elem, err := wd.FindElement(selenium.ByTagName, "vt-status") + require.Nil(t, err) + elem, err = elem.FindElement(selenium.ByID, group) + require.Nil(t, err) + elems, err := elem.FindElements(selenium.ByTagName, "option") + require.Nil(t, err) + + var out []string + for _, elem = range elems { + out = append(out, text(t, elem)) + } + + return out +} + +// getDashboardKeyspaces fetches keyspaces from the dashboard. +func getDashboardKeyspaces(t *testing.T) []string { + wait(t, selenium.ByTagName, "vt-dashboard") + + dashboardContent, err := wd.FindElement(selenium.ByTagName, "vt-dashboard") + require.Nil(t, err) + + ksCards, err := dashboardContent.FindElements(selenium.ByClassName, "vt-keyspace-card") + var out []string + for _, ks := range ksCards { + out = append(out, text(t, ks)) + } + return out +} + +// getDashboardShards fetches shards from the dashboard. +func getDashboardShards(t *testing.T) []string { + wait(t, selenium.ByTagName, "vt-dashboard") + + dashboardContent, err := wd.FindElement(selenium.ByTagName, "vt-dashboard") + require.Nil(t, err) + + ksCards, err := dashboardContent.FindElements(selenium.ByClassName, "vt-shard-stats") + var out []string + for _, ks := range ksCards { + out = append(out, text(t, ks)) + } + return out +} + +func getKeyspaceShard(t *testing.T) []string { + wait(t, selenium.ByTagName, "vt-keyspace-view") + + ksContent, err := wd.FindElement(selenium.ByTagName, "vt-keyspace-view") + require.Nil(t, err) + + shards, err := ksContent.FindElements(selenium.ByClassName, "vt-serving-shard") + require.Nil(t, err) + var out []string + for _, s := range shards { + out = append(out, text(t, s)) + } + return out +} + +// getShardTablets gives list of tablet type and uid. +func getShardTablets(t *testing.T) ([]string, []string) { + wait(t, selenium.ByTagName, "vt-shard-view") + shardContent, err := wd.FindElement(selenium.ByTagName, "vt-shard-view") + require.Nil(t, err) + + tableRows, err := shardContent.FindElements(selenium.ByTagName, "tr") + tableRows = tableRows[1:] + + var tabletTypes, tabletUIDs []string + for _, row := range tableRows { + columns, err := row.FindElements(selenium.ByTagName, "td") + require.Nil(t, err) + + typ, err := columns[1].FindElement(selenium.ByClassName, "ui-cell-data") + require.Nil(t, err) + + typTxt := text(t, typ) + + tabletTypes = append(tabletTypes, typTxt) + + uid, err := columns[3].FindElement(selenium.ByClassName, "ui-cell-data") + require.Nil(t, err) + + uidTxt := text(t, uid) + tabletUIDs = append(tabletUIDs, uidTxt) + } + + return tabletTypes, tabletUIDs +} + +// navigation functions +// navigateToDashBoard navigates chrome screen to dashboard of vitess. +func navigateToDashBoard(t *testing.T) { + err := wd.Get(vtctldAddr + "/app2") + require.Nil(t, err) + + wait(t, selenium.ByID, "test_keyspace") +} + +// navigateToKeyspaceView navigates chrome screen to first keyspace. +func navigateToKeyspaceView(t *testing.T) { + navigateToDashBoard(t) + dashboardContent, err := wd.FindElement(selenium.ByTagName, "vt-dashboard") + require.Nil(t, err) + ksCard, err := dashboardContent.FindElements(selenium.ByClassName, "vt-card") + require.Nil(t, err) + require.Equal(t, 2, len(ksCard)) + + shardStarts, err := ksCard[0].FindElement(selenium.ByTagName, "md-list") + require.Nil(t, err) + + click(t, shardStarts) + + wait(t, selenium.ByClassName, "vt-card") +} + +// navigateToShardView navigates chrome screen to the first shard of first keyspace. +func navigateToShardView(t *testing.T) { + navigateToKeyspaceView(t) + ksContent, err := wd.FindElement(selenium.ByTagName, "vt-keyspace-view") + require.Nil(t, err) + + shardCards, err := ksContent.FindElements(selenium.ByClassName, "vt-serving-shard") + require.Nil(t, err) + require.Equal(t, 2, len(shardCards)) + + click(t, shardCards[0]) + + wait(t, selenium.ByID, "1") +} + +// other utility +// wait waits for the given element to be discoverable. +func wait(t *testing.T, by, val string) { + err := wd.WaitWithTimeout(func(xwd selenium.WebDriver) (bool, error) { + _, err := xwd.FindElement(by, val) + return err == nil, nil + }, selenium.DefaultWaitTimeout) + require.Nil(t, err) +} + +// assertDialogCommand validates the command in dialog. +func assertDialogCommand(t *testing.T, dialog selenium.WebElement, cmds []string) { + elms, err := dialog.FindElements(selenium.ByClassName, "vt-sheet") + require.Nil(t, err) + + var tmpCmd []string + for _, elm := range elms { + tmpCmd = append(tmpCmd, text(t, elm)) + } + + assert.ElementsMatch(t, cmds, tmpCmd) +} + +func text(t *testing.T, elem selenium.WebElement) string { + for i := 0; i < 5; i++ { + opTxt, err := elem.Text() + require.Nil(t, err) + if opTxt != "" { + return opTxt + } + } + + return "" +} + +func click(t *testing.T, elem selenium.WebElement) { + require.Nil(t, elem.Click()) +} + +// ss takes screenshot of chrome, for debugging only. +func ss(t *testing.T, name string) { + b, err := wd.Screenshot() + require.Nil(t, err) + f, err := os.Create("./" + name) + require.Nil(t, err) + _, err = f.Write(b) + require.Nil(t, err) +} + +func getPort() int { + return 20000 + rand.Intn(10000) +} diff --git a/go/test/endtoend/vtctldweb/vtctld_web_test.go b/go/test/endtoend/vtctldweb/vtctld_web_test.go new file mode 100644 index 00000000000..29f8f7229ff --- /dev/null +++ b/go/test/endtoend/vtctldweb/vtctld_web_test.go @@ -0,0 +1,230 @@ +/* +Copyright 2020 The Vitess Authors. + +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. +*/ + +package vtctldweb + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/tebeka/selenium" + "vitess.io/vitess/go/test/endtoend/cluster" +) + +// TestRealtimeStats checks the status by changing dropdown values. +func TestRealtimeStats(t *testing.T) { + defer cluster.PanicHandler(t) + err := wd.Get(vtctldAddr + "/app2") + require.Nil(t, err) + + statusBtn, err := wd.FindElement(selenium.ByPartialLinkText, "Status") + require.Nil(t, err) + + click(t, statusBtn) + + wait(t, selenium.ByTagName, "vt-status") + + testCases := [8][5]string{ + {"", "", "all", "all", "all"}, + {"type", "REPLICA", "all", "all", "REPLICA"}, + {"cell", "test2", "all", "test2", "REPLICA"}, + {"keyspace", "test_keyspace", "test_keyspace", "test2", "REPLICA"}, + {"cell", "all", "test_keyspace", "all", "REPLICA"}, + {"type", "all", "test_keyspace", "all", "all"}, + {"cell", "test2", "test_keyspace", "test2", "all"}, + {"keyspace", "all", "all", "test2", "all"}, + } + for _, k := range testCases { + if k[0] != "" && k[1] != "" { + changeDropdownOptions(t, k[0], k[1]) + } + + tabletOption := []string{"all", "MASTER", "REPLICA", "RDONLY"} + if k[3] == "test2" { + tabletOption = []string{"all", "REPLICA", "RDONLY"} + } + + checkNewView(t, []string{"all", ks1, ks2}, []string{"all", "test", "test2"}, tabletOption, []string{"lag", "qps", "health"}, k[2], k[3], k[4], "health") + } +} + +// TestShardView validates tablet type and uids. +func TestShardView(t *testing.T) { + defer cluster.PanicHandler(t) + navigateToShardView(t) + + tabletTypes, tabletUIDs := getShardTablets(t) + + assert.ElementsMatch(t, []string{"master", "replica", "rdonly", "rdonly", "replica", "replica", "rdonly", "rdonly"}, tabletTypes) + assert.ElementsMatch(t, []string{"1", "2", "3", "4", "5", "6", "7", "8"}, tabletUIDs) +} + +// TestKsView validates the shard names for keyspace. +func TestKsView(t *testing.T) { + defer cluster.PanicHandler(t) + navigateToKeyspaceView(t) + shards := getKeyspaceShard(t) + assert.ElementsMatch(t, []string{"-80", "80-"}, shards) +} + +// TestCreateKs validates the keyspace creation using ui. +func TestCreateKs(t *testing.T) { + defer cluster.PanicHandler(t) + navigateToDashBoard(t) + + dashboardContent, err := wd.FindElement(selenium.ByTagName, "vt-dashboard") + require.Nil(t, err) + + dialog, err := dashboardContent.FindElement(selenium.ByTagName, "vt-dialog") + require.Nil(t, err) + + dashboardMenu, err := dashboardContent.FindElement(selenium.ByClassName, "vt-menu") + require.Nil(t, err) + + click(t, dashboardMenu) + + dashboardOptions, err := dashboardContent.FindElements(selenium.ByClassName, "ui-menuitem-text") + require.Nil(t, err) + + for _, v := range dashboardOptions { + if text(t, v) == "New" { + click(t, v) + break + } + } + + inputFields, err := dialog.FindElements(selenium.ByTagName, "md-input") + require.Nil(t, err) + + for i, input := range inputFields { + ele, err := input.FindElement(selenium.ByTagName, "input") + require.Nil(t, err) + switch i { + case 0: + err := ele.SendKeys("test_keyspace3") + require.Nil(t, err) + assertDialogCommand(t, dialog, []string{"CreateKeyspace", "-force=false", "test_keyspace3"}) + + case 1: + err := ele.SendKeys("test_id") + require.Nil(t, err) + assertDialogCommand(t, dialog, []string{"CreateKeyspace", "-sharding_column_name=test_id", "-sharding_column_type=UINT64", "-force=false", "test_keyspace3"}) + } + } + + dropdown, err := dialog.FindElement(selenium.ByTagName, "p-dropdown") + require.Nil(t, err) + + click(t, dropdown) + + options, err := dropdown.FindElements(selenium.ByTagName, "li") + require.Nil(t, err) + + click(t, options[1]) + + assertDialogCommand(t, dialog, []string{"CreateKeyspace", "-sharding_column_name=test_id", "-sharding_column_type=BYTES", "-force=false", "test_keyspace3"}) + + create, err := dialog.FindElement(selenium.ByID, "vt-action") + require.Nil(t, err) + click(t, create) + + dismiss, err := dialog.FindElement(selenium.ByID, "vt-dismiss") + require.Nil(t, err) + click(t, dismiss) + + ksNames := getDashboardKeyspaces(t) + assert.ElementsMatch(t, []string{"test_keyspace", "test_keyspace2", "test_keyspace3"}, ksNames) + + testKs, err := dashboardContent.FindElements(selenium.ByClassName, "vt-card") + require.Nil(t, err) + menu, err := testKs[2].FindElement(selenium.ByClassName, "vt-menu") + require.Nil(t, err) + click(t, menu) + + options, err = testKs[2].FindElements(selenium.ByTagName, "li") + require.Nil(t, err) + for _, v := range options { + if text(t, v) == "Delete" { + click(t, v) + break + } + } + + delete, err := dialog.FindElement(selenium.ByID, "vt-action") + require.Nil(t, err) + click(t, delete) + + dismiss, err = dialog.FindElement(selenium.ByID, "vt-dismiss") + require.Nil(t, err) + click(t, dismiss) + + ksNames = getDashboardKeyspaces(t) + assert.ElementsMatch(t, []string{"test_keyspace", "test_keyspace2"}, ksNames) +} + +// TestDashboard validate the keyspaces and shard in dashboard. +func TestDashboard(t *testing.T) { + defer cluster.PanicHandler(t) + navigateToDashBoard(t) + ksNames := getDashboardKeyspaces(t) + assert.ElementsMatch(t, []string{"test_keyspace", "test_keyspace2"}, ksNames) + shardNames := getDashboardShards(t) + assert.ElementsMatch(t, []string{"2 Shards", "1 Shards"}, shardNames) +} + +// TestDashboardValidate validates the validate command from the ui. +func TestDashboardValidate(t *testing.T) { + defer cluster.PanicHandler(t) + navigateToDashBoard(t) + dashboardContent, err := wd.FindElement(selenium.ByTagName, "vt-dashboard") + require.Nil(t, err) + + menu, err := dashboardContent.FindElement(selenium.ByClassName, "vt-menu") + require.Nil(t, err) + click(t, menu) + + firstOption, err := dashboardContent.FindElement(selenium.ByClassName, "ui-menuitem-text") + require.Nil(t, err) + assert.Equal(t, "Validate", text(t, firstOption)) + + click(t, firstOption) + + dialog, err := dashboardContent.FindElement(selenium.ByTagName, "vt-dialog") + require.Nil(t, err) + + assertDialogCommand(t, dialog, []string{"Validate", "-ping-tablets=false"}) + + checkBoxes, err := dialog.FindElements(selenium.ByClassName, "md-checkbox-inner-container") + require.Nil(t, err) + + click(t, checkBoxes[0]) + + assertDialogCommand(t, dialog, []string{"Validate", "-ping-tablets"}) + + validate, err := dialog.FindElement(selenium.ByID, "vt-action") + require.Nil(t, err) + click(t, validate) + validateResp, err := dialog.FindElement(selenium.ByClassName, "vt-resp") + require.Nil(t, err) + + fmt.Printf("Validate command response: %s\n", text(t, validateResp)) + + dismiss, err := dialog.FindElement(selenium.ByID, "vt-dismiss") + require.Nil(t, err) + click(t, dismiss) +} diff --git a/go/test/endtoend/vtgate/aggr_test.go b/go/test/endtoend/vtgate/aggr_test.go index e23e4a8970e..f7035f7da09 100644 --- a/go/test/endtoend/vtgate/aggr_test.go +++ b/go/test/endtoend/vtgate/aggr_test.go @@ -21,15 +21,17 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/test/endtoend/cluster" ) func TestAggregateTypes(t *testing.T) { + defer cluster.PanicHandler(t) ctx := context.Background() conn, err := mysql.Connect(ctx, &vtParams) - if err != nil { - t.Fatal(err) - } + require.Nil(t, err) defer conn.Close() exec(t, conn, "insert into aggr_test(id, val1, val2) values(1,'a',1), (2,'A',1), (3,'b',1), (4,'c',3), (5,'c',4)") diff --git a/go/test/endtoend/vtgate/buffer/buffer_test.go b/go/test/endtoend/vtgate/buffer/buffer_test.go new file mode 100644 index 00000000000..532822fe47d --- /dev/null +++ b/go/test/endtoend/vtgate/buffer/buffer_test.go @@ -0,0 +1,418 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +/* +Test the vtgate master buffer. + +During a master failover, vtgate should automatically buffer (stall) requests +for a configured time and retry them after the failover is over. + +The test reproduces such a scenario as follows: +- run two threads, the first thread continuously executes a critical read and the second executes a write (UPDATE) +- vtctl PlannedReparentShard runs a master failover +- both threads should not see any error during the failover +*/ + +package buffer + +import ( + "context" + "encoding/json" + "fmt" + "io/ioutil" + "math/rand" + "net/http" + "os" + "reflect" + "strconv" + "strings" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/test/endtoend/cluster" +) + +var ( + clusterInstance *cluster.LocalProcessCluster + vtParams mysql.ConnParams + keyspaceUnshardedName = "ks1" + cell = "zone1" + hostname = "localhost" + sqlSchema = ` + create table buffer( + id BIGINT NOT NULL, + msg VARCHAR(64) NOT NULL, + PRIMARY KEY (id) + ) Engine=InnoDB;` + wg = &sync.WaitGroup{} +) + +const ( + criticalReadRowID = 1 + updateRowID = 2 + demoteMasterQuery = "SET GLOBAL read_only = ON;FLUSH TABLES WITH READ LOCK;UNLOCK TABLES;" + disableSemiSyncMasterQuery = "SET GLOBAL rpl_semi_sync_master_enabled = 0" + enableSemiSyncMasterQuery = "SET GLOBAL rpl_semi_sync_master_enabled = 1" + promoteSlaveQuery = "STOP SLAVE;RESET SLAVE ALL;SET GLOBAL read_only = OFF;" +) + +//threadParams is set of params passed into read and write threads +type threadParams struct { + writable bool + quit bool + rpcs int // Number of queries successfully executed. + errors int // Number of failed queries. + waitForNotification chan bool // Channel used to notify the main thread that this thread executed + notifyLock sync.Mutex // notifyLock guards the two fields notifyAfterNSuccessfulRpcs/rpcsSoFar. + notifyAfterNSuccessfulRpcs int // If 0, notifications are disabled + rpcsSoFar int // Number of RPCs at the time a notification was requested + i int // + commitErrors int + executeFunction func(c *threadParams, conn *mysql.Conn) error // Implement the method for read/update. +} + +// Thread which constantly executes a query on vtgate. +func (c *threadParams) threadRun() { + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + if err != nil { + println(err.Error()) + } + defer conn.Close() + for !c.quit { + err = c.executeFunction(c, conn) + if err != nil { + c.errors++ + println(err.Error()) + } + c.rpcs++ + // If notifications are requested, check if we already executed the + // required number of successful RPCs. + // Use >= instead of == because we can miss the exact point due to + // slow thread scheduling. + c.notifyLock.Lock() + if c.notifyAfterNSuccessfulRpcs != 0 && c.rpcs >= (c.notifyAfterNSuccessfulRpcs+c.rpcsSoFar) { + c.waitForNotification <- true + c.notifyAfterNSuccessfulRpcs = 0 + } + c.notifyLock.Unlock() + // Wait 10ms seconds between two attempts. + time.Sleep(10 * time.Millisecond) + } + wg.Done() +} + +func (c *threadParams) setNotifyAfterNSuccessfulRpcs(n int) { + c.notifyLock.Lock() + c.notifyAfterNSuccessfulRpcs = n + c.rpcsSoFar = c.rpcs + c.notifyLock.Unlock() +} + +func (c *threadParams) stop() { + c.quit = true +} + +func readExecute(c *threadParams, conn *mysql.Conn) error { + _, err := conn.ExecuteFetch(fmt.Sprintf("SELECT * FROM buffer WHERE id = %d", criticalReadRowID), 1000, true) + return err +} + +func updateExecute(c *threadParams, conn *mysql.Conn) error { + attempts := c.i + // Value used in next UPDATE query. Increased after every query. + c.i++ + conn.ExecuteFetch("begin", 1000, true) + + _, err := conn.ExecuteFetch(fmt.Sprintf("UPDATE buffer SET msg='update %d' WHERE id = %d", attempts, updateRowID), 1000, true) + + // Sleep between [0, 1] seconds to prolong the time the transaction is in + // flight. This is more realistic because applications are going to keep + // their transactions open for longer as well. + time.Sleep(time.Duration(rand.Int31n(1000)) * time.Millisecond) + + if err == nil { + fmt.Printf("update %d affected", attempts) + _, err = conn.ExecuteFetch("commit", 1000, true) + if err != nil { + _, errRollback := conn.ExecuteFetch("rollback", 1000, true) + if errRollback != nil { + fmt.Print("Error in rollback", errRollback.Error()) + } + c.commitErrors++ + if c.commitErrors > 1 { + return err + } + fmt.Printf("UPDATE %d failed during ROLLBACK. This is okay once because we do not support buffering it. err: %s", attempts, err.Error()) + } + } + if err != nil { + _, errRollback := conn.ExecuteFetch("rollback", 1000, true) + if errRollback != nil { + fmt.Print("Error in rollback", errRollback.Error()) + } + c.commitErrors++ + if c.commitErrors > 1 { + return err + } + fmt.Printf("UPDATE %d failed during COMMIT with err: %s.This is okay once because we do not support buffering it.", attempts, err.Error()) + } + return nil +} + +func createCluster() (*cluster.LocalProcessCluster, int) { + clusterInstance = cluster.NewCluster(cell, hostname) + + // Start topo server + if err := clusterInstance.StartTopo(); err != nil { + return nil, 1 + } + + // Start keyspace + keyspace := &cluster.Keyspace{ + Name: keyspaceUnshardedName, + SchemaSQL: sqlSchema, + } + if err := clusterInstance.StartUnshardedKeyspace(*keyspace, 1, false); err != nil { + return nil, 1 + } + + clusterInstance.VtGateExtraArgs = []string{ + "-enable_buffer", + // Long timeout in case failover is slow. + "-buffer_window", "10m", + "-buffer_max_failover_duration", "10m", + "-buffer_min_time_between_failovers", "20m"} + + // Start vtgate + if err := clusterInstance.StartVtgate(); err != nil { + return nil, 1 + } + vtParams = mysql.ConnParams{ + Host: clusterInstance.Hostname, + Port: clusterInstance.VtgateMySQLPort, + } + rand.Seed(time.Now().UnixNano()) + return clusterInstance, 0 +} + +func exec(t *testing.T, conn *mysql.Conn, query string) *sqltypes.Result { + t.Helper() + qr, err := conn.ExecuteFetch(query, 1000, true) + require.Nil(t, err) + return qr +} + +func TestBufferInternalReparenting(t *testing.T) { + testBufferBase(t, false) +} + +func TestBufferExternalReparenting(t *testing.T) { + testBufferBase(t, true) +} + +func testBufferBase(t *testing.T, isExternalParent bool) { + defer cluster.PanicHandler(t) + clusterInstance, exitCode := createCluster() + if exitCode != 0 { + os.Exit(exitCode) + } + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + require.Nil(t, err) + defer conn.Close() + + // Insert two rows for the later threads (critical read, update). + exec(t, conn, fmt.Sprintf("INSERT INTO buffer (id, msg) VALUES (%d, %s)", criticalReadRowID, "'critical read'")) + exec(t, conn, fmt.Sprintf("INSERT INTO buffer (id, msg) VALUES (%d, %s)", updateRowID, "'update'")) + + //Start both threads. + readThreadInstance := &threadParams{writable: false, quit: false, rpcs: 0, errors: 0, notifyAfterNSuccessfulRpcs: 0, rpcsSoFar: 0, executeFunction: readExecute, waitForNotification: make(chan bool)} + wg.Add(1) + go readThreadInstance.threadRun() + updateThreadInstance := &threadParams{writable: false, quit: false, rpcs: 0, errors: 0, notifyAfterNSuccessfulRpcs: 0, rpcsSoFar: 0, executeFunction: updateExecute, i: 1, commitErrors: 0, waitForNotification: make(chan bool)} + wg.Add(1) + go updateThreadInstance.threadRun() + + // Verify they got at least 2 RPCs through. + readThreadInstance.setNotifyAfterNSuccessfulRpcs(2) + updateThreadInstance.setNotifyAfterNSuccessfulRpcs(2) + + <-readThreadInstance.waitForNotification + <-updateThreadInstance.waitForNotification + + // Execute the failover. + readThreadInstance.setNotifyAfterNSuccessfulRpcs(10) + updateThreadInstance.setNotifyAfterNSuccessfulRpcs(10) + + if isExternalParent { + externalReparenting(ctx, t, clusterInstance) + } else { + //reparent call + clusterInstance.VtctlclientProcess.ExecuteCommand("PlannedReparentShard", "-keyspace_shard", + fmt.Sprintf("%s/%s", keyspaceUnshardedName, "0"), + "-new_master", clusterInstance.Keyspaces[0].Shards[0].Vttablets[1].Alias) + } + + <-readThreadInstance.waitForNotification + <-updateThreadInstance.waitForNotification + + // Stop threads + readThreadInstance.stop() + updateThreadInstance.stop() + + // Both threads must not see any error + assert.Equal(t, 0, readThreadInstance.errors) + assert.Equal(t, 0, updateThreadInstance.errors) + + //At least one thread should have been buffered. + //This may fail if a failover is too fast. Add retries then. + resp, err := http.Get(clusterInstance.VtgateProcess.VerifyURL) + require.Nil(t, err) + label := fmt.Sprintf("%s.%s", keyspaceUnshardedName, "0") + inFlightMax := 0 + masterPromotedCount := 0 + durationMs := 0 + bufferingStops := 0 + if resp.StatusCode == 200 { + resultMap := make(map[string]interface{}) + respByte, _ := ioutil.ReadAll(resp.Body) + err := json.Unmarshal(respByte, &resultMap) + if err != nil { + panic(err) + } + inFlightMax = getVarFromVtgate(t, label, "BufferLastRequestsInFlightMax", resultMap) + masterPromotedCount = getVarFromVtgate(t, label, "HealthcheckMasterPromoted", resultMap) + durationMs = getVarFromVtgate(t, label, "BufferFailoverDurationSumMs", resultMap) + bufferingStops = getVarFromVtgate(t, "NewMasterSeen", "BufferStops", resultMap) + } + if inFlightMax == 0 { + // Missed buffering is okay when we observed the failover during the + // COMMIT (which cannot trigger the buffering). + assert.Greater(t, updateThreadInstance.commitErrors, 0, "No buffering took place and the update thread saw no error during COMMIT. But one of it must happen.") + } else { + assert.Greater(t, inFlightMax, 0) + } + + // There was a failover and the HealthCheck module must have seen it. + if masterPromotedCount > 0 { + assert.Greater(t, masterPromotedCount, 0) + } + + if durationMs > 0 { + // Number of buffering stops must be equal to the number of seen failovers. + assert.Equal(t, masterPromotedCount, bufferingStops) + } + wg.Wait() + clusterInstance.Teardown() +} + +func getVarFromVtgate(t *testing.T, label string, param string, resultMap map[string]interface{}) int { + paramVal := 0 + var err error + object := reflect.ValueOf(resultMap[param]) + if object.Kind() == reflect.Map { + for _, key := range object.MapKeys() { + if strings.Contains(key.String(), label) { + v := object.MapIndex(key) + s := fmt.Sprintf("%v", v.Interface()) + paramVal, err = strconv.Atoi(s) + require.Nil(t, err) + } + } + } + return paramVal +} + +func externalReparenting(ctx context.Context, t *testing.T, clusterInstance *cluster.LocalProcessCluster) { + start := time.Now() + + // Demote master Query + master := clusterInstance.Keyspaces[0].Shards[0].Vttablets[0] + replica := clusterInstance.Keyspaces[0].Shards[0].Vttablets[1] + oldMaster := master + newMaster := replica + master.VttabletProcess.QueryTablet(demoteMasterQuery, keyspaceUnshardedName, true) + if master.VttabletProcess.EnableSemiSync { + master.VttabletProcess.QueryTablet(disableSemiSyncMasterQuery, keyspaceUnshardedName, true) + } + + // Wait for replica to catch up to master. + cluster.WaitForReplicationPos(t, master, replica, "localhost", 60.0) + + duration := time.Since(start) + minUnavailabilityInS := 1.0 + if duration.Seconds() < minUnavailabilityInS { + w := minUnavailabilityInS - duration.Seconds() + fmt.Printf("Waiting for %.1f seconds because the failover was too fast (took only %.3f seconds)", w, duration.Seconds()) + time.Sleep(time.Duration(w) * time.Second) + } + + // Promote replica to new master. + replica.VttabletProcess.QueryTablet(promoteSlaveQuery, keyspaceUnshardedName, true) + + if replica.VttabletProcess.EnableSemiSync { + replica.VttabletProcess.QueryTablet(enableSemiSyncMasterQuery, keyspaceUnshardedName, true) + } + + // Configure old master to replicate from new master. + + _, gtID := cluster.GetMasterPosition(t, *newMaster, hostname) + + // Use 'localhost' as hostname because Travis CI worker hostnames + // are too long for MySQL replication. + changeMasterCommands := fmt.Sprintf("RESET SLAVE;SET GLOBAL gtid_slave_pos = '%s';CHANGE MASTER TO MASTER_HOST='%s', MASTER_PORT=%d ,MASTER_USER='vt_repl', MASTER_USE_GTID = slave_pos;START SLAVE;", gtID, "localhost", newMaster.MySQLPort) + oldMaster.VttabletProcess.QueryTablet(changeMasterCommands, keyspaceUnshardedName, true) + + // Notify the new vttablet master about the reparent. + clusterInstance.VtctlclientProcess.ExecuteCommand("TabletExternallyReparented", newMaster.Alias) +} + +func waitForReplicationPos(ctx context.Context, t *testing.T, tabletA *cluster.Vttablet, tabletB *cluster.Vttablet, timeout float64) { + replicationPosA, _ := cluster.GetMasterPosition(t, *tabletA, hostname) + for { + replicationPosB, _ := cluster.GetMasterPosition(t, *tabletB, hostname) + if positionAtLeast(t, tabletA, replicationPosB, replicationPosA) { + break + } + msg := fmt.Sprintf("%s's replication position to catch up to %s's;currently at: %s, waiting to catch up to: %s", tabletB.Alias, tabletA.Alias, replicationPosB, replicationPosA) + waitStep(t, msg, timeout, 0.01) + } +} + +func positionAtLeast(t *testing.T, tablet *cluster.Vttablet, a string, b string) bool { + isAtleast := false + val, err := tablet.MysqlctlProcess.ExecuteCommandWithOutput("position", "at_least", a, b) + require.Nil(t, err) + if strings.Contains(val, "true") { + isAtleast = true + } + return isAtleast +} + +func waitStep(t *testing.T, msg string, timeout float64, sleepTime float64) float64 { + timeout = timeout - sleepTime + if timeout < 0.0 { + t.Errorf("timeout waiting for condition '%s'", msg) + } + time.Sleep(time.Duration(sleepTime) * time.Second) + return timeout +} diff --git a/go/test/endtoend/vtgate/lookup_test.go b/go/test/endtoend/vtgate/lookup_test.go index 126b2593609..65c174bf8f1 100644 --- a/go/test/endtoend/vtgate/lookup_test.go +++ b/go/test/endtoend/vtgate/lookup_test.go @@ -22,22 +22,22 @@ import ( "strings" "testing" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/test/endtoend/cluster" ) func TestConsistentLookup(t *testing.T) { + defer cluster.PanicHandler(t) ctx := context.Background() conn, err := mysql.Connect(ctx, &vtParams) - if err != nil { - t.Fatal(err) - } + require.Nil(t, err) defer conn.Close() // conn2 is for queries that target shards. conn2, err := mysql.Connect(ctx, &vtParams) - if err != nil { - t.Fatal(err) - } + require.Nil(t, err) defer conn2.Close() // Simple insert. @@ -163,18 +163,105 @@ func TestConsistentLookup(t *testing.T) { exec(t, conn, "delete from t1 where id1=1") } -func TestConsistentLookupMultiInsert(t *testing.T) { +func TestDMLScatter(t *testing.T) { ctx := context.Background() conn, err := mysql.Connect(ctx, &vtParams) - if err != nil { - t.Fatal(err) + require.NoError(t, err) + defer conn.Close() + + /* Simple insert. after this dml, the tables will contain the following: + t3 (id5, id6, id7): + 1 2 3 + 2 2 3 + 3 4 3 + 4 5 4 + + t3_id7_idx (id7, keyspace_id:id6): + 3 2 + 3 2 + 3 4 + 4 5 + */ + exec(t, conn, "begin") + exec(t, conn, "insert into t3(id5, id6, id7) values(1, 2, 3), (2, 2, 3), (3, 4, 3), (4, 5, 4)") + exec(t, conn, "commit") + qr := exec(t, conn, "select id5, id6, id7 from t3 order by id5") + if got, want := fmt.Sprintf("%v", qr.Rows), "[[INT64(1) INT64(2) INT64(3)] [INT64(2) INT64(2) INT64(3)] [INT64(3) INT64(4) INT64(3)] [INT64(4) INT64(5) INT64(4)]]"; got != want { + t.Errorf("select:\n%v want\n%v", got, want) + } + + /* Updating a non lookup column. after this dml, the tables will contain the following: + t3 (id5, id6, id7): + 42 2 3 + 2 2 3 + 3 4 3 + 4 5 4 + + t3_id7_idx (id7, keyspace_id:id6): + 3 2 + 3 2 + 3 4 + 4 5 + */ + exec(t, conn, "update t3 set id5 = 42 where id5 = 1") + qr = exec(t, conn, "select id5, id6, id7 from t3 order by id5") + if got, want := fmt.Sprintf("%v", qr.Rows), "[[INT64(2) INT64(2) INT64(3)] [INT64(3) INT64(4) INT64(3)] [INT64(4) INT64(5) INT64(4)] [INT64(42) INT64(2) INT64(3)]]"; got != want { + t.Errorf("select:\n%v want\n%v", got, want) + } + + /* Updating a lookup column. after this dml, the tables will contain the following: + t3 (id5, id6, id7): + 42 2 42 + 2 2 42 + 3 4 3 + 4 5 4 + + t3_id7_idx (id7, keyspace_id:id6): + 42 2 + 42 2 + 3 4 + 4 5 + */ + exec(t, conn, "begin") + exec(t, conn, "update t3 set id7 = 42 where id6 = 2") + exec(t, conn, "commit") + qr = exec(t, conn, "select id5, id6, id7 from t3 order by id5") + if got, want := fmt.Sprintf("%v", qr.Rows), "[[INT64(2) INT64(2) INT64(42)] [INT64(3) INT64(4) INT64(3)] [INT64(4) INT64(5) INT64(4)] [INT64(42) INT64(2) INT64(42)]]"; got != want { + t.Errorf("select:\n%v want\n%v", got, want) } + + /* delete one specific keyspace id. after this dml, the tables will contain the following: + t3 (id5, id6, id7): + 3 4 3 + 4 5 4 + + t3_id7_idx (id7, keyspace_id:id6): + 3 4 + 4 5 + */ + exec(t, conn, "delete from t3 where id6 = 2") + qr = exec(t, conn, "select * from t3 where id6 = 2") + require.Empty(t, qr.Rows) + qr = exec(t, conn, "select * from t3_id7_idx where id6 = 2") + require.Empty(t, qr.Rows) + + // delete all the rows. + exec(t, conn, "delete from t3") + qr = exec(t, conn, "select * from t3") + require.Empty(t, qr.Rows) + qr = exec(t, conn, "select * from t3_id7_idx") + require.Empty(t, qr.Rows) +} + +func TestConsistentLookupMultiInsert(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + require.Nil(t, err) defer conn.Close() // conn2 is for queries that target shards. conn2, err := mysql.Connect(ctx, &vtParams) - if err != nil { - t.Fatal(err) - } + require.Nil(t, err) defer conn2.Close() exec(t, conn, "begin") @@ -221,17 +308,14 @@ func TestConsistentLookupMultiInsert(t *testing.T) { } func TestHashLookupMultiInsertIgnore(t *testing.T) { + defer cluster.PanicHandler(t) ctx := context.Background() conn, err := mysql.Connect(ctx, &vtParams) - if err != nil { - t.Fatal(err) - } + require.Nil(t, err) defer conn.Close() // conn2 is for queries that target shards. conn2, err := mysql.Connect(ctx, &vtParams) - if err != nil { - t.Fatal(err) - } + require.Nil(t, err) defer conn2.Close() // DB should start out clean @@ -260,11 +344,78 @@ func TestHashLookupMultiInsertIgnore(t *testing.T) { } } +func TestConsistentLookupUpdate(t *testing.T) { + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + require.NoError(t, err) + defer conn.Close() + + /* Simple insert. after this dml, the tables will contain the following: + t4 (id1, id2): + 1 2 + 2 2 + 3 3 + 4 3 + + t4_id2_idx (id2, id1, keyspace_id:id1): + 2 1 1 + 2 2 2 + 3 3 3 + 3 4 4 + */ + exec(t, conn, "insert into t4(id1, id2) values(1, '2'), (2, '2'), (3, '3'), (4, '3')") + qr := exec(t, conn, "select id1, id2 from t4 order by id1") + if got, want := fmt.Sprintf("%v", qr.Rows), `[[INT64(1) VARCHAR("2")] [INT64(2) VARCHAR("2")] [INT64(3) VARCHAR("3")] [INT64(4) VARCHAR("3")]]`; got != want { + t.Errorf("select:\n%v want\n%v", got, want) + } + + /* Updating a lookup column. after this dml, the tables will contain the following: + t4 (id1, id2): + 1 42 + 2 2 + 3 3 + 4 3 + + t4_id2_idx (id2, id1, keyspace_id:id1): + 42 1 1 + 2 2 2 + 3 3 3 + 3 4 4 + */ + exec(t, conn, "update t4 set id2 = '42' where id1 = 1") + qr = exec(t, conn, "select id1, id2 from t4 order by id1") + if got, want := fmt.Sprintf("%v", qr.Rows), `[[INT64(1) VARCHAR("42")] [INT64(2) VARCHAR("2")] [INT64(3) VARCHAR("3")] [INT64(4) VARCHAR("3")]]`; got != want { + t.Errorf("select:\n%v want\n%v", got, want) + } + + /* delete one specific keyspace id. after this dml, the tables will contain the following: + t4 (id1, id2): + 2 2 + 3 3 + 4 3 + + t4_id2_idx (id2, id1, keyspace_id:id1): + 2 2 2 + 3 3 3 + 3 4 4 + */ + exec(t, conn, "delete from t4 where id2 = '42'") + qr = exec(t, conn, "select * from t4 where id2 = '42'") + require.Empty(t, qr.Rows) + qr = exec(t, conn, "select * from t4_id2_idx where id2 = '42'") + require.Empty(t, qr.Rows) + + // delete all the rows. + exec(t, conn, "delete from t4") + qr = exec(t, conn, "select * from t4") + require.Empty(t, qr.Rows) + qr = exec(t, conn, "select * from t4_id2_idx") + require.Empty(t, qr.Rows) +} + func exec(t *testing.T, conn *mysql.Conn, query string) *sqltypes.Result { t.Helper() qr, err := conn.ExecuteFetch(query, 1000, true) - if err != nil { - t.Fatal(err) - } + require.Nil(t, err) return qr } diff --git a/go/test/endtoend/vtgate/main_test.go b/go/test/endtoend/vtgate/main_test.go index d707b0d511d..5ca001fb8a8 100644 --- a/go/test/endtoend/vtgate/main_test.go +++ b/go/test/endtoend/vtgate/main_test.go @@ -68,12 +68,41 @@ create table t2_id4_idx( primary key(id), key idx_id4(id4) ) Engine=InnoDB; -` + +create table t3( + id5 bigint, + id6 bigint, + id7 bigint, + primary key(id5) +) Engine=InnoDB; + +create table t3_id7_idx( + id bigint not null auto_increment, + id7 bigint, + id6 bigint, + primary key(id) +) Engine=InnoDB; + +create table t4( + id1 bigint, + id2 varchar(10), + primary key(id1) +) Engine=InnoDB; + +create table t4_id2_idx( + id2 varchar(10), + id1 bigint, + keyspace_id varbinary(50), + primary key(id2, id1) +) Engine=InnoDB;` VSchema = ` - { +{ "sharded": true, "vindexes": { + "unicode_loose_md5" : { + "type": "unicode_loose_md5" + }, "hash": { "type": "hash" }, @@ -95,6 +124,24 @@ create table t2_id4_idx( "autocommit": "true" }, "owner": "t2" + }, + "t3_id7_vdx": { + "type": "lookup_hash", + "params": { + "table": "t3_id7_idx", + "from": "id7", + "to": "id6" + }, + "owner": "t3" + }, + "t4_id2_vdx": { + "type": "consistent_lookup", + "params": { + "table": "t4_id2_idx", + "from": "id2,id1", + "to": "keyspace_id" + }, + "owner": "t4" } }, "tables": { @@ -138,6 +185,46 @@ create table t2_id4_idx( } ] }, + "t3": { + "column_vindexes": [ + { + "column": "id6", + "name": "hash" + }, + { + "column": "id7", + "name": "t3_id7_vdx" + } + ] + }, + "t3_id7_idx": { + "column_vindexes": [ + { + "column": "id7", + "name": "hash" + } + ] + }, + "t4": { + "column_vindexes": [ + { + "column": "id1", + "name": "hash" + }, + { + "columns": ["id2", "id1"], + "name": "t4_id2_vdx" + } + ] + }, + "t4_id2_idx": { + "column_vindexes": [ + { + "column": "id2", + "name": "unicode_loose_md5" + } + ] + }, "vstream_test": { "column_vindexes": [ { @@ -165,10 +252,11 @@ create table t2_id4_idx( ) func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) flag.Parse() exitCode := func() int { - clusterInstance = cluster.NewCluster(Cell, "localhost") + clusterInstance = cluster.NewCluster(Cell, "localhost") defer clusterInstance.Teardown() // Start topo server diff --git a/go/test/endtoend/vtgate/schema/schema_test.go b/go/test/endtoend/vtgate/schema/schema_test.go new file mode 100644 index 00000000000..0363bdcf8af --- /dev/null +++ b/go/test/endtoend/vtgate/schema/schema_test.go @@ -0,0 +1,299 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package schema + +import ( + "encoding/json" + "flag" + "fmt" + "io/ioutil" + "os" + "path" + "reflect" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/test/endtoend/cluster" +) + +var ( + clusterInstance *cluster.LocalProcessCluster + hostname = "localhost" + keyspaceName = "ks" + cell = "zone1" + schemaChangeDirectory = "" + totalTableCount = 4 + createTable = ` + CREATE TABLE %s ( + id BIGINT(20) not NULL, + msg varchar(64), + PRIMARY KEY (id) + ) ENGINE=InnoDB;` + alterTable = ` + ALTER TABLE %s + ADD COLUMN new_id bigint(20) NOT NULL AUTO_INCREMENT FIRST, + DROP PRIMARY KEY, + ADD PRIMARY KEY (new_id), + ADD INDEX idx_column(%s)` +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitcode, err := func() (int, error) { + clusterInstance = cluster.NewCluster(cell, hostname) + schemaChangeDirectory = path.Join("/tmp", fmt.Sprintf("schema_change_dir_%d", clusterInstance.GetAndReserveTabletUID())) + defer os.RemoveAll(schemaChangeDirectory) + defer clusterInstance.Teardown() + + if _, err := os.Stat(schemaChangeDirectory); os.IsNotExist(err) { + _ = os.Mkdir(schemaChangeDirectory, 0700) + } + + clusterInstance.VtctldExtraArgs = []string{ + "-schema_change_dir", schemaChangeDirectory, + "-schema_change_controller", "local", + "-schema_change_check_interval", "1"} + + if err := clusterInstance.StartTopo(); err != nil { + return 1, err + } + + // Start keyspace + keyspace := &cluster.Keyspace{ + Name: keyspaceName, + } + + if err := clusterInstance.StartUnshardedKeyspace(*keyspace, 2, true); err != nil { + return 1, err + } + if err := clusterInstance.StartKeyspace(*keyspace, []string{"1"}, 1, false); err != nil { + return 1, err + } + return m.Run(), nil + }() + if err != nil { + fmt.Printf("%v\n", err) + os.Exit(1) + } else { + os.Exit(exitcode) + } + +} + +func TestSchemaChange(t *testing.T) { + defer cluster.PanicHandler(t) + testWithInitialSchema(t) + testWithAlterSchema(t) + testWithAlterDatabase(t) + testWithDropCreateSchema(t) + testSchemaChangePreflightErrorPartially(t) + testDropNonExistentTables(t) + testCopySchemaShards(t, clusterInstance.Keyspaces[0].Shards[0].Vttablets[0].VttabletProcess.TabletPath, 2) + testCopySchemaShards(t, fmt.Sprintf("%s/0", keyspaceName), 3) + testCopySchemaShardWithDifferentDB(t, 4) + testWithAutoSchemaFromChangeDir(t) +} + +func testWithInitialSchema(t *testing.T) { + // Create 4 tables + var sqlQuery = "" + for i := 0; i < totalTableCount; i++ { + sqlQuery = fmt.Sprintf(createTable, fmt.Sprintf("vt_select_test_%02d", i)) + err := clusterInstance.VtctlclientProcess.ApplySchema(keyspaceName, sqlQuery) + require.Nil(t, err) + + } + + // Check if 4 tables are created + checkTables(t, totalTableCount) + checkTables(t, totalTableCount) + + // Also match the vschema for those tablets + matchSchema(t, clusterInstance.Keyspaces[0].Shards[0].Vttablets[0].VttabletProcess.TabletPath, clusterInstance.Keyspaces[0].Shards[1].Vttablets[0].VttabletProcess.TabletPath) +} + +// testWithAlterSchema if we alter schema and then apply, the resultant schema should match across shards +func testWithAlterSchema(t *testing.T) { + sqlQuery := fmt.Sprintf(alterTable, fmt.Sprintf("vt_select_test_%02d", 3), "msg") + err := clusterInstance.VtctlclientProcess.ApplySchema(keyspaceName, sqlQuery) + require.Nil(t, err) + matchSchema(t, clusterInstance.Keyspaces[0].Shards[0].Vttablets[0].VttabletProcess.TabletPath, clusterInstance.Keyspaces[0].Shards[1].Vttablets[0].VttabletProcess.TabletPath) +} + +// testWithAlterDatabase tests that ALTER DATABASE is accepted by the validator. +func testWithAlterDatabase(t *testing.T) { + sql := "create database alter_database_test; alter database alter_database_test default character set = utf8mb4; drop database alter_database_test" + err := clusterInstance.VtctlclientProcess.ApplySchema(keyspaceName, sql) + assert.Nil(t, err) +} + +// testWithDropCreateSchema , we should be able to drop and create same schema +//Tests that a DROP and CREATE table will pass PreflightSchema check. +// +//PreflightSchema checks each SQL statement separately. When doing so, it must +//consider previous statements within the same ApplySchema command. For +//example, a CREATE after DROP must not fail: When CREATE is checked, DROP +//must have been executed first. +//See: https://github.com/vitessio/vitess/issues/1731#issuecomment-222914389 +func testWithDropCreateSchema(t *testing.T) { + dropCreateTable := fmt.Sprintf("DROP TABLE vt_select_test_%02d ;", 2) + fmt.Sprintf(createTable, fmt.Sprintf("vt_select_test_%02d", 2)) + err := clusterInstance.VtctlclientProcess.ApplySchema(keyspaceName, dropCreateTable) + require.Nil(t, err) + checkTables(t, totalTableCount) +} + +// testWithAutoSchemaFromChangeDir on putting sql file to schema change directory, it should apply that sql to all shards +func testWithAutoSchemaFromChangeDir(t *testing.T) { + _ = os.Mkdir(path.Join(schemaChangeDirectory, keyspaceName), 0700) + _ = os.Mkdir(path.Join(schemaChangeDirectory, keyspaceName, "input"), 0700) + sqlFile := path.Join(schemaChangeDirectory, keyspaceName, "input/create_test_table_x.sql") + err := ioutil.WriteFile(sqlFile, []byte("create table test_table_x (id int)"), 0644) + require.Nil(t, err) + timeout := time.Now().Add(10 * time.Second) + matchFoundAfterAutoSchemaApply := false + for time.Now().Before(timeout) { + if _, err := os.Stat(sqlFile); os.IsNotExist(err) { + matchFoundAfterAutoSchemaApply = true + checkTables(t, totalTableCount+1) + matchSchema(t, clusterInstance.Keyspaces[0].Shards[0].Vttablets[0].VttabletProcess.TabletPath, clusterInstance.Keyspaces[0].Shards[1].Vttablets[0].VttabletProcess.TabletPath) + } + } + if !matchFoundAfterAutoSchemaApply { + assert.Fail(t, "Auto schema is not consumed") + } + defer os.RemoveAll(path.Join(schemaChangeDirectory, keyspaceName)) +} + +// matchSchema schema for supplied tablets should match +func matchSchema(t *testing.T, firstTablet string, secondTablet string) { + firstShardSchema, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("GetSchema", firstTablet) + require.Nil(t, err) + + secondShardSchema, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("GetSchema", secondTablet) + require.Nil(t, err) + + assert.Equal(t, firstShardSchema, secondShardSchema) +} + +// testSchemaChangePreflightErrorPartially applying same schema + new schema should throw error for existing one +// Tests that some SQL statements fail properly during PreflightSchema. +func testSchemaChangePreflightErrorPartially(t *testing.T) { + createNewTable := fmt.Sprintf(createTable, fmt.Sprintf("vt_select_test_%02d", 5)) + fmt.Sprintf(createTable, fmt.Sprintf("vt_select_test_%02d", 2)) + output, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("ApplySchema", "-sql", createNewTable, keyspaceName) + require.Error(t, err) + assert.True(t, strings.Contains(output, "already exists")) + + checkTables(t, totalTableCount) +} + +// testDropNonExistentTables applying same schema + new schema should throw error for existing one and also add the new schema +//If a table does not exist, DROP TABLE should error during preflight +//because the statement does not change the schema as there is +//nothing to drop. +//In case of DROP TABLE IF EXISTS though, it should not error as this +//is the MySQL behavior the user expects. +func testDropNonExistentTables(t *testing.T) { + dropNonExistentTable := "DROP TABLE nonexistent_table;" + output, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("ApplySchema", "-sql", dropNonExistentTable, keyspaceName) + require.Error(t, err) + assert.True(t, strings.Contains(output, "Unknown table")) + + dropIfExists := "DROP TABLE IF EXISTS nonexistent_table;" + err = clusterInstance.VtctlclientProcess.ApplySchema(keyspaceName, dropIfExists) + require.Nil(t, err) + + checkTables(t, totalTableCount) +} + +// checkTables checks the number of tables in the first two shards. +func checkTables(t *testing.T, count int) { + checkTablesCount(t, clusterInstance.Keyspaces[0].Shards[0].Vttablets[0], count) + checkTablesCount(t, clusterInstance.Keyspaces[0].Shards[1].Vttablets[0], count) +} + +// checkTablesCount checks the number of tables in the given tablet +func checkTablesCount(t *testing.T, tablet *cluster.Vttablet, count int) { + queryResult, err := tablet.VttabletProcess.QueryTablet("show tables;", keyspaceName, true) + require.Nil(t, err) + assert.Equal(t, len(queryResult.Rows), count) +} + +// testCopySchemaShards tests that schema from source is correctly applied to destination +func testCopySchemaShards(t *testing.T, source string, shard int) { + addNewShard(t, shard) + // InitShardMaster creates the db, but there shouldn't be any tables yet. + checkTablesCount(t, clusterInstance.Keyspaces[0].Shards[shard].Vttablets[0], 0) + checkTablesCount(t, clusterInstance.Keyspaces[0].Shards[shard].Vttablets[1], 0) + // Run the command twice to make sure it's idempotent. + for i := 0; i < 2; i++ { + err := clusterInstance.VtctlclientProcess.ExecuteCommand("CopySchemaShard", source, fmt.Sprintf("%s/%d", keyspaceName, shard)) + require.Nil(t, err) + } + // shard_2_master should look the same as the replica we copied from + checkTablesCount(t, clusterInstance.Keyspaces[0].Shards[shard].Vttablets[0], totalTableCount) + checkTablesCount(t, clusterInstance.Keyspaces[0].Shards[shard].Vttablets[1], totalTableCount) + + matchSchema(t, clusterInstance.Keyspaces[0].Shards[0].Vttablets[0].VttabletProcess.TabletPath, clusterInstance.Keyspaces[0].Shards[shard].Vttablets[0].VttabletProcess.TabletPath) +} + +// testCopySchemaShardWithDifferentDB if we apply different schema to new shard, it should throw error +func testCopySchemaShardWithDifferentDB(t *testing.T, shard int) { + addNewShard(t, shard) + checkTablesCount(t, clusterInstance.Keyspaces[0].Shards[shard].Vttablets[0], 0) + checkTablesCount(t, clusterInstance.Keyspaces[0].Shards[shard].Vttablets[1], 0) + source := fmt.Sprintf("%s/0", keyspaceName) + + masterTabletAlias := clusterInstance.Keyspaces[0].Shards[shard].Vttablets[0].VttabletProcess.TabletPath + schema, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("GetSchema", masterTabletAlias) + require.Nil(t, err) + + resultMap := make(map[string]interface{}) + err = json.Unmarshal([]byte(schema), &resultMap) + require.Nil(t, err) + dbSchema := reflect.ValueOf(resultMap["database_schema"]) + assert.True(t, strings.Contains(dbSchema.String(), "utf8")) + + // Change the db charset on the destination shard from utf8 to latin1. + // This will make CopySchemaShard fail during its final diff. + // (The different charset won't be corrected on the destination shard + // because we use "CREATE DATABASE IF NOT EXISTS" and this doesn't fail if + // there are differences in the options e.g. the character set.) + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ExecuteFetchAsDba", "-json", masterTabletAlias, "ALTER DATABASE vt_ks CHARACTER SET latin1") + require.Nil(t, err) + + output, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("CopySchemaShard", source, fmt.Sprintf("%s/%d", keyspaceName, shard)) + require.Error(t, err) + assert.True(t, strings.Contains(output, "schemas are different")) + + // shard_2_master should have the same number of tables. Only the db + // character set is different. + checkTablesCount(t, clusterInstance.Keyspaces[0].Shards[shard].Vttablets[0], totalTableCount) +} + +// addNewShard adds a new shard dynamically +func addNewShard(t *testing.T, shard int) { + keyspace := &cluster.Keyspace{ + Name: keyspaceName, + } + err := clusterInstance.StartKeyspace(*keyspace, []string{fmt.Sprintf("%d", shard)}, 1, false) + require.Nil(t, err) +} diff --git a/go/test/endtoend/vtgate/sequence/seq_test.go b/go/test/endtoend/vtgate/sequence/seq_test.go index 72ce77bea02..2dab1944fed 100644 --- a/go/test/endtoend/vtgate/sequence/seq_test.go +++ b/go/test/endtoend/vtgate/sequence/seq_test.go @@ -24,6 +24,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/test/endtoend/cluster" @@ -79,10 +81,11 @@ var ( ) func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) flag.Parse() exitCode := func() int { - clusterInstance = cluster.NewCluster(cell, hostname) + clusterInstance = cluster.NewCluster(cell, hostname) defer clusterInstance.Teardown() // Start topo server @@ -113,22 +116,19 @@ func TestMain(m *testing.M) { func exec(t *testing.T, conn *mysql.Conn, query string) *sqltypes.Result { t.Helper() qr, err := conn.ExecuteFetch(query, 1000, true) - if err != nil { - t.Fatal(err) - } + require.Nil(t, err) return qr } func TestSeq(t *testing.T) { + defer cluster.PanicHandler(t) ctx := context.Background() vtParams := mysql.ConnParams{ Host: "localhost", Port: clusterInstance.VtgateMySQLPort, } conn, err := mysql.Connect(ctx, &vtParams) - if err != nil { - t.Fatal(err) - } + require.Nil(t, err) defer conn.Close() //Initialize seq table diff --git a/go/test/endtoend/vtgate/transaction/rollback/txn_rollback_shutdown_test.go b/go/test/endtoend/vtgate/transaction/rollback/txn_rollback_shutdown_test.go new file mode 100644 index 00000000000..7785ef6e4cc --- /dev/null +++ b/go/test/endtoend/vtgate/transaction/rollback/txn_rollback_shutdown_test.go @@ -0,0 +1,144 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package rollback + +import ( + "context" + "flag" + "fmt" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/test/endtoend/cluster" +) + +var ( + clusterInstance *cluster.LocalProcessCluster + vtParams mysql.ConnParams + keyspaceName = "ks" + cell = "zone1" + hostname = "localhost" + sqlSchema = ` + create table buffer( + id BIGINT NOT NULL, + msg VARCHAR(64) NOT NULL, + PRIMARY KEY (id) + ) Engine=InnoDB;` +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitcode, err := func() (int, error) { + clusterInstance = cluster.NewCluster(cell, hostname) + defer clusterInstance.Teardown() + + // Reserve vtGate port in order to pass it to vtTablet + clusterInstance.VtgateGrpcPort = clusterInstance.GetAndReservePort() + + // Start topo server + if err := clusterInstance.StartTopo(); err != nil { + return 1, err + } + + // Start keyspace + keyspace := &cluster.Keyspace{ + Name: keyspaceName, + SchemaSQL: sqlSchema, + } + if err := clusterInstance.StartUnshardedKeyspace(*keyspace, 1, false); err != nil { + return 1, err + } + + // Set a short onterm timeout so the test goes faster. + clusterInstance.VtGateExtraArgs = []string{"-onterm_timeout", "1s"} + if err := clusterInstance.StartVtgate(); err != nil { + return 1, err + } + vtParams = mysql.ConnParams{ + Host: clusterInstance.Hostname, + Port: clusterInstance.VtgateMySQLPort, + } + + return m.Run(), nil + }() + if err != nil { + fmt.Printf("%v\n", err) + os.Exit(1) + } else { + os.Exit(exitcode) + } +} + +func exec(t *testing.T, conn *mysql.Conn, query string) *sqltypes.Result { + t.Helper() + qr, err := conn.ExecuteFetch(query, 1000, true) + if err != nil { + t.Fatal(err) + } + return qr +} + +func TestTransactionRollBackWhenShutDown(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + if err != nil { + t.Fatal(err) + } + defer conn.Close() + + exec(t, conn, "insert into buffer(id, msg) values(3,'mark')") + exec(t, conn, "insert into buffer(id, msg) values(4,'doug')") + + // start an incomplete transaction + exec(t, conn, "begin") + exec(t, conn, "insert into buffer(id, msg) values(33,'mark')") + + // Enforce a restart to enforce rollback + if err = clusterInstance.ReStartVtgate(); err != nil { + t.Errorf("Fail to re-start vtgate: %v", err) + } + + want := "" + + // Make a new mysql connection to vtGate + vtParams = mysql.ConnParams{ + Host: clusterInstance.Hostname, + Port: clusterInstance.VtgateMySQLPort, + } + conn2, err := mysql.Connect(ctx, &vtParams) + if err != nil { + t.Fatal(err) + } + defer conn2.Close() + + vtParams = mysql.ConnParams{ + Host: clusterInstance.Hostname, + Port: clusterInstance.VtgateMySQLPort, + } + + // Verify that rollback worked + qr := exec(t, conn2, "select id from buffer where msg='mark'") + got := fmt.Sprintf("%v", qr.Rows) + want = `[[INT64(3)]]` + assert.Equal(t, want, got) +} diff --git a/go/test/endtoend/vtgate/transaction/trxn_mode_test.go b/go/test/endtoend/vtgate/transaction/trxn_mode_test.go index bf20e10dd9b..5ab5e247ec7 100644 --- a/go/test/endtoend/vtgate/transaction/trxn_mode_test.go +++ b/go/test/endtoend/vtgate/transaction/trxn_mode_test.go @@ -95,10 +95,11 @@ var ( ) func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) flag.Parse() exitcode, err := func() (int, error) { - clusterInstance = cluster.NewCluster(cell, hostname) + clusterInstance = cluster.NewCluster(cell, hostname) defer clusterInstance.Teardown() // Reserve vtGate port in order to pass it to vtTablet @@ -156,6 +157,7 @@ func exec(t *testing.T, conn *mysql.Conn, query string) *sqltypes.Result { // TestTransactionModes tests trasactions using twopc mode func TestTransactionModes(t *testing.T) { + defer cluster.PanicHandler(t) ctx := context.Background() conn, err := mysql.Connect(ctx, &vtParams) if err != nil { diff --git a/go/test/endtoend/vtgate/vschema/vschema_test.go b/go/test/endtoend/vtgate/vschema/vschema_test.go index bcab68351dc..18f833c7aff 100644 --- a/go/test/endtoend/vtgate/vschema/vschema_test.go +++ b/go/test/endtoend/vtgate/vschema/vschema_test.go @@ -51,10 +51,11 @@ var ( ) func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) flag.Parse() exitcode, err := func() (int, error) { - clusterInstance = cluster.NewCluster(cell, hostname) + clusterInstance = cluster.NewCluster(cell, hostname) defer clusterInstance.Teardown() // Start topo server @@ -94,6 +95,7 @@ func TestMain(m *testing.M) { } func TestVSchema(t *testing.T) { + defer cluster.PanicHandler(t) ctx := context.Background() conn, err := mysql.Connect(ctx, &vtParams) if err != nil { diff --git a/go/test/endtoend/worker/worker_test.go b/go/test/endtoend/worker/worker_test.go new file mode 100644 index 00000000000..48b8f2a7ef3 --- /dev/null +++ b/go/test/endtoend/worker/worker_test.go @@ -0,0 +1,606 @@ +/* +Copyright 2019 The Vitess Authors. + +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 the robustness and resiliency of vtworkers. + +package worker + +import ( + "fmt" + "io/ioutil" + "net/http" + "net/url" + "os/exec" + "reflect" + "strconv" + "strings" + "testing" + "time" + + "vitess.io/vitess/go/test/endtoend/sharding" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/json2" + "vitess.io/vitess/go/test/endtoend/cluster" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" +) + +var ( + master *cluster.Vttablet + replica1 *cluster.Vttablet + rdOnly1 *cluster.Vttablet + + shard0Master *cluster.Vttablet + shard0Replica *cluster.Vttablet + shard0RdOnly1 *cluster.Vttablet + + shard1Master *cluster.Vttablet + shard1Replica *cluster.Vttablet + shard1RdOnly1 *cluster.Vttablet + + localCluster *cluster.LocalProcessCluster + cell = cluster.DefaultCell + hostname = "localhost" + keyspaceName = "test_keyspace" + shardName = "0" + shardTablets []*cluster.Vttablet + shard0Tablets []*cluster.Vttablet + shard1Tablets []*cluster.Vttablet + workerTestOffset = 0 + commonTabletArg = []string{ + "-binlog_use_v3_resharding_mode=true"} + vtWorkerTest = ` + create table worker_test ( + id bigint unsigned, + sid int unsigned, + msg varchar(64), + primary key (id), + index by_msg (msg) + ) Engine=InnoDB` + + vSchema = ` + { + "sharded": true, + "vindexes": { + "hash": { + "type": "hash" + } + }, + "tables": { + "worker_test": { + "column_vindexes": [ + { + "column": "sid", + "name": "hash" + } + ] + } + } +}` +) + +func TestReparentDuringWorkerCopy(t *testing.T) { + defer cluster.PanicHandler(t) + _, err := initializeCluster(t, false) + defer localCluster.Teardown() + require.Nil(t, err) + initialSetup(t) + verifySuccessfulWorkerCopyWithReparent(t, false) +} + +func TestReparentDuringWorkerCopyMysqlDown(t *testing.T) { + defer cluster.PanicHandler(t) + _, err := initializeCluster(t, false) + defer localCluster.Teardown() + require.Nil(t, err) + initialSetup(t) + verifySuccessfulWorkerCopyWithReparent(t, true) +} + +func TestWebInterface(t *testing.T) { + defer cluster.PanicHandler(t) + _, err := initializeCluster(t, true) + require.Nil(t, err) + defer localCluster.Teardown() + err = localCluster.StartVtworker(cell, "--use_v3_resharding_mode=true") + assert.Nil(t, err) + baseURL := fmt.Sprintf("http://localhost:%d", localCluster.VtworkerProcess.Port) + + // Wait for /status to become available. + startTime := time.Now() + for { + resp, err := http.Get(baseURL + "/status") + if err != nil && !time.Now().After(startTime.Add(10*time.Second)) { + time.Sleep(10 * time.Millisecond) + continue + } + if resp.StatusCode == 200 || time.Now().After(startTime.Add(10*time.Second)) { + break + } + } + + // Run the command twice to make sure it's idempotent. + i := 0 + for i < 2 { + data := url.Values{"message": {"pong"}} + http.DefaultClient.CheckRedirect = func(req *http.Request, via []*http.Request) error { + return http.ErrUseLastResponse + } + resp, err := http.Post(baseURL+"/Debugging/Ping", "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) + assert.Nil(t, err) + assert.Equal(t, 307, resp.StatusCode) + + // Wait for the Ping command to finish. + pollForVars(t, "done") + // Verify that the command logged something and it's available at /status. + resp, err = http.Get(baseURL + "/status") + assert.Nil(t, err) + if resp.StatusCode == 200 { + respByte, _ := ioutil.ReadAll(resp.Body) + respStr := string(respByte) + assert.Contains(t, respStr, "Ping command was called with message: 'pong'", fmt.Sprintf("Command did not log output to /status: %s", respStr)) + } + + // Reset the job. + _, err = http.Get(baseURL + "/reset") + assert.Nil(t, err) + resp, err = http.Get(baseURL + "/status") + assert.Nil(t, err) + if resp.StatusCode == 200 { + respByte, _ := ioutil.ReadAll(resp.Body) + statusAfterReset := string(respByte) + assert.Contains(t, statusAfterReset, "This worker is idle.", "/status does not indicate that the reset was successful") + } + i++ + } + + err = localCluster.VtworkerProcess.TearDown() + assert.Nil(t, err) + +} + +func initialSetup(t *testing.T) { + + runShardTablets(t, "0", shardTablets, true) + + // create the split shards + runShardTablets(t, "-80", shard0Tablets, false) + runShardTablets(t, "80-", shard1Tablets, false) + + // insert values + insertValues(master, "shard-0", 1, 4000, 0) + insertValues(master, "shard-1", 4, 4000, 1) + + // wait for replication position + cluster.WaitForReplicationPos(t, master, rdOnly1, "localhost", 60) + + copySchemaToDestinationShard(t) +} + +func verifySuccessfulWorkerCopyWithReparent(t *testing.T, isMysqlDown bool) { + + // Verifies that vtworker can successfully copy data for a SplitClone. + + // Order of operations: + // 1. Run a background vtworker + // 2. Wait until the worker successfully resolves the destination masters. + // 3. Reparent the destination tablets + // 4. Wait until the vtworker copy is finished + // 5. Verify that the worker was forced to reresolve topology and retry writes + // due to the reparent. + // 6. Verify that the data was copied successfully to both new shards + + err := localCluster.StartVtworker(cell, "--use_v3_resharding_mode=true") + assert.Nil(t, err) + + // --max_tps is only specified to enable the throttler and ensure that the + // code is executed. But the intent here is not to throttle the test, hence + // the rate limit is set very high. + + var args []string + + args = append(args, "SplitClone", "--offline=false", + "--destination_writer_count", "1", + "--min_healthy_rdonly_tablets", "1", + "--max_tps", "9999") + + // --chunk_count is 2 because rows are currently ordered by primary key such + // that all rows of the first shard come first and then the second shard. + // Make the clone as slow as necessary such that there is enough time to + // run PlannedReparent in the meantime. + + args = append(args, "--source_reader_count", "2", + "--chunk_count", "2", + "--min_rows_per_chunk", "1", + "--write_query_max_rows", "1", + "test_keyspace/0") + + proc, err := localCluster.VtworkerProcess.ExecuteCommandInBg(args...) + assert.Nil(t, err) + + if isMysqlDown { + // vtworker is blocked at this point. This is a good time to test that its + // throttler server is reacting to RPCs. + sharding.CheckThrottlerService(t, fmt.Sprintf("%s:%d", hostname, localCluster.VtworkerProcess.GrpcPort), + []string{"test_keyspace/-80", "test_keyspace/80-"}, 9999, *localCluster) + + pollForVars(t, "cloning the data (online)") + + // Stop MySql + var mysqlCtlProcessList []*exec.Cmd + + for _, tablet := range []*cluster.Vttablet{shard0Master, shard1Master} { + tablet.MysqlctlProcess.InitMysql = false + sqlProc, err := tablet.MysqlctlProcess.StopProcess() + assert.Nil(t, err) + mysqlCtlProcessList = append(mysqlCtlProcessList, sqlProc) + } + + // Wait for mysql processes to stop + for _, sqlProc := range mysqlCtlProcessList { + if err := sqlProc.Wait(); err != nil { + t.Fatal(err) + } + } + + // If MySQL is down, we wait until vtworker retried at least once to make + // sure it reached the point where a write failed due to MySQL being down. + // There should be two retries at least, one for each destination shard. + pollForVarsWorkerRetryCount(t, 1) + + // Bring back masters. Since we test with semi-sync now, we need at least + // one replica for the new master. This test is already quite expensive, + // so we bring back the old master and then let it be converted to a + // replica by PRS, rather than leaving the old master down and having a + // third replica up the whole time. + + // start mysql + var mysqlCtlProcessStartList []*exec.Cmd + + for _, tablet := range []*cluster.Vttablet{shard0Master, shard1Master} { + tablet.MysqlctlProcess.InitMysql = false + sqlProc, err := tablet.MysqlctlProcess.StartProcess() + assert.Nil(t, err) + mysqlCtlProcessStartList = append(mysqlCtlProcessStartList, sqlProc) + } + + // Wait for mysql processes to start + for _, sqlProc := range mysqlCtlProcessStartList { + if err := sqlProc.Wait(); err != nil { + t.Fatal(err) + } + } + } else { + + // NOTE: There is a race condition around this: + // It's possible that the SplitClone vtworker command finishes before the + // PlannedReparentShard vtctl command, which we start below, succeeds. + // Then the test would fail because vtworker did not have to retry. + // + // To workaround this, the test takes a parameter to increase the number of + // rows that the worker has to copy (with the idea being to slow the worker + // down). + // You should choose a value for num_insert_rows, such that this test + // passes for your environment (trial-and-error...) + // Make sure that vtworker got past the point where it picked a master + // for each destination shard ("finding targets" state). + pollForVars(t, "cloning the data (online)") + + } + + // Reparent away from the old masters. + localCluster.VtctlclientProcess.ExecuteCommand("PlannedReparentShard", "-keyspace_shard", + "test_keyspace/-80", "-new_master", shard0Replica.Alias) + + localCluster.VtctlclientProcess.ExecuteCommand("PlannedReparentShard", "-keyspace_shard", + "test_keyspace/80-", "-new_master", shard1Replica.Alias) + + proc.Wait() + + // Verify that we were forced to re-resolve and retry. + pollForVarsWorkerRetryCount(t, 1) + + err = localCluster.VtworkerProcess.TearDown() + assert.Nil(t, err) + + cluster.WaitForReplicationPos(t, shard0Replica, shard0RdOnly1, "localhost", 60) + cluster.WaitForReplicationPos(t, shard1Replica, shard1RdOnly1, "localhost", 60) + + err = localCluster.VtworkerProcess.ExecuteVtworkerCommand(localCluster.GetAndReservePort(), localCluster.GetAndReservePort(), "-cell", cell, + "--use_v3_resharding_mode=true", + "SplitClone", + "--online=false", + "--min_healthy_rdonly_tablets", "1", + "test_keyspace/0") + assert.Nil(t, err) + + // Make sure that everything is caught up to the same replication point + runSplitDiff(t, "test_keyspace/-80") + runSplitDiff(t, "test_keyspace/80-") + assertShardDataEqual(t, "0", master, shard0Replica) + assertShardDataEqual(t, "1", master, shard1Replica) +} + +func assertShardDataEqual(t *testing.T, shardNum string, sourceTablet *cluster.Vttablet, destinationTablet *cluster.Vttablet) { + messageStr := fmt.Sprintf("shard-%s", shardNum) + selectQuery := "select id,sid,msg from worker_test where msg = '" + messageStr + "' order by id asc" + qrSource, err := sourceTablet.VttabletProcess.QueryTablet(selectQuery, keyspaceName, true) + assert.Nil(t, err) + + // Make sure all the right rows made it from the source to the destination + qrDestination, err := destinationTablet.VttabletProcess.QueryTablet(selectQuery, keyspaceName, true) + assert.Nil(t, err) + assert.Equal(t, len(qrSource.Rows), len(qrDestination.Rows)) + + assert.Equal(t, fmt.Sprint(qrSource.Rows), fmt.Sprint(qrDestination.Rows)) + + // Make sure that there are no extra rows on the destination + countQuery := "select count(*) from worker_test" + qrDestinationCount, err := destinationTablet.VttabletProcess.QueryTablet(countQuery, keyspaceName, true) + assert.Nil(t, err) + assert.Equal(t, fmt.Sprintf("%d", len(qrDestination.Rows)), fmt.Sprintf("%s", qrDestinationCount.Rows[0][0].ToBytes())) + +} + +// Runs a vtworker SplitDiff on the given keyspace/shard. +func runSplitDiff(t *testing.T, keyspaceShard string) { + + err := localCluster.VtworkerProcess.ExecuteVtworkerCommand(localCluster.GetAndReservePort(), + localCluster.GetAndReservePort(), + "-cell", cell, + "--use_v3_resharding_mode=true", + "SplitDiff", + "--min_healthy_rdonly_tablets", "1", + keyspaceShard) + assert.Nil(t, err) + +} + +func pollForVars(t *testing.T, mssg string) { + startTime := time.Now() + var resultMap map[string]interface{} + var err error + var workerState string + for { + resultMap, err = localCluster.VtworkerProcess.GetVars() + assert.Nil(t, err) + workerState = fmt.Sprintf("%v", reflect.ValueOf(resultMap["WorkerState"])) + if strings.Contains(workerState, mssg) || (time.Now().After(startTime.Add(60 * time.Second))) { + break + } + continue + } + assert.Contains(t, workerState, mssg) +} + +func pollForVarsWorkerRetryCount(t *testing.T, count int) { + startTime := time.Now() + var resultMap map[string]interface{} + var err error + var workerRetryCountInt int + for { + resultMap, err = localCluster.VtworkerProcess.GetVars() + if err != nil { + continue + } + workerRetryCount := fmt.Sprintf("%v", reflect.ValueOf(resultMap["WorkerRetryCount"])) + workerRetryCountInt, err = strconv.Atoi(workerRetryCount) + assert.Nil(t, err) + if workerRetryCountInt > count || (time.Now().After(startTime.Add(60 * time.Second))) { + break + } + continue + } + assert.Greater(t, workerRetryCountInt, count) +} + +// vttablet: the Tablet instance to modify. +// msg: the value of `msg` column. +// numValues: number of rows to be inserted. +func insertValues(tablet *cluster.Vttablet, msg string, sid int, numValues int, initialVal int) { + + // For maximum performance, multiple values are inserted in one statement. + // However, when the statements are too long, queries will timeout and + // vttablet will kill them. Therefore, we chunk it into multiple statements. + maxChunkSize := 100 * 1000 + + var fullList []int + for i := 1; i <= numValues; i++ { + fullList = append(fullList, i) + } + m := getChunkArr(fullList, maxChunkSize) + + for i := 0; i < len(m); i++ { + valueStr := "" + for j := 0; j < len(m[i]); j++ { + if m[i][j] != m[i][0] { + valueStr += "," + } + rowID := j*2 + initialVal + valueStr = valueStr + fmt.Sprintf("(%d, %d, '%s')", rowID, sid, msg) + } + workerTestOffset += len(m[i]) + tablet.VttabletProcess.QueryTablet(fmt.Sprintf("insert into worker_test(id, sid, msg) values %s", valueStr), keyspaceName, true) + } +} + +func getChunkArr(fullList []int, chunkSize int) [][]int { + var m [][]int + for i := 0; i < len(fullList); i += chunkSize { + end := i + chunkSize + if end > len(fullList) { + end = len(fullList) + } + m = append(m, fullList[i:end]) + } + return m +} + +// shardName: the name of the shard to start tablets in +// tabletArr: an instance of ShardTablets for the given shard +// createTable: boolean, True iff we should create a table on the tablets +func runShardTablets(t *testing.T, shardName string, tabletArr []*cluster.Vttablet, createTable bool) error { + //Handles all the necessary work for initially running a shard's tablets. + + // This encompasses the following steps: + // 1. (optional) Create db + // 2. Starting vttablets and let themselves init them + // 3. Waiting for the appropriate vttablet state + // 4. Force reparent to the master tablet + // 5. RebuildKeyspaceGraph + // 7. (optional) Running initial schema setup + + // Start tablets. + for _, tablet := range tabletArr { + if err := tablet.VttabletProcess.CreateDB(keyspaceName); err != nil { + return err + } + err := tablet.VttabletProcess.Setup() + require.Nil(t, err) + } + + // Reparent to choose an initial master and enable replication. + err := localCluster.VtctlclientProcess.InitShardMaster(keyspaceName, shardName, cell, tabletArr[0].TabletUID) + require.Nil(t, err) + + for { + result, err := localCluster.VtctlclientProcess.ExecuteCommandWithOutput("GetShard", fmt.Sprintf("test_keyspace/%s", shardName)) + assert.Nil(t, err) + + var shardInfo topodatapb.Shard + err = json2.Unmarshal([]byte(result), &shardInfo) + assert.Nil(t, err) + + if int(shardInfo.MasterAlias.Uid) == tabletArr[0].TabletUID { + break + } + time.Sleep(10 * time.Second) + continue + } + + err = localCluster.VtctlclientProcess.ExecuteCommand("RebuildKeyspaceGraph", "test_keyspace") + assert.Nil(t, err) + + // Enforce a health check instead of waiting for the next periodic one. + // (saves up to 1 second execution time on average) + for _, tablet := range []*cluster.Vttablet{tabletArr[1], tabletArr[2]} { + err = localCluster.VtctlclientProcess.ExecuteCommand("RunHealthCheck", tablet.Alias) + assert.Nil(t, err) + } + + // Wait for tablet state to change after starting all tablets. This allows + // us to start all tablets at once, instead of sequentially waiting. + // NOTE: Replication has to be enabled first or the health check will + // set a replica or rdonly tablet back to NOT_SERVING. + + for _, tablet := range tabletArr { + err = tablet.VttabletProcess.WaitForTabletType("SERVING") + require.Nil(t, err) + } + + if createTable { + err = localCluster.VtctlclientProcess.ApplySchema(keyspaceName, vtWorkerTest) + assert.Nil(t, err) + + err = localCluster.VtctlclientProcess.ApplyVSchema(keyspaceName, vSchema) + assert.Nil(t, err) + } + + return err +} + +func copySchemaToDestinationShard(t *testing.T) { + for _, keyspaceShard := range []string{"test_keyspace/-80", "test_keyspace/80-"} { + err := localCluster.VtctlclientProcess.ExecuteCommand("CopySchemaShard", "--exclude_tables", "unrelated", "test_keyspace/0", keyspaceShard) + assert.Nil(t, err) + } +} + +func initializeCluster(t *testing.T, onlyTopo bool) (int, error) { + + localCluster = cluster.NewCluster(cell, hostname) + + // Start topo server + err := localCluster.StartTopo() + if err != nil { + return 1, err + } + + if onlyTopo { + return 0, nil + } + // Start keyspace + keyspace := &cluster.Keyspace{ + Name: keyspaceName, + } + localCluster.Keyspaces = append(localCluster.Keyspaces, *keyspace) + + shard := &cluster.Shard{ + Name: shardName, + } + shard0 := &cluster.Shard{ + Name: "-80", + } + shard1 := &cluster.Shard{ + Name: "80-", + } + + // Defining all the tablets + master = localCluster.GetVttabletInstance("replica", 0, "") + replica1 = localCluster.GetVttabletInstance("replica", 0, "") + rdOnly1 = localCluster.GetVttabletInstance("rdonly", 0, "") + shard0Master = localCluster.GetVttabletInstance("replica", 0, "") + shard0Replica = localCluster.GetVttabletInstance("replica", 0, "") + shard0RdOnly1 = localCluster.GetVttabletInstance("rdonly", 0, "") + shard1Master = localCluster.GetVttabletInstance("replica", 0, "") + shard1Replica = localCluster.GetVttabletInstance("replica", 0, "") + shard1RdOnly1 = localCluster.GetVttabletInstance("rdonly", 0, "") + + shard.Vttablets = []*cluster.Vttablet{master, replica1, rdOnly1} + shard0.Vttablets = []*cluster.Vttablet{shard0Master, shard0Replica, shard0RdOnly1} + shard1.Vttablets = []*cluster.Vttablet{shard1Master, shard1Replica, shard1RdOnly1} + + localCluster.VtTabletExtraArgs = append(localCluster.VtTabletExtraArgs, commonTabletArg...) + + err = localCluster.LaunchCluster(keyspace, []cluster.Shard{*shard, *shard0, *shard1}) + assert.Nil(t, err) + + // Start MySql + var mysqlCtlProcessList []*exec.Cmd + for _, shard := range localCluster.Keyspaces[0].Shards { + for _, tablet := range shard.Vttablets { + if proc, err := tablet.MysqlctlProcess.StartProcess(); err != nil { + t.Fatal(err) + } else { + mysqlCtlProcessList = append(mysqlCtlProcessList, proc) + } + } + } + + // Wait for mysql processes to start + for _, proc := range mysqlCtlProcessList { + if err := proc.Wait(); err != nil { + t.Fatal(err) + } + } + + shardTablets = []*cluster.Vttablet{master, replica1, rdOnly1} + shard0Tablets = []*cluster.Vttablet{shard0Master, shard0Replica, shard0RdOnly1} + shard1Tablets = []*cluster.Vttablet{shard1Master, shard1Replica, shard1RdOnly1} + + return 0, nil +} diff --git a/go/trace/plugin_datadog.go b/go/trace/plugin_datadog.go new file mode 100644 index 00000000000..87809d9bc50 --- /dev/null +++ b/go/trace/plugin_datadog.go @@ -0,0 +1,56 @@ +package trace + +import ( + "flag" + "fmt" + "io" + + "github.com/opentracing/opentracing-go" + "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/opentracer" + ddtracer "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" +) + +var ( + dataDogHost = flag.String("datadog-agent-host", "", "host to send spans to. if empty, no tracing will be done") + dataDogPort = flag.String("datadog-agent-port", "", "port to send spans to. if empty, no tracing will be done") +) + +func newDatadogTracer(serviceName string) (tracingService, io.Closer, error) { + if *dataDogHost == "" || *dataDogPort == "" { + return nil, nil, fmt.Errorf("need host and port to datadog agent to use datadog tracing") + } + + t := opentracer.New( + ddtracer.WithAgentAddr(*dataDogHost+":"+*dataDogPort), + ddtracer.WithServiceName(serviceName), + ddtracer.WithDebugMode(true), + ddtracer.WithSampler(ddtracer.NewRateSampler(*samplingRate)), + ) + + opentracing.SetGlobalTracer(t) + + return openTracingService{Tracer: &datadogTracer{actual: t}}, &ddCloser{}, nil +} + +var _ io.Closer = (*ddCloser)(nil) + +type ddCloser struct{} + +func (ddCloser) Close() error { + ddtracer.Stop() + return nil +} + +func init() { + tracingBackendFactories["opentracing-datadog"] = newDatadogTracer +} + +var _ tracer = (*datadogTracer)(nil) + +type datadogTracer struct { + actual opentracing.Tracer +} + +func (dt *datadogTracer) GetOpenTracingTracer() opentracing.Tracer { + return dt.actual +} diff --git a/go/vt/binlog/binlog_streamer.go b/go/vt/binlog/binlog_streamer.go index 9a2dec4c866..24206437e3d 100644 --- a/go/vt/binlog/binlog_streamer.go +++ b/go/vt/binlog/binlog_streamer.go @@ -28,6 +28,7 @@ import ( "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/stats" + "vitess.io/vitess/go/vt/dbconfigs" "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vttablet/tabletserver/schema" @@ -133,7 +134,7 @@ type tableCacheEntry struct { // NewStreamer() again. type Streamer struct { // The following fields at set at creation and immutable. - cp *mysql.ConnParams + cp dbconfigs.Connector se *schema.Engine resolverFactory keyspaceIDResolverFactory extractPK bool @@ -155,7 +156,7 @@ type Streamer struct { // startPos is the position to start streaming at. Incompatible with timestamp. // timestamp is the timestamp to start streaming at. Incompatible with startPos. // sendTransaction is called each time a transaction is committed or rolled back. -func NewStreamer(cp *mysql.ConnParams, se *schema.Engine, clientCharset *binlogdatapb.Charset, startPos mysql.Position, timestamp int64, sendTransaction sendTransactionFunc) *Streamer { +func NewStreamer(cp dbconfigs.Connector, se *schema.Engine, clientCharset *binlogdatapb.Charset, startPos mysql.Position, timestamp int64, sendTransaction sendTransactionFunc) *Streamer { return &Streamer{ cp: cp, se: se, @@ -407,7 +408,7 @@ func (bls *Streamer) parseEvents(ctx context.Context, events <-chan mysql.Binlog return pos, err } default: // BL_DDL, BL_SET, BL_INSERT, BL_UPDATE, BL_DELETE, BL_UNRECOGNIZED - if q.Database != "" && q.Database != bls.cp.DbName { + if q.Database != "" && q.Database != bls.cp.DBName() { // Skip cross-db statements. continue } @@ -472,7 +473,7 @@ func (bls *Streamer) parseEvents(ctx context.Context, events <-chan mysql.Binlog // Check we're in the right database, and if so, fill // in more data. - if tm.Database != "" && tm.Database != bls.cp.DbName { + if tm.Database != "" && tm.Database != bls.cp.DBName() { continue } diff --git a/go/vt/binlog/binlog_streamer_rbr_test.go b/go/vt/binlog/binlog_streamer_rbr_test.go index b235373a59f..58f0850cc55 100644 --- a/go/vt/binlog/binlog_streamer_rbr_test.go +++ b/go/vt/binlog/binlog_streamer_rbr_test.go @@ -23,6 +23,7 @@ import ( "golang.org/x/net/context" "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/vt/dbconfigs" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vttablet/tabletserver/schema" @@ -256,7 +257,13 @@ func TestStreamerParseRBREvents(t *testing.T) { }) return nil } - bls := NewStreamer(&mysql.ConnParams{DbName: "vt_test_keyspace"}, se, nil, mysql.Position{}, 0, sendTransaction) + // Set mock mysql.ConnParams and dbconfig + mcp := &mysql.ConnParams{ + DbName: "vt_test_keyspace", + } + dbcfgs := dbconfigs.New(mcp) + + bls := NewStreamer(dbcfgs, se, nil, mysql.Position{}, 0, sendTransaction) go sendTestEvents(events, input) _, err := bls.parseEvents(context.Background(), events) @@ -498,7 +505,13 @@ func TestStreamerParseRBRNameEscapes(t *testing.T) { }) return nil } - bls := NewStreamer(&mysql.ConnParams{DbName: "vt_test_keyspace"}, se, nil, mysql.Position{}, 0, sendTransaction) + // Set mock mysql.ConnParams and dbconfig + mcp := &mysql.ConnParams{ + DbName: "vt_test_keyspace", + } + dbcfgs := dbconfigs.New(mcp) + + bls := NewStreamer(dbcfgs, se, nil, mysql.Position{}, 0, sendTransaction) go sendTestEvents(events, input) _, err := bls.parseEvents(context.Background(), events) diff --git a/go/vt/binlog/binlog_streamer_test.go b/go/vt/binlog/binlog_streamer_test.go index d8edb2b7eb3..5126f330465 100644 --- a/go/vt/binlog/binlog_streamer_test.go +++ b/go/vt/binlog/binlog_streamer_test.go @@ -28,6 +28,7 @@ import ( "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/vt/dbconfigs" binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" querypb "vitess.io/vitess/go/vt/proto/query" ) @@ -115,7 +116,14 @@ func TestStreamerParseEventsXID(t *testing.T) { }, } var got binlogStatements - bls := NewStreamer(&mysql.ConnParams{DbName: "vt_test_keyspace"}, nil, nil, mysql.Position{}, 0, (&got).sendTransaction) + + // Set mock mysql.ConnParams and dbconfig + mcp := &mysql.ConnParams{ + DbName: "vt_test_keyspace", + } + dbcfgs := dbconfigs.New(mcp) + + bls := NewStreamer(dbcfgs, nil, nil, mysql.Position{}, 0, (&got).sendTransaction) go sendTestEvents(events, input) _, err := bls.parseEvents(context.Background(), events) @@ -170,8 +178,14 @@ func TestStreamerParseEventsCommit(t *testing.T) { }, }, } + // Set mock mysql.ConnParams and dbconfig + mcp := &mysql.ConnParams{ + DbName: "vt_test_keyspace", + } + dbcfgs := dbconfigs.New(mcp) + var got binlogStatements - bls := NewStreamer(&mysql.ConnParams{DbName: "vt_test_keyspace"}, nil, nil, mysql.Position{}, 0, (&got).sendTransaction) + bls := NewStreamer(dbcfgs, nil, nil, mysql.Position{}, 0, (&got).sendTransaction) go sendTestEvents(events, input) _, err := bls.parseEvents(context.Background(), events) @@ -190,7 +204,14 @@ func TestStreamerStop(t *testing.T) { sendTransaction := func(eventToken *querypb.EventToken, statements []FullBinlogStatement) error { return nil } - bls := NewStreamer(&mysql.ConnParams{DbName: "vt_test_keyspace"}, nil, nil, mysql.Position{}, 0, sendTransaction) + + // Set mock mysql.ConnParams and dbconfig + mcp := &mysql.ConnParams{ + DbName: "vt_test_keyspace", + } + dbcfgs := dbconfigs.New(mcp) + + bls := NewStreamer(dbcfgs, nil, nil, mysql.Position{}, 0, sendTransaction) // Start parseEvents(), but don't send it anything, so it just waits. ctx, cancel := context.WithCancel(context.Background()) @@ -235,7 +256,14 @@ func TestStreamerParseEventsClientEOF(t *testing.T) { sendTransaction := func(eventToken *querypb.EventToken, statements []FullBinlogStatement) error { return io.EOF } - bls := NewStreamer(&mysql.ConnParams{DbName: "vt_test_keyspace"}, nil, nil, mysql.Position{}, 0, sendTransaction) + + // Set mock mysql.ConnParams and dbconfig + mcp := &mysql.ConnParams{ + DbName: "vt_test_keyspace", + } + dbcfgs := dbconfigs.New(mcp) + + bls := NewStreamer(dbcfgs, nil, nil, mysql.Position{}, 0, sendTransaction) go sendTestEvents(events, input) _, err := bls.parseEvents(context.Background(), events) @@ -253,8 +281,13 @@ func TestStreamerParseEventsServerEOF(t *testing.T) { sendTransaction := func(eventToken *querypb.EventToken, statements []FullBinlogStatement) error { return nil } - bls := NewStreamer(&mysql.ConnParams{DbName: "vt_test_keyspace"}, nil, nil, mysql.Position{}, 0, sendTransaction) + // Set mock mysql.ConnParams and dbconfig + mcp := &mysql.ConnParams{ + DbName: "vt_test_keyspace", + } + dbcfgs := dbconfigs.New(mcp) + bls := NewStreamer(dbcfgs, nil, nil, mysql.Position{}, 0, sendTransaction) _, err := bls.parseEvents(context.Background(), events) if err != want { t.Errorf("wrong error, got %#v, want %#v", err, want) @@ -283,7 +316,14 @@ func TestStreamerParseEventsSendErrorXID(t *testing.T) { sendTransaction := func(eventToken *querypb.EventToken, statements []FullBinlogStatement) error { return fmt.Errorf("foobar") } - bls := NewStreamer(&mysql.ConnParams{DbName: "vt_test_keyspace"}, nil, nil, mysql.Position{}, 0, sendTransaction) + + // Set mock mysql.ConnParams and dbconfig + mcp := &mysql.ConnParams{ + DbName: "vt_test_keyspace", + } + dbcfgs := dbconfigs.New(mcp) + + bls := NewStreamer(dbcfgs, nil, nil, mysql.Position{}, 0, sendTransaction) go sendTestEvents(events, input) @@ -321,7 +361,14 @@ func TestStreamerParseEventsSendErrorCommit(t *testing.T) { sendTransaction := func(eventToken *querypb.EventToken, statements []FullBinlogStatement) error { return fmt.Errorf("foobar") } - bls := NewStreamer(&mysql.ConnParams{DbName: "vt_test_keyspace"}, nil, nil, mysql.Position{}, 0, sendTransaction) + + // Set mock mysql.ConnParams and dbconfig + mcp := &mysql.ConnParams{ + DbName: "vt_test_keyspace", + } + dbcfgs := dbconfigs.New(mcp) + + bls := NewStreamer(dbcfgs, nil, nil, mysql.Position{}, 0, sendTransaction) go sendTestEvents(events, input) _, err := bls.parseEvents(context.Background(), events) @@ -354,7 +401,14 @@ func TestStreamerParseEventsInvalid(t *testing.T) { sendTransaction := func(eventToken *querypb.EventToken, statements []FullBinlogStatement) error { return nil } - bls := NewStreamer(&mysql.ConnParams{DbName: "vt_test_keyspace"}, nil, nil, mysql.Position{}, 0, sendTransaction) + + // Set mock mysql.ConnParams and dbconfig + mcp := &mysql.ConnParams{ + DbName: "vt_test_keyspace", + } + dbcfgs := dbconfigs.New(mcp) + + bls := NewStreamer(dbcfgs, nil, nil, mysql.Position{}, 0, sendTransaction) go sendTestEvents(events, input) _, err := bls.parseEvents(context.Background(), events) @@ -389,7 +443,14 @@ func TestStreamerParseEventsInvalidFormat(t *testing.T) { sendTransaction := func(eventToken *querypb.EventToken, statements []FullBinlogStatement) error { return nil } - bls := NewStreamer(&mysql.ConnParams{DbName: "vt_test_keyspace"}, nil, nil, mysql.Position{}, 0, sendTransaction) + + // Set mock mysql.ConnParams and dbconfig + mcp := &mysql.ConnParams{ + DbName: "vt_test_keyspace", + } + dbcfgs := dbconfigs.New(mcp) + + bls := NewStreamer(dbcfgs, nil, nil, mysql.Position{}, 0, sendTransaction) go sendTestEvents(events, input) _, err := bls.parseEvents(context.Background(), events) @@ -424,7 +485,14 @@ func TestStreamerParseEventsNoFormat(t *testing.T) { sendTransaction := func(eventToken *querypb.EventToken, statements []FullBinlogStatement) error { return nil } - bls := NewStreamer(&mysql.ConnParams{DbName: "vt_test_keyspace"}, nil, nil, mysql.Position{}, 0, sendTransaction) + + // Set mock mysql.ConnParams and dbconfig + mcp := &mysql.ConnParams{ + DbName: "vt_test_keyspace", + } + dbcfgs := dbconfigs.New(mcp) + + bls := NewStreamer(dbcfgs, nil, nil, mysql.Position{}, 0, sendTransaction) go sendTestEvents(events, input) _, err := bls.parseEvents(context.Background(), events) @@ -457,7 +525,14 @@ func TestStreamerParseEventsInvalidQuery(t *testing.T) { sendTransaction := func(eventToken *querypb.EventToken, statements []FullBinlogStatement) error { return nil } - bls := NewStreamer(&mysql.ConnParams{DbName: "vt_test_keyspace"}, nil, nil, mysql.Position{}, 0, sendTransaction) + + // Set mock mysql.ConnParams and dbconfig + mcp := &mysql.ConnParams{ + DbName: "vt_test_keyspace", + } + dbcfgs := dbconfigs.New(mcp) + + bls := NewStreamer(dbcfgs, nil, nil, mysql.Position{}, 0, sendTransaction) go sendTestEvents(events, input) _, err := bls.parseEvents(context.Background(), events) @@ -538,7 +613,13 @@ func TestStreamerParseEventsRollback(t *testing.T) { }, } var got binlogStatements - bls := NewStreamer(&mysql.ConnParams{DbName: "vt_test_keyspace"}, nil, nil, mysql.Position{}, 0, (&got).sendTransaction) + // Set mock mysql.ConnParams and dbconfig + mcp := &mysql.ConnParams{ + DbName: "vt_test_keyspace", + } + dbcfgs := dbconfigs.New(mcp) + + bls := NewStreamer(dbcfgs, nil, nil, mysql.Position{}, 0, (&got).sendTransaction) go sendTestEvents(events, input) if _, err := bls.parseEvents(context.Background(), events); err != ErrServerEOF { @@ -603,7 +684,14 @@ func TestStreamerParseEventsDMLWithoutBegin(t *testing.T) { }, } var got binlogStatements - bls := NewStreamer(&mysql.ConnParams{DbName: "vt_test_keyspace"}, nil, nil, mysql.Position{}, 0, (&got).sendTransaction) + + // Set mock mysql.ConnParams and dbconfig + mcp := &mysql.ConnParams{ + DbName: "vt_test_keyspace", + } + dbcfgs := dbconfigs.New(mcp) + + bls := NewStreamer(dbcfgs, nil, nil, mysql.Position{}, 0, (&got).sendTransaction) go sendTestEvents(events, input) if _, err := bls.parseEvents(context.Background(), events); err != ErrServerEOF { @@ -671,7 +759,14 @@ func TestStreamerParseEventsBeginWithoutCommit(t *testing.T) { }, } var got binlogStatements - bls := NewStreamer(&mysql.ConnParams{DbName: "vt_test_keyspace"}, nil, nil, mysql.Position{}, 0, (&got).sendTransaction) + + // Set mock mysql.ConnParams and dbconfig + mcp := &mysql.ConnParams{ + DbName: "vt_test_keyspace", + } + dbcfgs := dbconfigs.New(mcp) + + bls := NewStreamer(dbcfgs, nil, nil, mysql.Position{}, 0, (&got).sendTransaction) go sendTestEvents(events, input) if _, err := bls.parseEvents(context.Background(), events); err != ErrServerEOF { @@ -726,7 +821,13 @@ func TestStreamerParseEventsSetInsertID(t *testing.T) { }, } var got binlogStatements - bls := NewStreamer(&mysql.ConnParams{DbName: "vt_test_keyspace"}, nil, nil, mysql.Position{}, 0, (&got).sendTransaction) + // Set mock mysql.ConnParams and dbconfig + mcp := &mysql.ConnParams{ + DbName: "vt_test_keyspace", + } + dbcfgs := dbconfigs.New(mcp) + + bls := NewStreamer(dbcfgs, nil, nil, mysql.Position{}, 0, (&got).sendTransaction) go sendTestEvents(events, input) if _, err := bls.parseEvents(context.Background(), events); err != ErrServerEOF { @@ -761,7 +862,13 @@ func TestStreamerParseEventsInvalidIntVar(t *testing.T) { sendTransaction := func(eventToken *querypb.EventToken, statements []FullBinlogStatement) error { return nil } - bls := NewStreamer(&mysql.ConnParams{DbName: "vt_test_keyspace"}, nil, nil, mysql.Position{}, 0, sendTransaction) + // Set mock mysql.ConnParams and dbconfig + mcp := &mysql.ConnParams{ + DbName: "vt_test_keyspace", + } + dbcfgs := dbconfigs.New(mcp) + + bls := NewStreamer(dbcfgs, nil, nil, mysql.Position{}, 0, sendTransaction) go sendTestEvents(events, input) _, err := bls.parseEvents(context.Background(), events) @@ -818,7 +925,13 @@ func TestStreamerParseEventsOtherDB(t *testing.T) { }, } var got binlogStatements - bls := NewStreamer(&mysql.ConnParams{DbName: "vt_test_keyspace"}, nil, nil, mysql.Position{}, 0, (&got).sendTransaction) + // Set mock mysql.ConnParams and dbconfig + mcp := &mysql.ConnParams{ + DbName: "vt_test_keyspace", + } + dbcfgs := dbconfigs.New(mcp) + + bls := NewStreamer(dbcfgs, nil, nil, mysql.Position{}, 0, (&got).sendTransaction) go sendTestEvents(events, input) if _, err := bls.parseEvents(context.Background(), events); err != ErrServerEOF { @@ -874,7 +987,13 @@ func TestStreamerParseEventsOtherDBBegin(t *testing.T) { }, } var got binlogStatements - bls := NewStreamer(&mysql.ConnParams{DbName: "vt_test_keyspace"}, nil, nil, mysql.Position{}, 0, (&got).sendTransaction) + // Set mock mysql.ConnParams and dbconfig + mcp := &mysql.ConnParams{ + DbName: "vt_test_keyspace", + } + dbcfgs := dbconfigs.New(mcp) + + bls := NewStreamer(dbcfgs, nil, nil, mysql.Position{}, 0, (&got).sendTransaction) go sendTestEvents(events, input) if _, err := bls.parseEvents(context.Background(), events); err != ErrServerEOF { @@ -909,7 +1028,13 @@ func TestStreamerParseEventsBeginAgain(t *testing.T) { sendTransaction := func(eventToken *querypb.EventToken, statements []FullBinlogStatement) error { return nil } - bls := NewStreamer(&mysql.ConnParams{DbName: "vt_test_keyspace"}, nil, nil, mysql.Position{}, 0, sendTransaction) + // Set mock mysql.ConnParams and dbconfig + mcp := &mysql.ConnParams{ + DbName: "vt_test_keyspace", + } + dbcfgs := dbconfigs.New(mcp) + + bls := NewStreamer(dbcfgs, nil, nil, mysql.Position{}, 0, sendTransaction) before := binlogStreamerErrors.Counts()["ParseEvents"] go sendTestEvents(events, input) @@ -972,7 +1097,13 @@ func TestStreamerParseEventsMariadbBeginGTID(t *testing.T) { }, } var got binlogStatements - bls := NewStreamer(&mysql.ConnParams{DbName: "vt_test_keyspace"}, nil, nil, mysql.Position{}, 0, (&got).sendTransaction) + // Set mock mysql.ConnParams and dbconfig + mcp := &mysql.ConnParams{ + DbName: "vt_test_keyspace", + } + dbcfgs := dbconfigs.New(mcp) + + bls := NewStreamer(dbcfgs, nil, nil, mysql.Position{}, 0, (&got).sendTransaction) go sendTestEvents(events, input) if _, err := bls.parseEvents(context.Background(), events); err != ErrServerEOF { @@ -1025,7 +1156,13 @@ func TestStreamerParseEventsMariadbStandaloneGTID(t *testing.T) { }, } var got binlogStatements - bls := NewStreamer(&mysql.ConnParams{DbName: "vt_test_keyspace"}, nil, nil, mysql.Position{}, 0, (&got).sendTransaction) + // Set mock mysql.ConnParams and dbconfig + mcp := &mysql.ConnParams{ + DbName: "vt_test_keyspace", + } + dbcfgs := dbconfigs.New(mcp) + + bls := NewStreamer(dbcfgs, nil, nil, mysql.Position{}, 0, (&got).sendTransaction) go sendTestEvents(events, input) if _, err := bls.parseEvents(context.Background(), events); err != ErrServerEOF { diff --git a/go/vt/binlog/binlogplayer/binlog_player.go b/go/vt/binlog/binlogplayer/binlog_player.go index 993a1ed8b22..d662129cd17 100644 --- a/go/vt/binlog/binlogplayer/binlog_player.go +++ b/go/vt/binlog/binlogplayer/binlog_player.go @@ -79,6 +79,8 @@ type Stats struct { SecondsBehindMaster sync2.AtomicInt64 History *history.History + + State sync2.AtomicString } // SetLastPosition sets the last replication position. @@ -111,7 +113,7 @@ func (bps *Stats) MessageHistory() []string { func NewStats() *Stats { bps := &Stats{} bps.Timings = stats.NewTimings("", "", "") - bps.Rates = stats.NewRates("", bps.Timings, 15, 60e9) + bps.Rates = stats.NewRates("", bps.Timings, 15*60/5, 5*time.Second) bps.History = history.New(3) bps.SecondsBehindMaster.Set(math.MaxInt64) return bps @@ -176,17 +178,12 @@ func NewBinlogPlayerTables(dbClient DBClient, tablet *topodatapb.Tablet, tables // If an error is encountered, it updates the vreplication state to "Error". // If a stop position was specified, and reached, the state is updated to "Stopped". func (blp *BinlogPlayer) ApplyBinlogEvents(ctx context.Context) error { - if err := SetVReplicationState(blp.dbClient, blp.uid, BlpRunning, ""); err != nil { + if err := blp.setVReplicationState(BlpRunning, ""); err != nil { log.Errorf("Error writing Running state: %v", err) } if err := blp.applyEvents(ctx); err != nil { - msg := err.Error() - blp.blplStats.History.Add(&StatsHistoryRecord{ - Time: time.Now(), - Message: msg, - }) - if err := SetVReplicationState(blp.dbClient, blp.uid, BlpError, msg); err != nil { + if err := blp.setVReplicationState(BlpError, err.Error()); err != nil { log.Errorf("Error writing stop state: %v", err) } return err @@ -202,6 +199,7 @@ func (blp *BinlogPlayer) applyEvents(ctx context.Context) error { log.Error(err) return err } + blp.position = settings.StartPos blp.stopPosition = settings.StopPos t, err := throttler.NewThrottler( @@ -240,14 +238,14 @@ func (blp *BinlogPlayer) applyEvents(ctx context.Context) error { case blp.position.Equal(blp.stopPosition): msg := fmt.Sprintf("not starting BinlogPlayer, we're already at the desired position %v", blp.stopPosition) log.Info(msg) - if err := SetVReplicationState(blp.dbClient, blp.uid, BlpStopped, msg); err != nil { + if err := blp.setVReplicationState(BlpStopped, msg); err != nil { log.Errorf("Error writing stop state: %v", err) } return nil case blp.position.AtLeast(blp.stopPosition): msg := fmt.Sprintf("starting point %v greater than stopping point %v", blp.position, blp.stopPosition) log.Error(msg) - if err := SetVReplicationState(blp.dbClient, blp.uid, BlpStopped, msg); err != nil { + if err := blp.setVReplicationState(BlpStopped, msg); err != nil { log.Errorf("Error writing stop state: %v", err) } // Don't return an error. Otherwise, it will keep retrying. @@ -347,7 +345,7 @@ func (blp *BinlogPlayer) applyEvents(ctx context.Context) error { if blp.position.AtLeast(blp.stopPosition) { msg := "Reached stopping position, done playing logs" log.Info(msg) - if err := SetVReplicationState(blp.dbClient, blp.uid, BlpStopped, msg); err != nil { + if err := blp.setVReplicationState(BlpStopped, msg); err != nil { log.Errorf("Error writing stop state: %v", err) } return nil @@ -462,6 +460,21 @@ func (blp *BinlogPlayer) writeRecoveryPosition(tx *binlogdatapb.BinlogTransactio return nil } +func (blp *BinlogPlayer) setVReplicationState(state, message string) error { + if message != "" { + blp.blplStats.History.Add(&StatsHistoryRecord{ + Time: time.Now(), + Message: message, + }) + } + blp.blplStats.State.Set(state) + query := fmt.Sprintf("update _vt.vreplication set state='%v', message=%v where id=%v", state, encodeString(MessageTruncate(message)), blp.uid) + if _, err := blp.dbClient.ExecuteFetch(query, 1); err != nil { + return fmt.Errorf("could not set state: %v: %v", query, err) + } + return nil +} + // CreateVReplicationTable returns the statements required to create // the _vt.vreplication table. // id: is an auto-increment column that identifies the stream. @@ -506,15 +519,6 @@ func AlterVReplicationTable() []string { return []string{"ALTER TABLE _vt.vreplication ADD COLUMN db_name VARBINARY(255) NOT NULL"} } -// SetVReplicationState updates the state in the _vt.vreplication table. -func SetVReplicationState(dbClient DBClient, uid uint32, state, message string) error { - query := fmt.Sprintf("update _vt.vreplication set state='%v', message=%v where id=%v", state, encodeString(MessageTruncate(message)), uid) - if _, err := dbClient.ExecuteFetch(query, 1); err != nil { - return fmt.Errorf("could not set state: %v: %v", query, err) - } - return nil -} - // VRSettings contains the settings of a vreplication table. type VRSettings struct { StartPos mysql.Position diff --git a/go/vt/binlog/binlogplayer/dbclient.go b/go/vt/binlog/binlogplayer/dbclient.go index 83533ddb34a..7dfeb36f2a4 100644 --- a/go/vt/binlog/binlogplayer/dbclient.go +++ b/go/vt/binlog/binlogplayer/dbclient.go @@ -17,10 +17,9 @@ limitations under the License. package binlogplayer import ( + "context" "fmt" - "golang.org/x/net/context" - "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/dbconfigs" @@ -40,12 +39,12 @@ type DBClient interface { // dbClientImpl is a real DBClient backed by a mysql connection. type dbClientImpl struct { - dbConfig *mysql.ConnParams + dbConfig dbconfigs.Connector dbConn *mysql.Conn } // NewDBClient creates a DBClient instance -func NewDBClient(params *mysql.ConnParams) DBClient { +func NewDBClient(params dbconfigs.Connector) DBClient { return &dbClientImpl{ dbConfig: params, } @@ -58,18 +57,16 @@ func (dc *dbClientImpl) handleError(err error) { } func (dc *dbClientImpl) DBName() string { - return dc.dbConfig.DbName + params, _ := dc.dbConfig.MysqlParams() + return params.DbName } func (dc *dbClientImpl) Connect() error { - params, err := dbconfigs.WithCredentials(dc.dbConfig) - if err != nil { - return err - } + var err error ctx := context.Background() - dc.dbConn, err = mysql.Connect(ctx, params) + dc.dbConn, err = dc.dbConfig.Connect(ctx) if err != nil { - return fmt.Errorf("error in connecting to mysql db, err %v", err) + return fmt.Errorf("error in connecting to mysql db with connection %v, err %v", dc.dbConn, err) } return nil } @@ -102,10 +99,7 @@ func (dc *dbClientImpl) Rollback() error { } func (dc *dbClientImpl) Close() { - if dc.dbConn != nil { - dc.dbConn.Close() - dc.dbConn = nil - } + dc.dbConn.Close() } func (dc *dbClientImpl) ExecuteFetch(query string, maxrows int) (*sqltypes.Result, error) { diff --git a/go/vt/binlog/event_streamer.go b/go/vt/binlog/event_streamer.go index 02bbb647cc7..4defc3fed83 100644 --- a/go/vt/binlog/event_streamer.go +++ b/go/vt/binlog/event_streamer.go @@ -26,6 +26,7 @@ import ( "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/vt/dbconfigs" "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vttablet/tabletserver/schema" @@ -51,7 +52,7 @@ type EventStreamer struct { } // NewEventStreamer returns a new EventStreamer on top of a Streamer -func NewEventStreamer(cp *mysql.ConnParams, se *schema.Engine, startPos mysql.Position, timestamp int64, sendEvent sendEventFunc) *EventStreamer { +func NewEventStreamer(cp dbconfigs.Connector, se *schema.Engine, startPos mysql.Position, timestamp int64, sendEvent sendEventFunc) *EventStreamer { evs := &EventStreamer{ sendEvent: sendEvent, } diff --git a/go/vt/binlog/event_streamer_test.go b/go/vt/binlog/event_streamer_test.go index 1a487efaf46..fc5434717a6 100644 --- a/go/vt/binlog/event_streamer_test.go +++ b/go/vt/binlog/event_streamer_test.go @@ -21,6 +21,7 @@ import ( "testing" "github.com/golang/protobuf/proto" + "github.com/stretchr/testify/require" binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" querypb "vitess.io/vitess/go/vt/proto/query" @@ -90,9 +91,7 @@ func TestSetErrors(t *testing.T) { } before := binlogStreamerErrors.Counts()["EventStreamer"] err := evs.transactionToEvent(nil, statements) - if err != nil { - t.Error(err) - } + require.NoError(t, err) got := binlogStreamerErrors.Counts()["EventStreamer"] if got != before+1 { t.Errorf("got: %v, want: %+v", got, before+1) @@ -160,9 +159,7 @@ func TestDMLEvent(t *testing.T) { }, } err := evs.transactionToEvent(eventToken, statements) - if err != nil { - t.Error(err) - } + require.NoError(t, err) } func TestDDLEvent(t *testing.T) { @@ -208,7 +205,5 @@ func TestDDLEvent(t *testing.T) { }, } err := evs.transactionToEvent(eventToken, statements) - if err != nil { - t.Error(err) - } + require.NoError(t, err) } diff --git a/go/vt/binlog/grpcbinlogplayer/player.go b/go/vt/binlog/grpcbinlogplayer/player.go index 21eb81cbb38..1a854f5c35f 100644 --- a/go/vt/binlog/grpcbinlogplayer/player.go +++ b/go/vt/binlog/grpcbinlogplayer/player.go @@ -52,7 +52,7 @@ func (client *client) Dial(tablet *topodatapb.Tablet) error { if err != nil { return err } - client.cc, err = grpcclient.Dial(addr, grpcclient.FailFast(false), opt) + client.cc, err = grpcclient.Dial(addr, grpcclient.FailFast(true), opt) if err != nil { return err } diff --git a/go/vt/binlog/keyspace_id_resolver.go b/go/vt/binlog/keyspace_id_resolver.go index 204960f06ca..a005222434d 100644 --- a/go/vt/binlog/keyspace_id_resolver.go +++ b/go/vt/binlog/keyspace_id_resolver.go @@ -147,7 +147,8 @@ func newKeyspaceIDResolverFactoryV3(ctx context.Context, ts *topo.Server, keyspa if col.Name.EqualString(shardingColumnName) { // We found the column. return i, &keyspaceIDResolverFactoryV3{ - vindex: colVindex.Vindex, + // Only SingleColumn vindexes are returned by FindVindexForSharding. + vindex: colVindex.Vindex.(vindexes.SingleColumn), }, nil } } @@ -158,7 +159,7 @@ func newKeyspaceIDResolverFactoryV3(ctx context.Context, ts *topo.Server, keyspa // keyspaceIDResolverFactoryV3 uses the Vindex to compute the value. type keyspaceIDResolverFactoryV3 struct { - vindex vindexes.Vindex + vindex vindexes.SingleColumn } func (r *keyspaceIDResolverFactoryV3) keyspaceID(v sqltypes.Value) ([]byte, error) { diff --git a/go/vt/binlog/slave_connection.go b/go/vt/binlog/slave_connection.go index c38e67af859..64367757b7f 100644 --- a/go/vt/binlog/slave_connection.go +++ b/go/vt/binlog/slave_connection.go @@ -40,7 +40,7 @@ var ( // among actual slaves in the topology. type SlaveConnection struct { *mysql.Conn - cp *mysql.ConnParams + cp dbconfigs.Connector slaveID uint32 cancel context.CancelFunc wg sync.WaitGroup @@ -53,7 +53,7 @@ type SlaveConnection struct { // 1) No other processes are making fake slave connections to our mysqld. // 2) No real slave servers will have IDs in the range 1-N where N is the peak // number of concurrent fake slave connections we will ever make. -func NewSlaveConnection(cp *mysql.ConnParams) (*SlaveConnection, error) { +func NewSlaveConnection(cp dbconfigs.Connector) (*SlaveConnection, error) { conn, err := connectForReplication(cp) if err != nil { return nil, err @@ -69,18 +69,12 @@ func NewSlaveConnection(cp *mysql.ConnParams) (*SlaveConnection, error) { } // connectForReplication create a MySQL connection ready to use for replication. -func connectForReplication(cp *mysql.ConnParams) (*mysql.Conn, error) { - params, err := dbconfigs.WithCredentials(cp) - if err != nil { - return nil, err - } - +func connectForReplication(cp dbconfigs.Connector) (*mysql.Conn, error) { ctx := context.Background() - conn, err := mysql.Connect(ctx, params) + conn, err := cp.Connect(ctx) if err != nil { return nil, err } - // Tell the server that we understand the format of events // that will be used if binlog_checksum is enabled on the server. if _, err := conn.ExecuteFetch("SET @master_binlog_checksum=@@global.binlog_checksum", 0, false); err != nil { diff --git a/go/vt/binlog/updatestreamctl.go b/go/vt/binlog/updatestreamctl.go index 142324fd298..ff331d89a33 100644 --- a/go/vt/binlog/updatestreamctl.go +++ b/go/vt/binlog/updatestreamctl.go @@ -26,6 +26,7 @@ import ( "vitess.io/vitess/go/stats" "vitess.io/vitess/go/sync2" "vitess.io/vitess/go/tb" + "vitess.io/vitess/go/vt/dbconfigs" "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/vttablet/tabletserver/schema" @@ -108,7 +109,7 @@ type UpdateStreamImpl struct { ts *topo.Server keyspace string cell string - cp *mysql.ConnParams + cp dbconfigs.Connector se *schema.Engine // actionLock protects the following variables @@ -169,7 +170,7 @@ type RegisterUpdateStreamServiceFunc func(UpdateStream) var RegisterUpdateStreamServices []RegisterUpdateStreamServiceFunc // NewUpdateStream returns a new UpdateStreamImpl object -func NewUpdateStream(ts *topo.Server, keyspace string, cell string, cp *mysql.ConnParams, se *schema.Engine) *UpdateStreamImpl { +func NewUpdateStream(ts *topo.Server, keyspace string, cell string, cp dbconfigs.Connector, se *schema.Engine) *UpdateStreamImpl { return &UpdateStreamImpl{ ts: ts, keyspace: keyspace, @@ -210,7 +211,7 @@ func (updateStream *UpdateStreamImpl) Enable() { updateStream.state.Set(usEnabled) updateStream.streams.Init() - log.Infof("Enabling update stream, dbname: %s", updateStream.cp.DbName) + log.Infof("Enabling update stream, dbname: %s", updateStream.cp.DBName()) } // Disable will disallow any connection to the service diff --git a/go/vt/dbconfigs/credentials.go b/go/vt/dbconfigs/credentials.go index f437879e4b9..026c9bafd6b 100644 --- a/go/vt/dbconfigs/credentials.go +++ b/go/vt/dbconfigs/credentials.go @@ -113,7 +113,7 @@ func (fcs *FileCredentialsServer) GetUserAndPassword(user string) (string, strin // WithCredentials returns a copy of the provided ConnParams that we can use // to connect, after going through the CredentialsServer. -func WithCredentials(cp *mysql.ConnParams) (*mysql.ConnParams, error) { +func withCredentials(cp *mysql.ConnParams) (*mysql.ConnParams, error) { result := *cp user, passwd, err := GetCredentialsServer().GetUserAndPassword(cp.Uname) switch err { diff --git a/go/vt/dbconfigs/dbconfigs.go b/go/vt/dbconfigs/dbconfigs.go index fc39c4011d4..31ccc90aa7d 100644 --- a/go/vt/dbconfigs/dbconfigs.go +++ b/go/vt/dbconfigs/dbconfigs.go @@ -21,6 +21,7 @@ limitations under the License. package dbconfigs import ( + "context" "encoding/json" "flag" "fmt" @@ -69,14 +70,15 @@ const ( // AllPrivs user should have more privileges than App (should include possibility to do // schema changes and write to internal Vitess tables), but it shouldn't have SUPER // privilege like Dba has. - AllPrivs = "allprivs" - Dba = "dba" - Filtered = "filtered" - Repl = "repl" + AllPrivs = "allprivs" + Dba = "dba" + Filtered = "filtered" + Repl = "repl" + ExternalRepl = "erepl" ) // All can be used to register all flags: RegisterFlags(All...) -var All = []string{App, AppDebug, AllPrivs, Dba, Filtered, Repl} +var All = []string{App, AppDebug, AllPrivs, Dba, Filtered, Repl, ExternalRepl} // RegisterFlags registers the flags for the given DBConfigFlag. // For instance, vttablet will register client, dba and repl. @@ -102,7 +104,7 @@ func registerBaseFlags() { flag.StringVar(&baseConfig.SslCert, "db_ssl_cert", "", "connection ssl certificate") flag.StringVar(&baseConfig.SslKey, "db_ssl_key", "", "connection ssl key") flag.StringVar(&baseConfig.ServerName, "db_server_name", "", "server name of the DB we are connecting to.") - + flag.Uint64Var(&baseConfig.ConnectTimeoutMs, "db_connect_timeout_ms", 0, "connection timeout to mysqld in milliseconds (0 for no timeout)") } // The flags will change the global singleton @@ -128,57 +130,127 @@ func registerPerUserFlags(dbc *userConfig, userKey string) { flag.StringVar(&dbc.param.SslCert, "db-config-"+userKey+"-ssl-cert", "", "deprecated: use db_ssl_cert") flag.StringVar(&dbc.param.SslKey, "db-config-"+userKey+"-ssl-key", "", "deprecated: use db_ssl_key") flag.StringVar(&dbc.param.ServerName, "db-config-"+userKey+"-server_name", "", "deprecated: use db_server_name") + flag.StringVar(&dbc.param.Flavor, "db-config-"+userKey+"-flavor", "", "deprecated: use db_flavor") flag.StringVar(&dbc.param.DeprecatedDBName, "db-config-"+userKey+"-dbname", "", "deprecated: dbname does not need to be explicitly configured") } +// Connector contains Connection Parameters for mysql connection +type Connector struct { + connParams *mysql.ConnParams + dbName string + host string +} + +// New initializes a ConnParams from mysql connection parameters +func New(mcp *mysql.ConnParams) Connector { + return Connector{ + connParams: mcp, + } +} + +// Connect will invoke the mysql.connect method and return a connection +func (c Connector) Connect(ctx context.Context) (*mysql.Conn, error) { + params, err := c.MysqlParams() + if err != nil { + return nil, err + } + conn, err := mysql.Connect(ctx, params) + if err != nil { + return nil, err + } + return conn, nil +} + +// MysqlParams returns the connections params +func (c Connector) MysqlParams() (*mysql.ConnParams, error) { + params, err := withCredentials(c.connParams) + if err != nil { + return nil, err + } + return params, nil +} + +// DBName gets the dbname from mysql.ConnParams +func (c Connector) DBName() string { + params, _ := c.MysqlParams() + return params.DbName +} + +// Host gets the host from mysql.ConnParams +func (c Connector) Host() string { + params, _ := c.MysqlParams() + return params.Host +} + // AppWithDB returns connection parameters for app with dbname set. -func (dbcfgs *DBConfigs) AppWithDB() *mysql.ConnParams { +func (dbcfgs *DBConfigs) AppWithDB() Connector { return dbcfgs.makeParams(App, true) } // AppDebugWithDB returns connection parameters for appdebug with dbname set. -func (dbcfgs *DBConfigs) AppDebugWithDB() *mysql.ConnParams { +func (dbcfgs *DBConfigs) AppDebugWithDB() Connector { return dbcfgs.makeParams(AppDebug, true) } // AllPrivsWithDB returns connection parameters for appdebug with dbname set. -func (dbcfgs *DBConfigs) AllPrivsWithDB() *mysql.ConnParams { +func (dbcfgs *DBConfigs) AllPrivsWithDB() Connector { return dbcfgs.makeParams(AllPrivs, true) } // Dba returns connection parameters for dba with no dbname set. -func (dbcfgs *DBConfigs) Dba() *mysql.ConnParams { +func (dbcfgs *DBConfigs) Dba() Connector { return dbcfgs.makeParams(Dba, false) } // DbaWithDB returns connection parameters for appdebug with dbname set. -func (dbcfgs *DBConfigs) DbaWithDB() *mysql.ConnParams { +func (dbcfgs *DBConfigs) DbaWithDB() Connector { return dbcfgs.makeParams(Dba, true) } -// FilteredWithDB returns connection parameters for appdebug with dbname set. -func (dbcfgs *DBConfigs) FilteredWithDB() *mysql.ConnParams { +// FilteredWithDB returns connection parameters for filtered with dbname set. +func (dbcfgs *DBConfigs) FilteredWithDB() Connector { return dbcfgs.makeParams(Filtered, true) } -// Repl returns connection parameters for appdebug with no dbname set. -func (dbcfgs *DBConfigs) Repl() *mysql.ConnParams { +// Repl returns connection parameters for repl with no dbname set. +func (dbcfgs *DBConfigs) Repl() Connector { return dbcfgs.makeParams(Repl, false) } +// ExternalRepl returns connection parameters for repl with no dbname set. +func (dbcfgs *DBConfigs) ExternalRepl() Connector { + return dbcfgs.makeParams(ExternalRepl, true) +} + +// ExternalReplWithDB returns connection parameters for repl with dbname set. +func (dbcfgs *DBConfigs) ExternalReplWithDB() Connector { + params := dbcfgs.makeParams(ExternalRepl, true) + // TODO @rafael: This is a hack to allows to configure external databases by providing + // db-config-erepl-dbname. + if params.connParams.DeprecatedDBName != "" { + params.connParams.DbName = params.connParams.DeprecatedDBName + return params + } + return params +} + // AppWithDB returns connection parameters for app with dbname set. -func (dbcfgs *DBConfigs) makeParams(userKey string, withDB bool) *mysql.ConnParams { +func (dbcfgs *DBConfigs) makeParams(userKey string, withDB bool) Connector { orig := dbcfgs.userConfigs[userKey] if orig == nil { - return &mysql.ConnParams{} + return Connector{ + connParams: &mysql.ConnParams{}, + } } result := orig.param if withDB { result.DbName = dbcfgs.DBName.Get() } - return &result + return Connector{ + connParams: &result, + } } // IsZero returns true if DBConfigs was uninitialized. @@ -238,8 +310,13 @@ func HasConnectionParams() bool { // is used to initialize the per-user conn params. func Init(defaultSocketFile string) (*DBConfigs, error) { // The new base configs, if set, supersede legacy settings. - for _, uc := range dbConfigs.userConfigs { - if HasConnectionParams() { + for user, uc := range dbConfigs.userConfigs { + // TODO @rafael: For ExternalRepl we need to respect the provided host / port + // At the moment this is an snowflake user connection type that it used by + // vreplication to connect to external mysql hosts that are not part of a vitess + // cluster. In the future we need to refactor all dbconfig to support custom users + // in a more flexible way. + if HasConnectionParams() && user != ExternalRepl { uc.param.Host = baseConfig.Host uc.param.Port = baseConfig.Port uc.param.UnixSocket = baseConfig.UnixSocket @@ -253,7 +330,9 @@ func Init(defaultSocketFile string) (*DBConfigs, error) { if baseConfig.Flags != 0 { uc.param.Flags = baseConfig.Flags } - uc.param.Flavor = baseConfig.Flavor + if user != ExternalRepl { + uc.param.Flavor = baseConfig.Flavor + } if uc.useSSL { uc.param.SslCa = baseConfig.SslCa uc.param.SslCaPath = baseConfig.SslCaPath @@ -261,12 +340,13 @@ func Init(defaultSocketFile string) (*DBConfigs, error) { uc.param.SslKey = baseConfig.SslKey uc.param.ServerName = baseConfig.ServerName } + uc.param.ConnectTimeoutMs = baseConfig.ConnectTimeoutMs } // See if the CredentialsServer is working. We do not use the // result for anything, this is just a check. for _, uc := range dbConfigs.userConfigs { - if _, err := WithCredentials(&uc.param); err != nil { + if _, err := withCredentials(&uc.param); err != nil { return nil, fmt.Errorf("dbconfig cannot be initialized: %v", err) } // Check for only one. @@ -282,12 +362,13 @@ func Init(defaultSocketFile string) (*DBConfigs, error) { func NewTestDBConfigs(genParams, appDebugParams mysql.ConnParams, dbName string) *DBConfigs { dbcfgs := &DBConfigs{ userConfigs: map[string]*userConfig{ - App: {param: genParams}, - AppDebug: {param: appDebugParams}, - AllPrivs: {param: genParams}, - Dba: {param: genParams}, - Filtered: {param: genParams}, - Repl: {param: genParams}, + App: {param: genParams}, + AppDebug: {param: appDebugParams}, + AllPrivs: {param: genParams}, + Dba: {param: genParams}, + Filtered: {param: genParams}, + Repl: {param: genParams}, + ExternalRepl: {param: genParams}, }, } dbcfgs.DBName.Set(dbName) diff --git a/go/vt/dbconfigs/dbconfigs_test.go b/go/vt/dbconfigs/dbconfigs_test.go index d20b50539f8..323da7eceee 100644 --- a/go/vt/dbconfigs/dbconfigs_test.go +++ b/go/vt/dbconfigs/dbconfigs_test.go @@ -261,6 +261,60 @@ func TestInit(t *testing.T) { } } +func TestInitTimeout(t *testing.T) { + f := saveDBConfigs() + defer f() + + baseConfig = mysql.ConnParams{ + Host: "a", + Port: 1, + Uname: "b", + Pass: "c", + DbName: "d", + UnixSocket: "e", + Charset: "f", + Flags: 2, + Flavor: "flavor", + ConnectTimeoutMs: 250, + } + dbConfigs = DBConfigs{ + userConfigs: map[string]*userConfig{ + App: { + param: mysql.ConnParams{ + Uname: "app", + Pass: "apppass", + }, + }, + }, + } + + dbc, err := Init("default") + if err != nil { + t.Fatal(err) + } + want := &DBConfigs{ + userConfigs: map[string]*userConfig{ + App: { + param: mysql.ConnParams{ + Host: "a", + Port: 1, + Uname: "app", + Pass: "apppass", + UnixSocket: "e", + Charset: "f", + Flags: 2, + Flavor: "flavor", + ConnectTimeoutMs: 250, + }, + }, + }, + } + + if !reflect.DeepEqual(dbc.userConfigs[App].param, want.userConfigs[App].param) { + t.Errorf("dbc: \n%#v, want \n%#v", dbc.userConfigs[App].param, want.userConfigs[App].param) + } +} + func TestAccessors(t *testing.T) { dbc := &DBConfigs{ userConfigs: map[string]*userConfig{ @@ -273,25 +327,25 @@ func TestAccessors(t *testing.T) { }, } dbc.DBName.Set("db") - if got, want := dbc.AppWithDB().DbName, "db"; got != want { + if got, want := dbc.AppWithDB().connParams.DbName, "db"; got != want { t.Errorf("dbc.AppWithDB().DbName: %v, want %v", got, want) } - if got, want := dbc.AllPrivsWithDB().DbName, "db"; got != want { + if got, want := dbc.AllPrivsWithDB().connParams.DbName, "db"; got != want { t.Errorf("dbc.AllPrivsWithDB().DbName: %v, want %v", got, want) } - if got, want := dbc.AppDebugWithDB().DbName, "db"; got != want { + if got, want := dbc.AppDebugWithDB().connParams.DbName, "db"; got != want { t.Errorf("dbc.AppDebugWithDB().DbName: %v, want %v", got, want) } - if got, want := dbc.Dba().DbName, ""; got != want { + if got, want := dbc.Dba().connParams.DbName, ""; got != want { t.Errorf("dbc.Dba().DbName: %v, want %v", got, want) } - if got, want := dbc.DbaWithDB().DbName, "db"; got != want { + if got, want := dbc.DbaWithDB().connParams.DbName, "db"; got != want { t.Errorf("dbc.DbaWithDB().DbName: %v, want %v", got, want) } - if got, want := dbc.FilteredWithDB().DbName, "db"; got != want { + if got, want := dbc.FilteredWithDB().connParams.DbName, "db"; got != want { t.Errorf("dbc.FilteredWithDB().DbName: %v, want %v", got, want) } - if got, want := dbc.Repl().DbName, ""; got != want { + if got, want := dbc.Repl().connParams.DbName, ""; got != want { t.Errorf("dbc.Repl().DbName: %v, want %v", got, want) } } diff --git a/go/vt/dbconnpool/connection.go b/go/vt/dbconnpool/connection.go index 294a7319233..bf4de535c10 100644 --- a/go/vt/dbconnpool/connection.go +++ b/go/vt/dbconnpool/connection.go @@ -17,11 +17,10 @@ limitations under the License. package dbconnpool import ( + "context" "fmt" "time" - "golang.org/x/net/context" - "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/stats" @@ -116,15 +115,21 @@ func (dbc *DBConnection) ExecuteStreamFetch(query string, callback func(*sqltype // NewDBConnection returns a new DBConnection based on the ConnParams // and will use the provided stats to collect timing. -func NewDBConnection(info *mysql.ConnParams, mysqlStats *stats.Timings) (*DBConnection, error) { +func NewDBConnection(info dbconfigs.Connector, mysqlStats *stats.Timings) (*DBConnection, error) { start := time.Now() defer mysqlStats.Record("Connect", start) - params, err := dbconfigs.WithCredentials(info) + + ctx := context.Background() + params, err := info.MysqlParams() if err != nil { return nil, err } - ctx := context.Background() - c, err := mysql.Connect(ctx, params) + if params.ConnectTimeoutMs != 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, time.Duration(params.ConnectTimeoutMs)*time.Millisecond) + defer cancel() + } + c, err := info.Connect(ctx) if err != nil { mysqlStats.Record("ConnectError", start) } diff --git a/go/vt/dbconnpool/connection_pool.go b/go/vt/dbconnpool/connection_pool.go index 472f4942cde..76520467665 100644 --- a/go/vt/dbconnpool/connection_pool.go +++ b/go/vt/dbconnpool/connection_pool.go @@ -29,9 +29,9 @@ import ( "golang.org/x/net/context" - "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/pools" "vitess.io/vitess/go/stats" + "vitess.io/vitess/go/vt/dbconfigs" "vitess.io/vitess/go/vt/log" ) @@ -56,7 +56,7 @@ type ConnectionPool struct { resolutionFrequency time.Duration // info and mysqlStats are set at Open() time - info *mysql.ConnParams + info dbconfigs.Connector addresses []net.IP ticker *time.Ticker @@ -97,7 +97,7 @@ func (cp *ConnectionPool) pool() (p *pools.ResourcePool) { func (cp *ConnectionPool) refreshdns() { cp.mu.Lock() - host := cp.info.Host + host := cp.info.Host() cp.mu.Unlock() addrs, err := net.LookupHost(host) @@ -141,14 +141,14 @@ func (cp *ConnectionPool) validAddress(addr net.IP) bool { // ... // conn, err := pool.Get() // ... -func (cp *ConnectionPool) Open(info *mysql.ConnParams, mysqlStats *stats.Timings) { +func (cp *ConnectionPool) Open(info dbconfigs.Connector, mysqlStats *stats.Timings) { cp.mu.Lock() defer cp.mu.Unlock() cp.info = info cp.mysqlStats = mysqlStats cp.connections = pools.NewResourcePool(cp.connect, cp.capacity, cp.capacity, cp.idleTimeout, 0) // Check if we need to resolve a hostname (The Host is not just an IP address). - if cp.resolutionFrequency > 0 && net.ParseIP(info.Host) == nil { + if cp.resolutionFrequency > 0 && net.ParseIP(info.Host()) == nil { cp.hostIsNotIP = true cp.ticker = time.NewTicker(cp.resolutionFrequency) cp.stop = make(chan struct{}) diff --git a/go/vt/discovery/healthcheck_test.go b/go/vt/discovery/healthcheck_flaky_test.go similarity index 100% rename from go/vt/discovery/healthcheck_test.go rename to go/vt/discovery/healthcheck_flaky_test.go diff --git a/go/vt/discovery/tablet_stats_cache.go b/go/vt/discovery/tablet_stats_cache.go index 92208266e1c..14771e7aec9 100644 --- a/go/vt/discovery/tablet_stats_cache.go +++ b/go/vt/discovery/tablet_stats_cache.go @@ -17,7 +17,6 @@ limitations under the License. package discovery import ( - "math" "sync" "golang.org/x/net/context" @@ -27,7 +26,6 @@ import ( "vitess.io/vitess/go/vt/srvtopo" "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/topo/topoproto" - "vitess.io/vitess/go/vt/topotools" ) // TabletStatsCache is a HealthCheckStatsListener that keeps both the @@ -47,8 +45,6 @@ type TabletStatsCache struct { cell string // ts is the topo server in use. ts *topo.Server - // aggregatesChan is used to send notifications to listeners. - aggregatesChan chan []*srvtopo.TargetStatsEntry // mu protects the following fields. It does not protect individual // entries in the entries map. mu sync.RWMutex @@ -70,8 +66,6 @@ type tabletStatsCacheEntry struct { all map[string]*TabletStats // healthy only has the healthy ones. healthy []*TabletStats - // aggregates has the per-alias aggregates. - aggregates map[string]*querypb.AggregateStats } func (e *tabletStatsCacheEntry) updateHealthyMapForMaster(ts *TabletStats) { @@ -131,12 +125,11 @@ func NewTabletStatsCacheDoNotSetListener(ts *topo.Server, cell string) *TabletSt func newTabletStatsCache(hc HealthCheck, ts *topo.Server, cell string, setListener bool) *TabletStatsCache { tc := &TabletStatsCache{ - cell: cell, - ts: ts, - aggregatesChan: make(chan []*srvtopo.TargetStatsEntry, 100), - entries: make(map[string]map[string]map[topodatapb.TabletType]*tabletStatsCacheEntry), - tsm: srvtopo.NewTargetStatsMultiplexer(), - cellAliases: make(map[string]string), + cell: cell, + ts: ts, + entries: make(map[string]map[string]map[topodatapb.TabletType]*tabletStatsCacheEntry), + tsm: srvtopo.NewTargetStatsMultiplexer(), + cellAliases: make(map[string]string), } if setListener { @@ -188,8 +181,7 @@ func (tc *TabletStatsCache) getOrCreateEntry(target *querypb.Target) *tabletStat e, ok := t[target.TabletType] if !ok { e = &tabletStatsCacheEntry{ - all: make(map[string]*TabletStats), - aggregates: make(map[string]*querypb.AggregateStats), + all: make(map[string]*TabletStats), } t[target.TabletType] = e } @@ -258,9 +250,6 @@ func (tc *TabletStatsCache) StatsUpdate(ts *TabletStats) { // The healthy list is different for TabletType_MASTER: we // only keep the most recent one. e.updateHealthyMapForMaster(ts) - for _, s := range e.all { - allArray = append(allArray, s) - } } else { // For non-master, if it is a trivial update, // we just skip everything else. We don't even update the @@ -276,45 +265,6 @@ func (tc *TabletStatsCache) StatsUpdate(ts *TabletStats) { } e.healthy = FilterByReplicationLag(allArray) } - - tc.updateAggregateMap(ts.Target.Keyspace, ts.Target.Shard, ts.Target.TabletType, e, allArray) -} - -// makeAggregateMap takes a list of TabletStats and builds a per-alias -// AggregateStats map. -func (tc *TabletStatsCache) makeAggregateMap(stats []*TabletStats) map[string]*querypb.AggregateStats { - result := make(map[string]*querypb.AggregateStats) - for _, ts := range stats { - alias := tc.getAliasByCell(ts.Tablet.Alias.Cell) - agg, ok := result[alias] - if !ok { - agg = &querypb.AggregateStats{ - SecondsBehindMasterMin: math.MaxUint32, - } - result[alias] = agg - } - - if ts.Serving && ts.LastError == nil { - agg.HealthyTabletCount++ - if ts.Stats.SecondsBehindMaster < agg.SecondsBehindMasterMin { - agg.SecondsBehindMasterMin = ts.Stats.SecondsBehindMaster - } - if ts.Stats.SecondsBehindMaster > agg.SecondsBehindMasterMax { - agg.SecondsBehindMasterMax = ts.Stats.SecondsBehindMaster - } - } else { - agg.UnhealthyTabletCount++ - } - } - return result -} - -// updateAggregateMap will update the aggregate map for the -// tabletStatsCacheEntry. It may broadcast the changes too if we have listeners. -// e.mu needs to be locked. -func (tc *TabletStatsCache) updateAggregateMap(keyspace, shard string, tabletType topodatapb.TabletType, e *tabletStatsCacheEntry, stats []*TabletStats) { - // Save the new value - e.aggregates = tc.makeAggregateMap(stats) } // GetTabletStats returns the full list of available targets. @@ -361,53 +311,5 @@ func (tc *TabletStatsCache) ResetForTesting() { tc.entries = make(map[string]map[string]map[topodatapb.TabletType]*tabletStatsCacheEntry) } -// GetAggregateStats is part of the TargetStatsListener interface. -func (tc *TabletStatsCache) GetAggregateStats(target *querypb.Target) (*querypb.AggregateStats, error) { - e := tc.getEntry(target.Keyspace, target.Shard, target.TabletType) - if e == nil { - return nil, topo.NewError(topo.NoNode, topotools.TargetIdent(target)) - } - - e.mu.RLock() - defer e.mu.RUnlock() - if target.TabletType == topodatapb.TabletType_MASTER { - if len(e.aggregates) == 0 { - return nil, topo.NewError(topo.NoNode, topotools.TargetIdent(target)) - } - for _, agg := range e.aggregates { - return agg, nil - } - } - targetAlias := tc.getAliasByCell(target.Cell) - agg, ok := e.aggregates[targetAlias] - if !ok { - return nil, topo.NewError(topo.NoNode, topotools.TargetIdent(target)) - } - return agg, nil -} - -// GetMasterCell is part of the TargetStatsListener interface. -func (tc *TabletStatsCache) GetMasterCell(keyspace, shard string) (cell string, err error) { - e := tc.getEntry(keyspace, shard, topodatapb.TabletType_MASTER) - if e == nil { - return "", topo.NewError(topo.NoNode, topotools.TargetIdent(&querypb.Target{ - Keyspace: keyspace, - Shard: shard, - TabletType: topodatapb.TabletType_MASTER, - })) - } - - e.mu.RLock() - defer e.mu.RUnlock() - for cell := range e.aggregates { - return cell, nil - } - return "", topo.NewError(topo.NoNode, topotools.TargetIdent(&querypb.Target{ - Keyspace: keyspace, - Shard: shard, - TabletType: topodatapb.TabletType_MASTER, - })) -} - // Compile-time interface check. var _ HealthCheckStatsListener = (*TabletStatsCache)(nil) diff --git a/go/vt/discovery/topology_watcher.go b/go/vt/discovery/topology_watcher.go index fdf14f11a19..b623457663c 100644 --- a/go/vt/discovery/topology_watcher.go +++ b/go/vt/discovery/topology_watcher.go @@ -437,3 +437,59 @@ func (fbs *FilterByShard) isIncluded(tablet *topodatapb.Tablet) bool { } return false } + +// FilterByKeyspace is a TabletRecorder filter that filters tablets by +// keyspace +type FilterByKeyspace struct { + tr TabletRecorder + + keyspaces map[string]bool +} + +// NewFilterByKeyspace creates a new FilterByKeyspace on top of an existing +// TabletRecorder. Each filter is a keyspace entry. All tablets that match +// a keyspace will be forwarded to the underlying TabletRecorder. +func NewFilterByKeyspace(tr TabletRecorder, selectedKeyspaces []string) *FilterByKeyspace { + m := make(map[string]bool) + for _, keyspace := range selectedKeyspaces { + m[keyspace] = true + } + + return &FilterByKeyspace{ + tr: tr, + keyspaces: m, + } +} + +// AddTablet is part of the TabletRecorder interface. +func (fbk *FilterByKeyspace) AddTablet(tablet *topodatapb.Tablet, name string) { + if fbk.isIncluded(tablet) { + fbk.tr.AddTablet(tablet, name) + } +} + +// RemoveTablet is part of the TabletRecorder interface. +func (fbk *FilterByKeyspace) RemoveTablet(tablet *topodatapb.Tablet) { + if fbk.isIncluded(tablet) { + fbk.tr.RemoveTablet(tablet) + } +} + +// ReplaceTablet is part of the TabletRecorder interface. +func (fbk *FilterByKeyspace) ReplaceTablet(old *topodatapb.Tablet, new *topodatapb.Tablet, name string) { + if old.Keyspace != new.Keyspace { + log.Errorf("Error replacing old tablet in %v with new tablet in %v", old.Keyspace, new.Keyspace) + return + } + + if fbk.isIncluded(new) { + fbk.tr.ReplaceTablet(old, new, name) + } +} + +// isIncluded returns true if the tablet's keyspace should be +// forwarded to the underlying TabletRecorder. +func (fbk *FilterByKeyspace) isIncluded(tablet *topodatapb.Tablet) bool { + _, exist := fbk.keyspaces[tablet.Keyspace] + return exist +} diff --git a/go/vt/discovery/topology_watcher_test.go b/go/vt/discovery/topology_watcher_test.go index c3cd553699a..02c664fa15b 100644 --- a/go/vt/discovery/topology_watcher_test.go +++ b/go/vt/discovery/topology_watcher_test.go @@ -17,6 +17,7 @@ limitations under the License. package discovery import ( + "math/rand" "testing" "time" @@ -410,3 +411,97 @@ func TestFilterByShard(t *testing.T) { } } } + +var ( + testFilterByKeyspace = []struct { + keyspace string + expected bool + }{ + {"ks1", true}, + {"ks2", true}, + {"ks3", false}, + {"ks4", true}, + {"ks5", true}, + {"ks6", false}, + {"ks7", false}, + } + testKeyspacesToWatch = []string{"ks1", "ks2", "ks4", "ks5"} + testCell = "testCell" + testShard = "testShard" + testHostName = "testHostName" +) + +func TestFilterByKeyspace(t *testing.T) { + hc := NewFakeHealthCheck() + tr := NewFilterByKeyspace(hc, testKeyspacesToWatch) + ts := memorytopo.NewServer(testCell) + tw := NewCellTabletsWatcher(context.Background(), ts, tr, testCell, 10*time.Minute, true, 5) + + for _, test := range testFilterByKeyspace { + // Add a new tablet to the topology. + port := rand.Int31n(1000) + tablet := &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: testCell, + Uid: rand.Uint32(), + }, + Hostname: testHostName, + PortMap: map[string]int32{ + "vt": port, + }, + Keyspace: test.keyspace, + Shard: testShard, + } + + got := tr.isIncluded(tablet) + if got != test.expected { + t.Errorf("isIncluded(%v) for keyspace %v returned %v but expected %v", test.keyspace, test.keyspace, got, test.expected) + } + + if err := ts.CreateTablet(context.Background(), tablet); err != nil { + t.Errorf("CreateTablet failed: %v", err) + } + + tw.loadTablets() + key := TabletToMapKey(tablet) + allTablets := hc.GetAllTablets() + + if _, ok := allTablets[key]; ok != test.expected && proto.Equal(allTablets[key], tablet) != test.expected { + t.Errorf("Error adding tablet - got %v; want %v", ok, test.expected) + } + + // Replace the tablet we added above + tabletReplacement := &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: testCell, + Uid: rand.Uint32(), + }, + Hostname: testHostName, + PortMap: map[string]int32{ + "vt": port, + }, + Keyspace: test.keyspace, + Shard: testShard, + } + got = tr.isIncluded(tabletReplacement) + if got != test.expected { + t.Errorf("isIncluded(%v) for keyspace %v returned %v but expected %v", test.keyspace, test.keyspace, got, test.expected) + } + if err := ts.CreateTablet(context.Background(), tabletReplacement); err != nil { + t.Errorf("CreateTablet failed: %v", err) + } + + tw.loadTablets() + key = TabletToMapKey(tabletReplacement) + allTablets = hc.GetAllTablets() + + if _, ok := allTablets[key]; ok != test.expected && proto.Equal(allTablets[key], tabletReplacement) != test.expected { + t.Errorf("Error replacing tablet - got %v; want %v", ok, test.expected) + } + + // Delete the tablet + if err := ts.DeleteTablet(context.Background(), tabletReplacement.Alias); err != nil { + t.Fatalf("DeleteTablet failed: %v", err) + } + } +} diff --git a/go/vt/discovery/utils.go b/go/vt/discovery/utils.go index 07e4642fdf3..ac57b032ded 100644 --- a/go/vt/discovery/utils.go +++ b/go/vt/discovery/utils.go @@ -30,7 +30,7 @@ func RemoveUnhealthyTablets(tabletStatsList []TabletStats) []TabletStats { // source and destination, and the source is not serving (disabled by // TabletControl). When we switch the tablet to 'worker', it will // go back to serving state. - if ts.Stats == nil || ts.Stats.HealthError != "" || IsReplicationLagHigh(&ts) { + if ts.Stats == nil || ts.Stats.HealthError != "" || ts.LastError != nil || IsReplicationLagHigh(&ts) { continue } result = append(result, ts) diff --git a/go/vt/discovery/utils_test.go b/go/vt/discovery/utils_test.go index 488ea45e713..4a0266072c9 100644 --- a/go/vt/discovery/utils_test.go +++ b/go/vt/discovery/utils_test.go @@ -17,6 +17,7 @@ limitations under the License. package discovery import ( + "errors" "testing" querypb "vitess.io/vitess/go/vt/proto/query" @@ -28,38 +29,35 @@ func TestRemoveUnhealthyTablets(t *testing.T) { desc string input []TabletStats want []TabletStats - }{ - { - desc: "tablets missing Stats", - input: []TabletStats{replica(1), replica(2)}, - want: []TabletStats{}, - }, - { - desc: "all tablets healthy", - input: []TabletStats{healthy(replica(1)), healthy(replica(2))}, - want: []TabletStats{healthy(replica(1)), healthy(replica(2))}, - }, - { - desc: "one unhealthy tablet (error)", - input: []TabletStats{healthy(replica(1)), unhealthyError(replica(2))}, - want: []TabletStats{healthy(replica(1))}, - }, - { - desc: "one unhealthy tablet (lag)", - input: []TabletStats{healthy(replica(1)), unhealthyLag(replica(2))}, - want: []TabletStats{healthy(replica(1))}, - }, - { - desc: "no filtering by tablet type", - input: []TabletStats{healthy(master(1)), healthy(replica(2)), healthy(rdonly(3))}, - want: []TabletStats{healthy(master(1)), healthy(replica(2)), healthy(rdonly(3))}, - }, - { - desc: "non-serving tablets won't be removed", - input: []TabletStats{notServing(healthy(replica(1)))}, - want: []TabletStats{notServing(healthy(replica(1)))}, - }, - } + }{{ + desc: "tablets missing Stats", + input: []TabletStats{replica(1), replica(2)}, + want: []TabletStats{}, + }, { + desc: "all tablets healthy", + input: []TabletStats{healthy(replica(1)), healthy(replica(2))}, + want: []TabletStats{healthy(replica(1)), healthy(replica(2))}, + }, { + desc: "one unhealthy tablet (error)", + input: []TabletStats{healthy(replica(1)), unhealthyError(replica(2))}, + want: []TabletStats{healthy(replica(1))}, + }, { + desc: "one error tablet", + input: []TabletStats{healthy(replica(1)), unhealthyLastError(replica(2))}, + want: []TabletStats{healthy(replica(1))}, + }, { + desc: "one unhealthy tablet (lag)", + input: []TabletStats{healthy(replica(1)), unhealthyLag(replica(2))}, + want: []TabletStats{healthy(replica(1))}, + }, { + desc: "no filtering by tablet type", + input: []TabletStats{healthy(master(1)), healthy(replica(2)), healthy(rdonly(3))}, + want: []TabletStats{healthy(master(1)), healthy(replica(2)), healthy(rdonly(3))}, + }, { + desc: "non-serving tablets won't be removed", + input: []TabletStats{notServing(healthy(replica(1)))}, + want: []TabletStats{notServing(healthy(replica(1)))}, + }} for _, tc := range testcases { got := RemoveUnhealthyTablets(tc.input) @@ -123,6 +121,11 @@ func unhealthyError(ts TabletStats) TabletStats { return ts } +func unhealthyLastError(ts TabletStats) TabletStats { + ts.LastError = errors.New("err") + return ts +} + func notServing(ts TabletStats) TabletStats { ts.Serving = false return ts diff --git a/go/vt/dtids/dtids_test.go b/go/vt/dtids/dtids_test.go index e5a8fc86750..acb00bdfe84 100644 --- a/go/vt/dtids/dtids_test.go +++ b/go/vt/dtids/dtids_test.go @@ -20,6 +20,7 @@ import ( "testing" "github.com/golang/protobuf/proto" + "github.com/stretchr/testify/require" querypb "vitess.io/vitess/go/vt/proto/query" topodatapb "vitess.io/vitess/go/vt/proto/topodata" @@ -41,9 +42,7 @@ func TestDTID(t *testing.T) { t.Errorf("generateDTID: %s, want %s", dtid, want) } out, err := ShardSession(dtid) - if err != nil { - t.Error(err) - } + require.NoError(t, err) if !proto.Equal(in, out) { t.Errorf("ShardSession: %+v, want %+v", out, in) } @@ -61,9 +60,7 @@ func TestDTID(t *testing.T) { func TestTransactionID(t *testing.T) { out, err := TransactionID("aa:0:1") - if err != nil { - t.Error(err) - } + require.NoError(t, err) if out != 1 { t.Errorf("TransactionID(aa:0:1): %d, want 1", out) } diff --git a/go/vt/env/env.go b/go/vt/env/env.go index 49b462815be..70feb43186c 100644 --- a/go/vt/env/env.go +++ b/go/vt/env/env.go @@ -18,7 +18,9 @@ package env import ( "errors" + "fmt" "os" + "os/exec" "path" "path/filepath" "strings" @@ -27,6 +29,8 @@ import ( const ( // DefaultVtDataRoot is the default value for VTROOT environment variable DefaultVtDataRoot = "/vt" + // DefaultVtRoot is only required for hooks + DefaultVtRoot = "/usr/local/vitess" ) // VtRoot returns $VTROOT or tries to guess its value if it's not set. @@ -45,8 +49,7 @@ func VtRoot() (root string, err error) { if strings.HasSuffix(dir, "/bin") { return path.Dir(dir), nil } - err = errors.New("VTROOT could not be guessed from the executable location. Please set $VTROOT") - return + return DefaultVtRoot, nil } // VtDataRoot returns $VTDATAROOT or the default if $VTDATAROOT is not @@ -60,20 +63,26 @@ func VtDataRoot() string { return DefaultVtDataRoot } -// VtMysqlRoot returns the root for the mysql distribution, which -// contains bin/mysql CLI for instance. +// VtMysqlRoot returns the root for the mysql distribution, +// which contains bin/mysql CLI for instance. +// If it is not set, look for mysqld in the path. func VtMysqlRoot() (string, error) { // if the environment variable is set, use that if root := os.Getenv("VT_MYSQL_ROOT"); root != "" { return root, nil } - // otherwise let's use VTROOT - root, err := VtRoot() + // otherwise let's look for mysqld in the PATH. + // ensure that /usr/sbin is included, as it might not be by default + // This is the default location for mysqld from packages. + newPath := fmt.Sprintf("/usr/sbin:%s", os.Getenv("PATH")) + os.Setenv("PATH", newPath) + path, err := exec.LookPath("mysqld") if err != nil { - return "", errors.New("VT_MYSQL_ROOT is not set and could not be guessed from the executable location. Please set $VT_MYSQL_ROOT") + return "", errors.New("VT_MYSQL_ROOT is not set and no mysqld could be found in your PATH") } - return root, nil + path = filepath.Dir(filepath.Dir(path)) // strip mysqld, and the sbin + return path, nil } // VtMysqlBaseDir returns the Mysql base directory, which diff --git a/go/vt/grpcclient/client.go b/go/vt/grpcclient/client.go index 2dae863a9a9..a723d287ee0 100644 --- a/go/vt/grpcclient/client.go +++ b/go/vt/grpcclient/client.go @@ -20,6 +20,7 @@ package grpcclient import ( "flag" + "time" grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" @@ -27,16 +28,14 @@ import ( "google.golang.org/grpc/credentials" "google.golang.org/grpc/keepalive" "vitess.io/vitess/go/trace" - "vitess.io/vitess/go/vt/grpccommon" - "vitess.io/vitess/go/vt/vttls" - "vitess.io/vitess/go/vt/log" + "vitess.io/vitess/go/vt/vttls" ) var ( - keepaliveTime = flag.Duration("grpc_keepalive_time", 0, "After a duration of this time if the client doesn't see any activity it pings the server to see if the transport is still alive.") - keepaliveTimeout = flag.Duration("grpc_keepalive_timeout", 0, "After having pinged for keepalive check, the client waits for a duration of Timeout and if no activity is seen even after that the connection is closed.") + keepaliveTime = flag.Duration("grpc_keepalive_time", 10*time.Second, "After a duration of this time if the client doesn't see any activity it pings the server to see if the transport is still alive.") + keepaliveTimeout = flag.Duration("grpc_keepalive_timeout", 10*time.Second, "After having pinged for keepalive check, the client waits for a duration of Timeout and if no activity is seen even after that the connection is closed.") initialConnWindowSize = flag.Int("grpc_initial_conn_window_size", 0, "grpc initial connection window size") initialWindowSize = flag.Int("grpc_initial_window_size", 0, "grpc initial window size") ) diff --git a/go/vt/grpcclient/client_test.go b/go/vt/grpcclient/client_flaky_test.go similarity index 100% rename from go/vt/grpcclient/client_test.go rename to go/vt/grpcclient/client_flaky_test.go diff --git a/go/vt/key/key.go b/go/vt/key/key.go index b9ae9698403..0bd7f137a34 100644 --- a/go/vt/key/key.go +++ b/go/vt/key/key.go @@ -120,6 +120,21 @@ func EvenShardsKeyRange(i, n int) (*topodatapb.KeyRange, error) { return &topodatapb.KeyRange{Start: startBytes, End: endBytes}, nil } +// KeyRangeAdd adds two adjacent keyranges into a single value. +// If the values are not adjacent, it returns false. +func KeyRangeAdd(first, second *topodatapb.KeyRange) (*topodatapb.KeyRange, bool) { + if first == nil || second == nil { + return nil, false + } + if len(first.End) != 0 && bytes.Equal(first.End, second.Start) { + return &topodatapb.KeyRange{Start: first.Start, End: second.End}, true + } + if len(second.End) != 0 && bytes.Equal(second.End, first.Start) { + return &topodatapb.KeyRange{Start: second.Start, End: first.End}, true + } + return nil, false +} + // KeyRangeContains returns true if the provided id is in the keyrange. func KeyRangeContains(kr *topodatapb.KeyRange, id []byte) bool { if kr == nil { diff --git a/go/vt/key/key_test.go b/go/vt/key/key_test.go index 9d88ba19ea3..89bac6311fc 100644 --- a/go/vt/key/key_test.go +++ b/go/vt/key/key_test.go @@ -139,6 +139,107 @@ func TestEvenShardsKeyRange(t *testing.T) { } } +func TestKeyRangeAdd(t *testing.T) { + testcases := []struct { + first string + second string + out string + ok bool + }{{ + first: "", + second: "", + out: "", + ok: false, + }, { + first: "", + second: "-80", + out: "", + ok: false, + }, { + first: "-80", + second: "", + out: "", + ok: false, + }, { + first: "", + second: "80-", + out: "", + ok: false, + }, { + first: "80-", + second: "", + out: "", + ok: false, + }, { + first: "80-", + second: "-40", + out: "", + ok: false, + }, { + first: "-40", + second: "80-", + out: "", + ok: false, + }, { + first: "-80", + second: "80-", + out: "-", + ok: true, + }, { + first: "80-", + second: "-80", + out: "-", + ok: true, + }, { + first: "-40", + second: "40-80", + out: "-80", + ok: true, + }, { + first: "40-80", + second: "-40", + out: "-80", + ok: true, + }, { + first: "40-80", + second: "80-c0", + out: "40-c0", + ok: true, + }, { + first: "80-c0", + second: "40-80", + out: "40-c0", + ok: true, + }} + stringToKeyRange := func(spec string) *topodatapb.KeyRange { + if spec == "" { + return nil + } + parts := strings.Split(spec, "-") + if len(parts) != 2 { + panic("invalid spec") + } + kr, err := ParseKeyRangeParts(parts[0], parts[1]) + if err != nil { + panic(err) + } + return kr + } + keyRangeToString := func(kr *topodatapb.KeyRange) string { + if kr == nil { + return "" + } + return KeyRangeString(kr) + } + for _, tcase := range testcases { + first := stringToKeyRange(tcase.first) + second := stringToKeyRange(tcase.second) + out, ok := KeyRangeAdd(first, second) + assert.Equal(t, tcase.out, keyRangeToString(out)) + assert.Equal(t, tcase.ok, ok) + } +} + func TestEvenShardsKeyRange_Error(t *testing.T) { testCases := []struct { i, n int diff --git a/go/vt/logutil/logutil_test.go b/go/vt/logutil/logutil_flaky_test.go similarity index 100% rename from go/vt/logutil/logutil_test.go rename to go/vt/logutil/logutil_flaky_test.go diff --git a/go/vt/mysqlctl/azblobbackupstorage/azblob.go b/go/vt/mysqlctl/azblobbackupstorage/azblob.go new file mode 100644 index 00000000000..870605a9d2d --- /dev/null +++ b/go/vt/mysqlctl/azblobbackupstorage/azblob.go @@ -0,0 +1,330 @@ +/* +Copyright 2020 The Vitess Authors. + +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. +*/ + +// Package azblobbackupstorage implements the BackupStorage interface +// for Azure Blob Storage +package azblobbackupstorage + +import ( + "context" + "flag" + "fmt" + "io" + "io/ioutil" + "net/url" + "os" + "strings" + "sync" + "time" + + "github.com/Azure/azure-storage-blob-go/azblob" + "vitess.io/vitess/go/vt/concurrency" + "vitess.io/vitess/go/vt/log" + "vitess.io/vitess/go/vt/mysqlctl/backupstorage" +) + +var ( + // This is the account name + accountName = flag.String("azblob_backup_account_name", "", "Azure Storage Account name for backups; if this flag is unset, the environment variable VT_AZBLOB_ACCOUNT_NAME will be used") + + // This is the private access key + accountKeyFile = flag.String("azblob_backup_account_key_file", "", "Path to a file containing the Azure Storage account key; if this flag is unset, the environment variable VT_AZBLOB_ACCOUNT_KEY will be used as the key itself (NOT a file path)") + + // This is the name of the container that will store the backups + containerName = flag.String("azblob_backup_container_name", "", "Azure Blob Container Name") + + // This is an optional prefix to prepend to all files + storageRoot = flag.String("azblob_backup_storage_root", "", "Root prefix for all backup-related Azure Blobs; this should exclude both initial and trailing '/' (e.g. just 'a/b' not '/a/b/')") + + azBlobParallelism = flag.Int("azblob_backup_parallelism", 1, "Azure Blob operation parallelism (requires extra memory when increased)") +) + +const ( + defaultRetryCount = 5 + delimiter = "/" +) + +// Return a Shared credential from the available credential sources. +// We will use credentials in the following order +// 1. Direct Command Line Flag (azblob_backup_account_name, azblob_backup_account_key) +// 2. Environment variables +func azCredentials() (*azblob.SharedKeyCredential, error) { + actName := *accountName + if actName == "" { + // Check the Environmental Value + actName = os.Getenv("VT_AZBLOB_ACCOUNT_NAME") + } + + var actKey string + if *accountKeyFile != "" { + log.Infof("Getting Azure Storage Account key from file: %s", *accountKeyFile) + dat, err := ioutil.ReadFile(*accountKeyFile) + if err != nil { + return nil, err + } + actKey = string(dat) + } else { + actKey = os.Getenv("VT_AZBLOB_ACCOUNT_KEY") + } + + if actName == "" || actKey == "" { + return nil, fmt.Errorf("Azure Storage Account credentials not found in command-line flags or environment variables") + } + return azblob.NewSharedKeyCredential(actName, actKey) +} + +func azServiceURL(credentials *azblob.SharedKeyCredential) azblob.ServiceURL { + pipeline := azblob.NewPipeline(credentials, azblob.PipelineOptions{ + Retry: azblob.RetryOptions{ + Policy: azblob.RetryPolicyFixed, + MaxTries: defaultRetryCount, + // Per https://godoc.org/github.com/Azure/azure-storage-blob-go/azblob#RetryOptions + // this should be set to a very nigh number (they claim 60s per MB). + // That could end up being days so we are limiting this to four hours. + TryTimeout: 4 * time.Hour, + }, + }) + u := url.URL{ + Scheme: "https", + Host: credentials.AccountName() + ".blob.core.windows.net", + Path: "/", + } + return azblob.NewServiceURL(u, pipeline) +} + +// AZBlobBackupHandle implements BackupHandle for Azure Blob service. +type AZBlobBackupHandle struct { + bs *AZBlobBackupStorage + dir string + name string + readOnly bool + waitGroup sync.WaitGroup + errors concurrency.AllErrorRecorder +} + +// Directory implements BackupHandle. +func (bh *AZBlobBackupHandle) Directory() string { + return bh.dir +} + +// Name implements BackupHandle. +func (bh *AZBlobBackupHandle) Name() string { + return bh.name +} + +// AddFile implements BackupHandle. +func (bh *AZBlobBackupHandle) AddFile(ctx context.Context, filename string, filesize int64) (io.WriteCloser, error) { + if bh.readOnly { + return nil, fmt.Errorf("AddFile cannot be called on read-only backup") + } + // Error out if the file size it too large ( ~4.75 TB) + if filesize > azblob.BlockBlobMaxStageBlockBytes*azblob.BlockBlobMaxBlocks { + return nil, fmt.Errorf("filesize (%v) is too large to upload to az blob (max size %v)", filesize, azblob.BlockBlobMaxStageBlockBytes*azblob.BlockBlobMaxBlocks) + } + + obj := objName(bh.dir, bh.name, filename) + containerURL, err := bh.bs.containerURL() + if err != nil { + return nil, err + } + + blockBlobURL := containerURL.NewBlockBlobURL(obj) + + reader, writer := io.Pipe() + bh.waitGroup.Add(1) + + go func() { + defer bh.waitGroup.Done() + _, err := azblob.UploadStreamToBlockBlob(ctx, reader, blockBlobURL, azblob.UploadStreamToBlockBlobOptions{ + BufferSize: azblob.BlockBlobMaxStageBlockBytes, + MaxBuffers: *azBlobParallelism, + }) + if err != nil { + reader.CloseWithError(err) + bh.errors.RecordError(err) + } + }() + + return writer, nil +} + +// EndBackup implements BackupHandle. +func (bh *AZBlobBackupHandle) EndBackup(ctx context.Context) error { + if bh.readOnly { + return fmt.Errorf("EndBackup cannot be called on read-only backup") + } + bh.waitGroup.Wait() + return bh.errors.Error() +} + +// AbortBackup implements BackupHandle. +func (bh *AZBlobBackupHandle) AbortBackup(ctx context.Context) error { + if bh.readOnly { + return fmt.Errorf("AbortBackup cannot be called on read-only backup") + } + return bh.bs.RemoveBackup(ctx, bh.dir, bh.name) +} + +// ReadFile implements BackupHandle. +func (bh *AZBlobBackupHandle) ReadFile(ctx context.Context, filename string) (io.ReadCloser, error) { + if !bh.readOnly { + return nil, fmt.Errorf("ReadFile cannot be called on read-write backup") + } + + obj := objName(bh.dir, filename) + containerURL, err := bh.bs.containerURL() + if err != nil { + return nil, err + } + blobURL := containerURL.NewBlobURL(obj) + + resp, err := blobURL.Download(ctx, 0, azblob.CountToEnd, azblob.BlobAccessConditions{}, false) + if err != nil { + return nil, err + } + return resp.Body(azblob.RetryReaderOptions{ + MaxRetryRequests: defaultRetryCount, + NotifyFailedRead: func(failureCount int, lastError error, offset int64, count int64, willRetry bool) { + log.Warningf("ReadFile: [azblob] container: %s, directory: %s, filename: %s, error: %v", *containerName, objName(bh.dir, ""), filename, lastError) + }, + TreatEarlyCloseAsError: true, + }), nil +} + +// AZBlobBackupStorage structs implements the BackupStorage interface for AZBlob +type AZBlobBackupStorage struct { +} + +func (bs *AZBlobBackupStorage) containerURL() (*azblob.ContainerURL, error) { + credentials, err := azCredentials() + if err != nil { + return nil, err + } + u := azServiceURL(credentials).NewContainerURL(*containerName) + return &u, nil +} + +// ListBackups implements BackupStorage. +func (bs *AZBlobBackupStorage) ListBackups(ctx context.Context, dir string) ([]backupstorage.BackupHandle, error) { + log.Infof("ListBackups: [azblob] container: %s, directory: %v", *containerName, objName(dir, "")) + + containerURL, err := bs.containerURL() + if err != nil { + return nil, err + } + + searchPrefix := objName(dir, "") + + result := make([]backupstorage.BackupHandle, 0) + var subdirs []string + + for marker := (azblob.Marker{}); marker.NotDone(); { + // This returns Blobs in sorted order so we don't need to sort them a second time. + resp, err := containerURL.ListBlobsHierarchySegment(ctx, marker, delimiter, azblob.ListBlobsSegmentOptions{ + Prefix: searchPrefix, + MaxResults: 0, + }) + + if err != nil { + return nil, err + } + + for _, item := range resp.Segment.BlobPrefixes { + subdir := strings.TrimPrefix(item.Name, searchPrefix) + subdir = strings.TrimSuffix(subdir, delimiter) + subdirs = append(subdirs, subdir) + } + + marker = resp.NextMarker + } + + for _, subdir := range subdirs { + result = append(result, &AZBlobBackupHandle{ + bs: bs, + dir: strings.Join([]string{dir, subdir}, "/"), + name: subdir, + readOnly: true, + }) + } + + return result, nil +} + +// StartBackup implements BackupStorage. +func (bs *AZBlobBackupStorage) StartBackup(ctx context.Context, dir, name string) (backupstorage.BackupHandle, error) { + return &AZBlobBackupHandle{ + bs: bs, + dir: dir, + name: name, + readOnly: false, + }, nil +} + +// RemoveBackup implements BackupStorage. +func (bs *AZBlobBackupStorage) RemoveBackup(ctx context.Context, dir, name string) error { + log.Infof("ListBackups: [azblob] container: %s, directory: %s", *containerName, objName(dir, "")) + + containerURL, err := bs.containerURL() + if err != nil { + return err + } + + searchPrefix := objName(dir, name, "") + + for marker := (azblob.Marker{}); marker.NotDone(); { + resp, err := containerURL.ListBlobsHierarchySegment(ctx, marker, delimiter, azblob.ListBlobsSegmentOptions{ + Prefix: searchPrefix, + MaxResults: 0, + }) + + if err != nil { + return err + } + + // Right now there is no batch delete so we must iterate over all the blobs to delete them one by one + // One day we will be able to use this https://docs.microsoft.com/en-us/rest/api/storageservices/blob-batch + // but currently it is listed as a preview and its not in the go API + for _, item := range resp.Segment.BlobItems { + _, err = containerURL.NewBlobURL(item.Name).Delete(ctx, azblob.DeleteSnapshotsOptionNone, azblob.BlobAccessConditions{}) + if err != nil { + return err + } + } + marker = resp.NextMarker + } + + return nil +} + +// Close implements BackupStorage. +func (bs *AZBlobBackupStorage) Close() error { + // This function is a No-op + return nil +} + +// objName joins path parts into an object name. +// Unlike path.Join, it doesn't collapse ".." or strip trailing slashes. +// It also adds the value of the -azblob_backup_storage_root flag if set. +func objName(parts ...string) string { + if *storageRoot != "" { + return *storageRoot + "/" + strings.Join(parts, "/") + } + return strings.Join(parts, "/") +} + +func init() { + backupstorage.BackupStorageMap["azblob"] = &AZBlobBackupStorage{} +} diff --git a/go/vt/mysqlctl/fakemysqldaemon/fakemysqldaemon.go b/go/vt/mysqlctl/fakemysqldaemon/fakemysqldaemon.go index 6759edebeb4..a73b5249e39 100644 --- a/go/vt/mysqlctl/fakemysqldaemon/fakemysqldaemon.go +++ b/go/vt/mysqlctl/fakemysqldaemon/fakemysqldaemon.go @@ -58,6 +58,10 @@ type FakeMysqlDaemon struct { // test owner responsibility to have these two match) Replicating bool + // SlaveIORunning is always true except in one testcase + // where we want to test error handling during SetMaster + SlaveIORunning bool + // CurrentMasterPosition is returned by MasterPosition // and SlaveStatus CurrentMasterPosition mysql.Position @@ -65,6 +69,9 @@ type FakeMysqlDaemon struct { // SlaveStatusError is used by SlaveStatus SlaveStatusError error + // StartSlaveError is used by StartSlave + StartSlaveError error + // CurrentMasterHost is returned by SlaveStatus CurrentMasterHost string @@ -91,6 +98,9 @@ type FakeMysqlDaemon struct { // (as "%v:%v"). If it doesn't match, SetMaster will return an error. SetMasterInput string + // SetMasterError is used by SetMaster + SetMasterError error + // WaitMasterPosition is checked by WaitMasterPos, if the // same it returns nil, if different it returns an error WaitMasterPosition mysql.Position @@ -147,8 +157,9 @@ type FakeMysqlDaemon struct { // 'db' can be nil if the test doesn't use a database at all. func NewFakeMysqlDaemon(db *fakesqldb.DB) *FakeMysqlDaemon { result := &FakeMysqlDaemon{ - db: db, - Running: true, + db: db, + Running: true, + SlaveIORunning: true, } if db != nil { result.appPool = dbconnpool.NewConnectionPool("AppConnPool", 5, time.Minute, 0) @@ -211,10 +222,12 @@ func (fmd *FakeMysqlDaemon) SlaveStatus() (mysql.SlaveStatus, error) { return mysql.SlaveStatus{ Position: fmd.CurrentMasterPosition, SecondsBehindMaster: fmd.SecondsBehindMaster, - SlaveIORunning: fmd.Replicating, - SlaveSQLRunning: fmd.Replicating, - MasterHost: fmd.CurrentMasterHost, - MasterPort: fmd.CurrentMasterPort, + // implemented as AND to avoid changing all tests that were + // previously using Replicating = false + SlaveIORunning: fmd.Replicating && fmd.SlaveIORunning, + SlaveSQLRunning: fmd.Replicating, + MasterHost: fmd.CurrentMasterHost, + MasterPort: fmd.CurrentMasterPort, }, nil } @@ -250,11 +263,23 @@ func (fmd *FakeMysqlDaemon) SetSuperReadOnly(on bool) error { // StartSlave is part of the MysqlDaemon interface. func (fmd *FakeMysqlDaemon) StartSlave(hookExtraEnv map[string]string) error { + if fmd.StartSlaveError != nil { + return fmd.StartSlaveError + } return fmd.ExecuteSuperQueryList(context.Background(), []string{ "START SLAVE", }) } +// RestartSlave is part of the MysqlDaemon interface. +func (fmd *FakeMysqlDaemon) RestartSlave(hookExtraEnv map[string]string) error { + return fmd.ExecuteSuperQueryList(context.Background(), []string{ + "STOP SLAVE", + "RESET SLAVE", + "START SLAVE", + }) +} + // StartSlaveUntilAfter is part of the MysqlDaemon interface. func (fmd *FakeMysqlDaemon) StartSlaveUntilAfter(ctx context.Context, pos mysql.Position) error { if !reflect.DeepEqual(fmd.StartSlaveUntilAfterPos, pos) { @@ -289,6 +314,9 @@ func (fmd *FakeMysqlDaemon) SetMaster(ctx context.Context, masterHost string, ma if fmd.SetMasterInput != input { return fmt.Errorf("wrong input for SetMasterCommands: expected %v got %v", fmd.SetMasterInput, input) } + if fmd.SetMasterError != nil { + return fmd.SetMasterError + } cmds := []string{} if slaveStopBefore { cmds = append(cmds, "STOP SLAVE") diff --git a/go/vt/mysqlctl/gcsbackupstorage/gcs.go b/go/vt/mysqlctl/gcsbackupstorage/gcs.go index 513a15ae16c..5473be3217a 100644 --- a/go/vt/mysqlctl/gcsbackupstorage/gcs.go +++ b/go/vt/mysqlctl/gcsbackupstorage/gcs.go @@ -37,8 +37,6 @@ import ( ) var ( - _ = flag.String("gcs_backup_storage_project", "", "This flag is unused and deprecated. It will be removed entirely in a future release.") - // bucket is where the backups will go. bucket = flag.String("gcs_backup_storage_bucket", "", "Google Cloud Storage bucket to use for backups") diff --git a/go/vt/mysqlctl/metadata_tables.go b/go/vt/mysqlctl/metadata_tables.go index 4df32691eac..699bc57ee4e 100644 --- a/go/vt/mysqlctl/metadata_tables.go +++ b/go/vt/mysqlctl/metadata_tables.go @@ -61,7 +61,7 @@ var ( // a per-tablet table that is never replicated. This allows queries // against local_metadata to return different values on different tablets, // which is used for communicating between Vitess and MySQL-level tools like -// Orchestrator (http://github.com/github/orchestrator). +// Orchestrator (https://github.com/github/orchestrator). // _vt.shard_metadata is a replicated table with per-shard information, but it's // created here to make it easier to create it on databases that were running // old version of Vitess, or databases that are getting converted to run under diff --git a/go/vt/mysqlctl/mycnf_gen.go b/go/vt/mysqlctl/mycnf_gen.go index eda6b5d6f48..5a89ebc614b 100644 --- a/go/vt/mysqlctl/mycnf_gen.go +++ b/go/vt/mysqlctl/mycnf_gen.go @@ -22,7 +22,6 @@ import ( "bytes" "crypto/rand" "fmt" - "io/ioutil" "math/big" "path" "text/template" @@ -121,19 +120,9 @@ func (cnf *Mycnf) directoryList() []string { } } -// makeMycnf will join cnf files cnfPaths and substitute in the right values. -func (cnf *Mycnf) makeMycnf(cnfFiles []string) (string, error) { - myTemplateSource := new(bytes.Buffer) - myTemplateSource.WriteString("[mysqld]\n") - for _, path := range cnfFiles { - data, dataErr := ioutil.ReadFile(path) - if dataErr != nil { - return "", dataErr - } - myTemplateSource.WriteString("## " + path + "\n") - myTemplateSource.Write(data) - } - return cnf.fillMycnfTemplate(myTemplateSource.String()) +// makeMycnf will substitute values +func (cnf *Mycnf) makeMycnf(partialcnf string) (string, error) { + return cnf.fillMycnfTemplate(partialcnf) } // fillMycnfTemplate will fill in the passed in template with the values diff --git a/go/vt/mysqlctl/mycnf_test.go b/go/vt/mysqlctl/mycnf_test.go index e7215f894fe..3412e56c57b 100644 --- a/go/vt/mysqlctl/mycnf_test.go +++ b/go/vt/mysqlctl/mycnf_test.go @@ -17,36 +17,29 @@ limitations under the License. package mysqlctl import ( + "bytes" "io/ioutil" "os" - "path" "strings" "testing" "vitess.io/vitess/go/vt/dbconfigs" - "vitess.io/vitess/go/vt/env" "vitess.io/vitess/go/vt/servenv" ) var MycnfPath = "/tmp/my.cnf" func TestMycnf(t *testing.T) { - os.Setenv("MYSQL_FLAVOR", "MariaDB") uid := uint32(11111) cnf := NewMycnf(uid, 6802) + myTemplateSource := new(bytes.Buffer) + myTemplateSource.WriteString("[mysqld]\n") // Assigning ServerID to be different from tablet UID to make sure that there are no // assumptions in the code that those IDs are the same. cnf.ServerID = 22222 - root, err := env.VtRoot() - if err != nil { - t.Errorf("err: %v", err) - } - cnfTemplatePaths := []string{ - path.Join(root, "src/vitess.io/vitess/config/mycnf/default.cnf"), - path.Join(root, "src/vitess.io/vitess/config/mycnf/replica.cnf"), - path.Join(root, "src/vitess.io/vitess/config/mycnf/master.cnf"), - } - data, err := cnf.makeMycnf(cnfTemplatePaths) + f, _ := ioutil.ReadFile("../../../config/mycnf/default.cnf") + myTemplateSource.Write(f) + data, err := cnf.makeMycnf(myTemplateSource.String()) if err != nil { t.Errorf("err: %v", err) } else { @@ -81,13 +74,12 @@ func TestMycnf(t *testing.T) { // Run this test if any changes are made to hook handling / make_mycnf hook // other tests fail if we keep the hook around -// 1. ln -snf $VTTOP/test/vthook-make_mycnf $VTROOT/vthook/make_mycnf +// 1. ln -snf $VTROOT/test/vthook-make_mycnf $VTROOT/vthook/make_mycnf // 2. Remove "No" prefix from func name // 3. go test // 4. \rm $VTROOT/vthook/make_mycnf // 5. Add No Prefix back func NoTestMycnfHook(t *testing.T) { - os.Setenv("MYSQL_FLAVOR", "MariaDB") uid := uint32(11111) cnf := NewMycnf(uid, 6802) // Assigning ServerID to be different from tablet UID to make sure that there are no diff --git a/go/vt/mysqlctl/mysql_daemon.go b/go/vt/mysqlctl/mysql_daemon.go index 18d6d6816e0..f205527ba97 100644 --- a/go/vt/mysqlctl/mysql_daemon.go +++ b/go/vt/mysqlctl/mysql_daemon.go @@ -42,6 +42,7 @@ type MysqlDaemon interface { // replication related methods StartSlave(hookExtraEnv map[string]string) error + RestartSlave(hookExtraEnv map[string]string) error StartSlaveUntilAfter(ctx context.Context, pos mysql.Position) error StopSlave(hookExtraEnv map[string]string) error SlaveStatus() (mysql.SlaveStatus, error) diff --git a/go/vt/mysqlctl/mysqld.go b/go/vt/mysqlctl/mysqld.go index 84c000306c2..0fe96edd0f7 100644 --- a/go/vt/mysqlctl/mysqld.go +++ b/go/vt/mysqlctl/mysqld.go @@ -41,6 +41,8 @@ import ( "sync" "time" + rice "github.com/GeertJohan/go.rice" + "golang.org/x/net/context" "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/stats" @@ -70,8 +72,8 @@ var ( poolDynamicHostnameResolution = flag.Duration("pool_hostname_resolve_interval", 0, "if set force an update to all hostnames and reconnect if changed, defaults to 0 (disabled)") - socketFile = flag.String("mysqlctl_socket", "", "socket file to use for remote mysqlctl actions (empty for local actions)") mycnfTemplateFile = flag.String("mysqlctl_mycnf_template", "", "template file to use for generating the my.cnf file during server init") + socketFile = flag.String("mysqlctl_socket", "", "socket file to use for remote mysqlctl actions (empty for local actions)") // masterConnectRetry is used in 'SET MASTER' commands masterConnectRetry = flag.Duration("master_connect_retry", 10*time.Second, "how long to wait in between slave -> connection attempts. Only precise to the second.") @@ -109,7 +111,7 @@ func NewMysqld(dbcfgs *dbconfigs.DBConfigs) *Mysqld { // Create and open the connection pool for dba access. result.dbaPool = dbconnpool.NewConnectionPool("DbaConnPool", *dbaPoolSize, *dbaIdleTimeout, *poolDynamicHostnameResolution) - result.dbaPool.Open(dbcfgs.Dba(), dbaMysqlStats) + result.dbaPool.Open(dbcfgs.DbaWithDB(), dbaMysqlStats) // Create and open the connection pool for app access. result.appPool = dbconnpool.NewConnectionPool("AppConnPool", *appPoolSize, *appIdleTimeout, *poolDynamicHostnameResolution) @@ -133,8 +135,8 @@ func NewMysqld(dbcfgs *dbconfigs.DBConfigs) *Mysqld { /* By default Vitess searches in vtenv.VtMysqlRoot() for a mysqld binary. - This is usually the VT_MYSQL_ROOT env, but if it is unset or empty, it - will substitute VtRoot(). See go/vt/env/env.go. + This is historically the VT_MYSQL_ROOT env, but if it is unset or empty, + Vitess will search the PATH. See go/vt/env/env.go. A number of subdirs inside vtenv.VtMysqlRoot() will be searched, see func binaryPath() for context. If no mysqld binary is found (possibly @@ -153,12 +155,14 @@ func NewMysqld(dbcfgs *dbconfigs.DBConfigs) *Mysqld { f, v, err = getVersionFromEnv() if err != nil { vtenvMysqlRoot, _ := vtenv.VtMysqlRoot() - message := fmt.Sprintf(`could not auto-detect MySQL version. You may need to set VT_MYSQL_ROOT so a mysqld binary can be found, or set the environment variable MYSQL_FLAVOR if mysqld is not available locally: + message := fmt.Sprintf(`could not auto-detect MySQL version. You may need to set your PATH so a mysqld binary can be found, or set the environment variable MYSQL_FLAVOR if mysqld is not available locally: + PATH: %s VT_MYSQL_ROOT: %s VTROOT: %s vtenv.VtMysqlRoot(): %s MYSQL_FLAVOR: %s `, + os.Getenv("PATH"), os.Getenv("VT_MYSQL_ROOT"), os.Getenv("VTROOT"), vtenvMysqlRoot, @@ -264,25 +268,13 @@ func (mysqld *Mysqld) RunMysqlUpgrade() error { return nil } - // Find mysql_upgrade. If not there, we do nothing. - dir, err := vtenv.VtMysqlRoot() - if err != nil { - log.Warningf("VT_MYSQL_ROOT not set, skipping mysql_upgrade step: %v", err) - return nil - } - name, err := binaryPath(dir, "mysql_upgrade") - if err != nil { - log.Warningf("mysql_upgrade binary not present, skipping it: %v", err) - return nil - } - // Since we started mysql with --skip-grant-tables, we should // be able to run mysql_upgrade without any valid user or // password. However, mysql_upgrade executes a 'flush // privileges' right in the middle, and then subsequent // commands fail if we don't use valid credentials. So let's // use dba credentials. - params, err := dbconfigs.WithCredentials(mysqld.dbcfgs.Dba()) + params, err := mysqld.dbcfgs.Dba().MysqlParams() if err != nil { return err } @@ -300,10 +292,26 @@ func (mysqld *Mysqld) RunMysqlUpgrade() error { "--defaults-file=" + defaultsFile, "--force", // Don't complain if it's already been upgraded. } - cmd := exec.Command(name, args...) - cmd.Env = []string{os.ExpandEnv("LD_LIBRARY_PATH=$VT_MYSQL_ROOT/lib/mysql")} - out, err := cmd.CombinedOutput() - log.Infof("mysql_upgrade output: %s", out) + + // Find mysql_upgrade. If not there, we do nothing. + vtMysqlRoot, err := vtenv.VtMysqlRoot() + if err != nil { + log.Warningf("VT_MYSQL_ROOT not set, skipping mysql_upgrade step: %v", err) + return nil + } + name, err := binaryPath(vtMysqlRoot, "mysql_upgrade") + if err != nil { + log.Warningf("mysql_upgrade binary not present, skipping it: %v", err) + return nil + } + + env, err := buildLdPaths() + if err != nil { + log.Warningf("skipping mysql_upgrade step: %v", err) + return nil + } + + _, _, err = execCmd(name, args, env, "", nil) return err } @@ -344,16 +352,16 @@ func (mysqld *Mysqld) startNoWait(ctx context.Context, cnf *Mycnf, mysqldArgs .. case hook.HOOK_DOES_NOT_EXIST: // hook doesn't exist, run mysqld_safe ourselves log.Infof("%v: No mysqld_start hook, running mysqld_safe directly", ts) - dir, err := vtenv.VtMysqlRoot() + vtMysqlRoot, err := vtenv.VtMysqlRoot() if err != nil { return err } - name, err = binaryPath(dir, "mysqld_safe") + name, err = binaryPath(vtMysqlRoot, "mysqld_safe") if err != nil { // The movement to use systemd means that mysqld_safe is not always provided. // This should not be considered an issue do not generate a warning. log.Infof("%v: trying to launch mysqld instead", err) - name, err = binaryPath(dir, "mysqld") + name, err = binaryPath(vtMysqlRoot, "mysqld") // If this also fails, return an error. if err != nil { return err @@ -363,15 +371,18 @@ func (mysqld *Mysqld) startNoWait(ctx context.Context, cnf *Mycnf, mysqldArgs .. if err != nil { return err } - arg := []string{ + args := []string{ "--defaults-file=" + cnf.path, "--basedir=" + mysqlBaseDir, } - arg = append(arg, mysqldArgs...) - env := []string{os.ExpandEnv("LD_LIBRARY_PATH=$VT_MYSQL_ROOT/lib/mysql")} + args = append(args, mysqldArgs...) + env, err := buildLdPaths() + if err != nil { + return err + } - cmd := exec.Command(name, arg...) - cmd.Dir = dir + cmd := exec.Command(name, args...) + cmd.Dir = vtMysqlRoot cmd.Env = env log.Infof("%v %#v", ts, cmd) stderr, err := cmd.StderrPipe() @@ -430,7 +441,7 @@ func (mysqld *Mysqld) startNoWait(ctx context.Context, cnf *Mycnf, mysqldArgs .. // will use the dba credentials to try to connect. Use wait() with // different credentials if needed. func (mysqld *Mysqld) Wait(ctx context.Context, cnf *Mycnf) error { - params, err := dbconfigs.WithCredentials(mysqld.dbcfgs.Dba()) + params, err := mysqld.dbcfgs.Dba().MysqlParams() if err != nil { return err } @@ -520,7 +531,7 @@ func (mysqld *Mysqld) Shutdown(ctx context.Context, cnf *Mycnf, waitForMysqld bo if err != nil { return err } - params, err := dbconfigs.WithCredentials(mysqld.dbcfgs.Dba()) + params, err := mysqld.dbcfgs.Dba().MysqlParams() if err != nil { return err } @@ -536,13 +547,13 @@ func (mysqld *Mysqld) Shutdown(ctx context.Context, cnf *Mycnf, waitForMysqld bo "--wait=10", "shutdown", } - env := []string{ - os.ExpandEnv("LD_LIBRARY_PATH=$VT_MYSQL_ROOT/lib/mysql"), - } - _, _, err = execCmd(name, args, env, dir, nil) + env, err := buildLdPaths() if err != nil { return err } + if _, _, err = execCmd(name, args, env, dir, nil); err != nil { + return err + } default: // hook failed, we report error return fmt.Errorf("mysqld_shutdown hook failed: %v", hr.String()) @@ -618,14 +629,8 @@ func (mysqld *Mysqld) InitConfig(cnf *Mycnf) error { log.Errorf("%s", err.Error()) return err } - root, err := vtenv.VtRoot() - if err != nil { - log.Errorf("%s", err.Error()) - return err - } - // Set up config files. - if err = mysqld.initConfig(root, cnf, cnf.path); err != nil { + if err = mysqld.initConfig(cnf, cnf.path); err != nil { log.Errorf("failed creating %v: %v", cnf.path, err) return err } @@ -666,7 +671,19 @@ func (mysqld *Mysqld) Init(ctx context.Context, cnf *Mycnf, initDBSQLFile string return err } - // Run initial SQL file. + if initDBSQLFile == "" { // default to built-in + riceBox := rice.MustFindBox("../../../config") + sqlFile, err := riceBox.Open("init_db.sql") + if err != nil { + return fmt.Errorf("could not open built-in init_db.sql file") + } + if err := mysqld.executeMysqlScript(params, sqlFile); err != nil { + return fmt.Errorf("failed to initialize mysqld: %v", err) + } + return nil + } + + // else, user specified an init db file sqlFile, err := os.Open(initDBSQLFile) if err != nil { return fmt.Errorf("can't open init_db_sql_file (%v): %v", initDBSQLFile, err) @@ -675,7 +692,6 @@ func (mysqld *Mysqld) Init(ctx context.Context, cnf *Mycnf, initDBSQLFile string if err := mysqld.executeMysqlScript(params, sqlFile); err != nil { return fmt.Errorf("can't run init_db_sql_file (%v): %v", initDBSQLFile, err) } - return nil } @@ -756,7 +772,7 @@ func (mysqld *Mysqld) installDataDir(cnf *Mycnf) error { return nil } -func (mysqld *Mysqld) initConfig(root string, cnf *Mycnf, outFile string) error { +func (mysqld *Mysqld) initConfig(cnf *Mycnf, outFile string) error { var err error var configData string @@ -769,7 +785,7 @@ func (mysqld *Mysqld) initConfig(root string, cnf *Mycnf, outFile string) error switch hr := hook.NewHookWithEnv("make_mycnf", nil, env).Execute(); hr.ExitStatus { case hook.HOOK_DOES_NOT_EXIST: log.Infof("make_mycnf hook doesn't exist, reading template files") - configData, err = cnf.makeMycnf(mysqld.getMycnfTemplates(root)) + configData, err = cnf.makeMycnf(mysqld.getMycnfTemplate()) case hook.HOOK_SUCCESS: configData, err = cnf.fillMycnfTemplate(hr.Stdout) default: @@ -782,47 +798,50 @@ func (mysqld *Mysqld) initConfig(root string, cnf *Mycnf, outFile string) error return ioutil.WriteFile(outFile, []byte(configData), 0664) } -func contains(haystack []string, needle string) bool { - for _, v := range haystack { - if v == needle { - return true - } - } - return false -} - -func (mysqld *Mysqld) getMycnfTemplates(root string) []string { +func (mysqld *Mysqld) getMycnfTemplate() string { if *mycnfTemplateFile != "" { - return []string{*mycnfTemplateFile} - } - - cnfTemplatePaths := []string{ - path.Join(root, "config/mycnf/default.cnf"), - path.Join(root, "config/mycnf/master.cnf"), - path.Join(root, "config/mycnf/replica.cnf"), + data, err := ioutil.ReadFile(*mycnfTemplateFile) + if err != nil { + log.Fatalf("template file specified by -mysqlctl_mycnf_template could not be read: %v", *mycnfTemplateFile) + } + return string(data) // use only specified template } + myTemplateSource := new(bytes.Buffer) + myTemplateSource.WriteString("[mysqld]\n") - if extraCnf := os.Getenv("EXTRA_MY_CNF"); extraCnf != "" { - parts := strings.Split(extraCnf, ":") - cnfTemplatePaths = append(cnfTemplatePaths, parts...) + riceBox := rice.MustFindBox("../../../config") + b, err := riceBox.Bytes("mycnf/default.cnf") + if err != nil { + log.Warningf("could not open embedded default.cnf config file") } + myTemplateSource.Write(b) - // Only include files if they exist. - // Percona Server == MySQL in this context - + // mysql version specific file. + // master_{flavor}{major}{minor}.cnf f := flavorMariaDB if mysqld.capabilities.isMySQLLike() { f = flavorMySQL } - - // master_{flavor}{major}{minor}.cnf - p := path.Join(root, fmt.Sprintf("config/mycnf/master_%s%d%d.cnf", f, mysqld.capabilities.version.Major, mysqld.capabilities.version.Minor)) - _, err := os.Stat(p) - if err == nil && !contains(cnfTemplatePaths, p) { - cnfTemplatePaths = append(cnfTemplatePaths, p) + fn := fmt.Sprintf("mycnf/master_%s%d%d.cnf", f, mysqld.capabilities.version.Major, mysqld.capabilities.version.Minor) + b, err = riceBox.Bytes(fn) + if err != nil { + log.Infof("this version of Vitess does not include built-in support for %v %v", mysqld.capabilities.flavor, mysqld.capabilities.version) } + myTemplateSource.Write(b) - return cnfTemplatePaths + if extraCnf := os.Getenv("EXTRA_MY_CNF"); extraCnf != "" { + parts := strings.Split(extraCnf, ":") + for _, path := range parts { + data, dataErr := ioutil.ReadFile(path) + if dataErr != nil { + log.Infof("could not open config file for mycnf: %v", path) + continue + } + myTemplateSource.WriteString("## " + path + "\n") + myTemplateSource.Write(data) + } + } + return myTemplateSource.String() } // RefreshConfig attempts to recreate the my.cnf from templates, and log and @@ -841,17 +860,13 @@ func (mysqld *Mysqld) RefreshConfig(ctx context.Context, cnf *Mycnf) error { } log.Info("Checking for updates to my.cnf") - root, err := vtenv.VtRoot() - if err != nil { - return err - } f, err := ioutil.TempFile(path.Dir(cnf.path), "my.cnf") if err != nil { return fmt.Errorf("could not create temp file: %v", err) } defer os.Remove(f.Name()) - err = mysqld.initConfig(root, cnf, f.Name()) + err = mysqld.initConfig(cnf, f.Name()) if err != nil { return fmt.Errorf("could not initConfig in %v: %v", f.Name(), err) } @@ -905,11 +920,7 @@ func (mysqld *Mysqld) ReinitConfig(ctx context.Context, cnf *Mycnf) error { if err := cnf.RandomizeMysqlServerID(); err != nil { return err } - root, err := vtenv.VtRoot() - if err != nil { - return err - } - return mysqld.initConfig(root, cnf, cnf.path) + return mysqld.initConfig(cnf, cnf.path) } func (mysqld *Mysqld) createDirs(cnf *Mycnf) error { @@ -1028,8 +1039,9 @@ func (mysqld *Mysqld) executeMysqlScript(connParams *mysql.ConnParams, sql io.Re "--defaults-extra-file=" + cnf, "--batch", } - env := []string{ - "LD_LIBRARY_PATH=" + path.Join(dir, "lib/mysql"), + env, err := buildLdPaths() + if err != nil { + return err } _, _, err = execCmd(name, args, env, dir, sql) if err != nil { @@ -1047,6 +1059,7 @@ func (mysqld *Mysqld) executeMysqlScript(connParams *mysql.ConnParams, sql io.Re // 'defer os.Remove()' statement. func (mysqld *Mysqld) defaultsExtraFile(connParams *mysql.ConnParams) (string, error) { var contents string + connParams.Pass = strings.Replace(connParams.Pass, "#", "\\#", -1) if connParams.UnixSocket == "" { contents = fmt.Sprintf(` [client] @@ -1116,3 +1129,17 @@ func (mysqld *Mysqld) OnTerm(f func()) { defer mysqld.mutex.Unlock() mysqld.onTermFuncs = append(mysqld.onTermFuncs, f) } + +func buildLdPaths() ([]string, error) { + vtMysqlRoot, err := vtenv.VtMysqlRoot() + if err != nil { + return []string{}, err + } + + ldPaths := []string{ + fmt.Sprintf("LD_LIBRARY_PATH=%s/lib/mysql", vtMysqlRoot), + os.ExpandEnv("LD_PRELOAD=$LD_PRELOAD"), + } + + return ldPaths, nil +} diff --git a/go/vt/mysqlctl/replication.go b/go/vt/mysqlctl/replication.go index 67acf25ff95..4bcec1d8408 100644 --- a/go/vt/mysqlctl/replication.go +++ b/go/vt/mysqlctl/replication.go @@ -32,7 +32,6 @@ import ( "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/netutil" "vitess.io/vitess/go/sqltypes" - "vitess.io/vitess/go/vt/dbconfigs" "vitess.io/vitess/go/vt/hook" "vitess.io/vitess/go/vt/log" ) @@ -114,6 +113,29 @@ func (mysqld *Mysqld) StopSlave(hookExtraEnv map[string]string) error { return mysqld.executeSuperQueryListConn(ctx, conn, []string{conn.StopSlaveCommand()}) } +// RestartSlave stops, resets and starts a slave. +func (mysqld *Mysqld) RestartSlave(hookExtraEnv map[string]string) error { + h := hook.NewSimpleHook("preflight_stop_slave") + h.ExtraEnv = hookExtraEnv + if err := h.ExecuteOptional(); err != nil { + return err + } + ctx := context.TODO() + conn, err := getPoolReconnect(ctx, mysqld.dbaPool) + if err != nil { + return err + } + defer conn.Recycle() + + if err := mysqld.executeSuperQueryListConn(ctx, conn, conn.RestartSlaveCommands()); err != nil { + return err + } + + h = hook.NewSimpleHook("postflight_start_slave") + h.ExtraEnv = hookExtraEnv + return h.ExecuteOptional() +} + // GetMysqlPort returns mysql port func (mysqld *Mysqld) GetMysqlPort() (int32, error) { qr, err := mysqld.FetchSuperQuery(context.TODO(), "SHOW VARIABLES LIKE 'port'") @@ -253,7 +275,7 @@ func (mysqld *Mysqld) SetSlavePosition(ctx context.Context, pos mysql.Position) // SetMaster makes the provided host / port the master. It optionally // stops replication before, and starts it after. func (mysqld *Mysqld) SetMaster(ctx context.Context, masterHost string, masterPort int, slaveStopBefore bool, slaveStartAfter bool) error { - params, err := dbconfigs.WithCredentials(mysqld.dbcfgs.Repl()) + params, err := mysqld.dbcfgs.Repl().MysqlParams() if err != nil { return err } diff --git a/go/vt/mysqlctl/rice-box.go b/go/vt/mysqlctl/rice-box.go new file mode 100644 index 00000000000..b2ee667d6e3 --- /dev/null +++ b/go/vt/mysqlctl/rice-box.go @@ -0,0 +1,177 @@ +package mysqlctl + +import ( + "time" + + "github.com/GeertJohan/go.rice/embedded" +) + +func init() { + + // define files + file2 := &embedded.EmbeddedFile{ + Filename: "gomysql.pc.tmpl", + FileModTime: time.Unix(1562782645, 0), + + Content: string("Name: GoMysql\nDescription: Flags for using mysql C client in go\n"), + } + file3 := &embedded.EmbeddedFile{ + Filename: "init_db.sql", + FileModTime: time.Unix(1578077737, 0), + + Content: string("# This file is executed immediately after mysql_install_db,\n# to initialize a fresh data directory.\n\n###############################################################################\n# WARNING: This sql is *NOT* safe for production use,\n# as it contains default well-known users and passwords.\n# Care should be taken to change these users and passwords\n# for production.\n###############################################################################\n\n###############################################################################\n# Equivalent of mysql_secure_installation\n###############################################################################\n\n# Changes during the init db should not make it to the binlog.\n# They could potentially create errant transactions on replicas.\nSET sql_log_bin = 0;\n# Remove anonymous users.\nDELETE FROM mysql.user WHERE User = '';\n\n# Disable remote root access (only allow UNIX socket).\nDELETE FROM mysql.user WHERE User = 'root' AND Host != 'localhost';\n\n# Remove test database.\nDROP DATABASE IF EXISTS test;\n\n###############################################################################\n# Vitess defaults\n###############################################################################\n\n# Vitess-internal database.\nCREATE DATABASE IF NOT EXISTS _vt;\n# Note that definitions of local_metadata and shard_metadata should be the same\n# as in production which is defined in go/vt/mysqlctl/metadata_tables.go.\nCREATE TABLE IF NOT EXISTS _vt.local_metadata (\n name VARCHAR(255) NOT NULL,\n value VARCHAR(255) NOT NULL,\n db_name VARBINARY(255) NOT NULL,\n PRIMARY KEY (db_name, name)\n ) ENGINE=InnoDB;\nCREATE TABLE IF NOT EXISTS _vt.shard_metadata (\n name VARCHAR(255) NOT NULL,\n value MEDIUMBLOB NOT NULL,\n db_name VARBINARY(255) NOT NULL,\n PRIMARY KEY (db_name, name)\n ) ENGINE=InnoDB;\n\n# Admin user with all privileges.\nCREATE USER 'vt_dba'@'localhost';\nGRANT ALL ON *.* TO 'vt_dba'@'localhost';\nGRANT GRANT OPTION ON *.* TO 'vt_dba'@'localhost';\n\n# User for app traffic, with global read-write access.\nCREATE USER 'vt_app'@'localhost';\nGRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE,\n REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES,\n LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW,\n SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER\n ON *.* TO 'vt_app'@'localhost';\n\n# User for app debug traffic, with global read access.\nCREATE USER 'vt_appdebug'@'localhost';\nGRANT SELECT, SHOW DATABASES, PROCESS ON *.* TO 'vt_appdebug'@'localhost';\n\n# User for administrative operations that need to be executed as non-SUPER.\n# Same permissions as vt_app here.\nCREATE USER 'vt_allprivs'@'localhost';\nGRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE,\n REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES,\n LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW,\n SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER\n ON *.* TO 'vt_allprivs'@'localhost';\n\n# User for slave replication connections.\nCREATE USER 'vt_repl'@'%';\nGRANT REPLICATION SLAVE ON *.* TO 'vt_repl'@'%';\n\n# User for Vitess filtered replication (binlog player).\n# Same permissions as vt_app.\nCREATE USER 'vt_filtered'@'localhost';\nGRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE,\n REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES,\n LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW,\n SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER\n ON *.* TO 'vt_filtered'@'localhost';\n\n# User for general MySQL monitoring.\nCREATE USER 'vt_monitoring'@'localhost';\nGRANT SELECT, PROCESS, SUPER, REPLICATION CLIENT, RELOAD\n ON *.* TO 'vt_monitoring'@'localhost';\nGRANT SELECT, UPDATE, DELETE, DROP\n ON performance_schema.* TO 'vt_monitoring'@'localhost';\n\n# User for Orchestrator (https://github.com/github/orchestrator).\nCREATE USER 'orc_client_user'@'%' IDENTIFIED BY 'orc_client_user_password';\nGRANT SUPER, PROCESS, REPLICATION SLAVE, RELOAD\n ON *.* TO 'orc_client_user'@'%';\nGRANT SELECT\n ON _vt.* TO 'orc_client_user'@'%';\n\nFLUSH PRIVILEGES;\n\nRESET SLAVE ALL;\nRESET MASTER;\n"), + } + file5 := &embedded.EmbeddedFile{ + Filename: "mycnf/default-fast.cnf", + FileModTime: time.Unix(1579019392, 0), + + Content: string("# This sets some unsafe settings specifically for \n# the test-suite which is currently MySQL 5.7 based\n# In future it should be renamed testsuite.cnf\n\ninnodb_buffer_pool_size = 32M\ninnodb_flush_log_at_trx_commit = 0\ninnodb_log_buffer_size = 1M\ninnodb_log_file_size = 5M\n\n# Native AIO tends to run into aio-max-nr limit during test startup.\ninnodb_use_native_aio = 0\n\nkey_buffer_size = 2M\nsync_binlog=0\ninnodb_doublewrite=0\n\n# These two settings are required for the testsuite to pass, \n# but enabling them does not spark joy. They should be removed\n# in the future. See:\n# https://github.com/vitessio/vitess/issues/5396\n\nsql_mode = STRICT_TRANS_TABLES\n"), + } + file6 := &embedded.EmbeddedFile{ + Filename: "mycnf/default.cnf", + FileModTime: time.Unix(1579632282, 0), + + Content: string("# Global configuration that is auto-included for all MySQL/MariaDB versions\n\ndatadir = {{.DataDir}}\ninnodb_data_home_dir = {{.InnodbDataHomeDir}}\ninnodb_log_group_home_dir = {{.InnodbLogGroupHomeDir}}\nlog-error = {{.ErrorLogPath}}\nlog-bin = {{.BinLogPath}}\nrelay-log = {{.RelayLogPath}}\nrelay-log-index = {{.RelayLogIndexPath}}\npid-file = {{.PidFile}}\nport = {{.MysqlPort}}\n\n# all db instances should start in read-only mode - once the db is started and\n# fully functional, we'll push it into read-write mode\nread-only\nserver-id = {{.ServerID}}\n\n# all db instances should skip the slave startup - that way we can do any\n# additional configuration (like enabling semi-sync) before we connect to\n# the master.\nskip_slave_start\nslave_load_tmpdir = {{.SlaveLoadTmpDir}}\nsocket = {{.SocketFile}}\ntmpdir = {{.TmpDir}}\n\nslow-query-log-file = {{.SlowLogPath}}\n\n# These are sensible defaults that apply to all MySQL/MariaDB versions\n\nlong_query_time = 2\nslow-query-log\nskip-name-resolve\nconnect_timeout = 30\ninnodb_lock_wait_timeout = 20\nmax_allowed_packet = 64M\nmax_connections = 500\n\n\n"), + } + file7 := &embedded.EmbeddedFile{ + Filename: "mycnf/master_mariadb100.cnf", + FileModTime: time.Unix(1579019403, 0), + + Content: string("# This file is auto-included when MariaDB 10.0 is detected.\n\n# Semi-sync replication is required for automated unplanned failover\n# (when the master goes away). Here we just load the plugin so it's\n# available if desired, but it's disabled at startup.\n#\n# If the -enable_semi_sync flag is used, VTTablet will enable semi-sync\n# at the proper time when replication is set up, or when masters are\n# promoted or demoted.\nplugin-load = rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so\n\nslave_net_timeout = 60\n\n# MariaDB 10.0 is unstrict by default\nsql_mode = STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION\n\n# enable strict mode so it's safe to compare sequence numbers across different server IDs.\ngtid_strict_mode = 1\ninnodb_stats_persistent = 0\n\n# When semi-sync is enabled, don't allow fallback to async\n# if you get no ack, or have no slaves. This is necessary to\n# prevent alternate futures when doing a failover in response to\n# a master that becomes unresponsive.\nrpl_semi_sync_master_timeout = 1000000000000000000\nrpl_semi_sync_master_wait_no_slave = 1\n\n\ncharacter_set_server = utf8\ncollation_server = utf8_general_ci\n\nexpire_logs_days = 3\n\nsync_binlog = 1\nbinlog_format = ROW\nlog_slave_updates\nexpire_logs_days = 3\n\n# In MariaDB the default charset is latin1\n\ncharacter_set_server = utf8\ncollation_server = utf8_general_ci\n\n"), + } + file8 := &embedded.EmbeddedFile{ + Filename: "mycnf/master_mariadb101.cnf", + FileModTime: time.Unix(1579019403, 0), + + Content: string("# This file is auto-included when MariaDB 10.1 is detected.\n\n# Semi-sync replication is required for automated unplanned failover\n# (when the master goes away). Here we just load the plugin so it's\n# available if desired, but it's disabled at startup.\n#\n# If the -enable_semi_sync flag is used, VTTablet will enable semi-sync\n# at the proper time when replication is set up, or when masters are\n# promoted or demoted.\nplugin-load = rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so\n\nslave_net_timeout = 60\n\n# MariaDB 10.1 default is only no-engine-substitution and no-auto-create-user\nsql_mode = STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,NO_AUTO_CREATE_USER\n\n# enable strict mode so it's safe to compare sequence numbers across different server IDs.\ngtid_strict_mode = 1\ninnodb_stats_persistent = 0\n\n# When semi-sync is enabled, don't allow fallback to async\n# if you get no ack, or have no slaves. This is necessary to\n# prevent alternate futures when doing a failover in response to\n# a master that becomes unresponsive.\nrpl_semi_sync_master_timeout = 1000000000000000000\nrpl_semi_sync_master_wait_no_slave = 1\n\n\ncharacter_set_server = utf8\ncollation_server = utf8_general_ci\n\nexpire_logs_days = 3\n\nsync_binlog = 1\nbinlog_format = ROW\nlog_slave_updates\nexpire_logs_days = 3\n\n# In MariaDB the default charset is latin1\n\ncharacter_set_server = utf8\ncollation_server = utf8_general_ci\n"), + } + file9 := &embedded.EmbeddedFile{ + Filename: "mycnf/master_mariadb102.cnf", + FileModTime: time.Unix(1579019403, 0), + + Content: string("# This file is auto-included when MariaDB 10.2 is detected.\n\n# Semi-sync replication is required for automated unplanned failover\n# (when the master goes away). Here we just load the plugin so it's\n# available if desired, but it's disabled at startup.\n#\n# If the -enable_semi_sync flag is used, VTTablet will enable semi-sync\n# at the proper time when replication is set up, or when masters are\n# promoted or demoted.\nplugin-load = rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so\n\n# enable strict mode so it's safe to compare sequence numbers across different server IDs.\ngtid_strict_mode = 1\ninnodb_stats_persistent = 0\n\n# When semi-sync is enabled, don't allow fallback to async\n# if you get no ack, or have no slaves. This is necessary to\n# prevent alternate futures when doing a failover in response to\n# a master that becomes unresponsive.\nrpl_semi_sync_master_timeout = 1000000000000000000\nrpl_semi_sync_master_wait_no_slave = 1\n\n\ncharacter_set_server = utf8\ncollation_server = utf8_general_ci\n\nexpire_logs_days = 3\n\nsync_binlog = 1\nbinlog_format = ROW\nlog_slave_updates\nexpire_logs_days = 3\n\n# In MariaDB the default charset is latin1\n\ncharacter_set_server = utf8\ncollation_server = utf8_general_ci\n"), + } + filea := &embedded.EmbeddedFile{ + Filename: "mycnf/master_mariadb103.cnf", + FileModTime: time.Unix(1579019403, 0), + + Content: string("# This file is auto-included when MariaDB 10.3 is detected.\n\n# enable strict mode so it's safe to compare sequence numbers across different server IDs.\ngtid_strict_mode = 1\ninnodb_stats_persistent = 0\n\n# When semi-sync is enabled, don't allow fallback to async\n# if you get no ack, or have no slaves. This is necessary to\n# prevent alternate futures when doing a failover in response to\n# a master that becomes unresponsive.\nrpl_semi_sync_master_timeout = 1000000000000000000\nrpl_semi_sync_master_wait_no_slave = 1\n\n\ncharacter_set_server = utf8\ncollation_server = utf8_general_ci\n\nexpire_logs_days = 3\n\nsync_binlog = 1\nbinlog_format = ROW\nlog_slave_updates\nexpire_logs_days = 3\n\n# In MariaDB the default charset is latin1\n\ncharacter_set_server = utf8\ncollation_server = utf8_general_ci\n\n\n"), + } + fileb := &embedded.EmbeddedFile{ + Filename: "mycnf/master_mariadb104.cnf", + FileModTime: time.Unix(1579019403, 0), + + Content: string("# This file is auto-included when MariaDB 10.4 is detected.\n\n# enable strict mode so it's safe to compare sequence numbers across different server IDs.\ngtid_strict_mode = 1\ninnodb_stats_persistent = 0\n\n# When semi-sync is enabled, don't allow fallback to async\n# if you get no ack, or have no slaves. This is necessary to\n# prevent alternate futures when doing a failover in response to\n# a master that becomes unresponsive.\nrpl_semi_sync_master_timeout = 1000000000000000000\nrpl_semi_sync_master_wait_no_slave = 1\n\n\ncharacter_set_server = utf8\ncollation_server = utf8_general_ci\n\nexpire_logs_days = 3\n\nsync_binlog = 1\nbinlog_format = ROW\nlog_slave_updates\nexpire_logs_days = 3\n\n# In MariaDB the default charset is latin1\n\ncharacter_set_server = utf8\ncollation_server = utf8_general_ci\n\n\n"), + } + filec := &embedded.EmbeddedFile{ + Filename: "mycnf/master_mysql56.cnf", + FileModTime: time.Unix(1579019403, 0), + + Content: string("# This file is auto-included when MySQL 5.6 is detected.\n\n# MySQL 5.6 does not enable the binary log by default, and \n# the default for sync_binlog is unsafe. The format is TABLE, and\n# info repositories also default to file.\n\nsync_binlog = 1\ngtid_mode = ON\nbinlog_format = ROW\nlog_slave_updates\nenforce_gtid_consistency\nexpire_logs_days = 3\nmaster_info_repository = TABLE\nrelay_log_info_repository = TABLE\nrelay_log_purge = 1\nrelay_log_recovery = 1\nslave_net_timeout = 60\n\n# In MySQL 5.6 the default charset is latin1\n\ncharacter_set_server = utf8\ncollation_server = utf8_general_ci\n\n# MySQL 5.6 is unstrict by default\nsql_mode = STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION\n\n# Semi-sync replication is required for automated unplanned failover\n# (when the master goes away). Here we just load the plugin so it's\n# available if desired, but it's disabled at startup.\n#\n# If the -enable_semi_sync flag is used, VTTablet will enable semi-sync\n# at the proper time when replication is set up, or when masters are\n# promoted or demoted.\nplugin-load = rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so\n\n# When semi-sync is enabled, don't allow fallback to async\n# if you get no ack, or have no slaves. This is necessary to\n# prevent alternate futures when doing a failover in response to\n# a master that becomes unresponsive.\nrpl_semi_sync_master_timeout = 1000000000000000000\nrpl_semi_sync_master_wait_no_slave = 1\n\n"), + } + filed := &embedded.EmbeddedFile{ + Filename: "mycnf/master_mysql57.cnf", + FileModTime: time.Unix(1579019403, 0), + + Content: string("# This file is auto-included when MySQL 5.7 is detected.\n\n# MySQL 5.7 does not enable the binary log by default, and \n# info repositories default to file\n\ngtid_mode = ON\nlog_slave_updates\nenforce_gtid_consistency\nexpire_logs_days = 3\nmaster_info_repository = TABLE\nrelay_log_info_repository = TABLE\nrelay_log_purge = 1\nrelay_log_recovery = 1\n\n# In MySQL 5.7 the default charset is latin1\n\ncharacter_set_server = utf8\ncollation_server = utf8_general_ci\n\n# Semi-sync replication is required for automated unplanned failover\n# (when the master goes away). Here we just load the plugin so it's\n# available if desired, but it's disabled at startup.\n#\n# If the -enable_semi_sync flag is used, VTTablet will enable semi-sync\n# at the proper time when replication is set up, or when masters are\n# promoted or demoted.\nplugin-load = rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so\n\n# When semi-sync is enabled, don't allow fallback to async\n# if you get no ack, or have no slaves. This is necessary to\n# prevent alternate futures when doing a failover in response to\n# a master that becomes unresponsive.\nrpl_semi_sync_master_timeout = 1000000000000000000\nrpl_semi_sync_master_wait_no_slave = 1\n\n"), + } + filee := &embedded.EmbeddedFile{ + Filename: "mycnf/master_mysql80.cnf", + FileModTime: time.Unix(1578945496, 0), + + Content: string("# This file is auto-included when MySQL 8.0 is detected.\n\n# MySQL 8.0 enables binlog by default with sync_binlog and TABLE info repositories\n# It does not enable GTIDs or enforced GTID consistency\n\ngtid_mode = ON\nenforce_gtid_consistency\nrelay_log_recovery = 1\nbinlog_expire_logs_seconds = 259200\n\n# disable mysqlx\nmysqlx = 0\n\n# 8.0 changes the default auth-plugin to caching_sha2_password\ndefault_authentication_plugin = mysql_native_password\n\n# Semi-sync replication is required for automated unplanned failover\n# (when the master goes away). Here we just load the plugin so it's\n# available if desired, but it's disabled at startup.\n#\n# If the -enable_semi_sync flag is used, VTTablet will enable semi-sync\n# at the proper time when replication is set up, or when masters are\n# promoted or demoted.\nplugin-load = rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so\n\n# MySQL 8.0 will not load plugins during --initialize\n# which makes these options unknown. Prefixing with --loose\n# tells the server it's fine if they are not understood.\nloose_rpl_semi_sync_master_timeout = 1000000000000000000\nloose_rpl_semi_sync_master_wait_no_slave = 1\n\n"), + } + filef := &embedded.EmbeddedFile{ + Filename: "mycnf/sbr.cnf", + FileModTime: time.Unix(1579019392, 0), + + Content: string("# This file is used to allow legacy tests to pass\n# In theory it should not be required\nbinlog_format=statement\n"), + } + fileg := &embedded.EmbeddedFile{ + Filename: "zk-client-dev.json", + FileModTime: time.Unix(1562782645, 0), + + Content: string("{\n \"local\": \"localhost:3863\",\n \"global\": \"localhost:3963\"\n}\n"), + } + filei := &embedded.EmbeddedFile{ + Filename: "zkcfg/zoo.cfg", + FileModTime: time.Unix(1562782645, 0), + + Content: string("tickTime=2000\ndataDir={{.DataDir}}\nclientPort={{.ClientPort}}\ninitLimit=5\nsyncLimit=2\nmaxClientCnxns=0\n{{range .Servers}}\nserver.{{.ServerId}}={{.Hostname}}:{{.LeaderPort}}:{{.ElectionPort}}\n{{end}}\n"), + } + + // define dirs + dir1 := &embedded.EmbeddedDir{ + Filename: "", + DirModTime: time.Unix(1578267519, 0), + ChildFiles: []*embedded.EmbeddedFile{ + file2, // "gomysql.pc.tmpl" + file3, // "init_db.sql" + fileg, // "zk-client-dev.json" + + }, + } + dir4 := &embedded.EmbeddedDir{ + Filename: "mycnf", + DirModTime: time.Unix(1579632282, 0), + ChildFiles: []*embedded.EmbeddedFile{ + file5, // "mycnf/default-fast.cnf" + file6, // "mycnf/default.cnf" + file7, // "mycnf/master_mariadb100.cnf" + file8, // "mycnf/master_mariadb101.cnf" + file9, // "mycnf/master_mariadb102.cnf" + filea, // "mycnf/master_mariadb103.cnf" + fileb, // "mycnf/master_mariadb104.cnf" + filec, // "mycnf/master_mysql56.cnf" + filed, // "mycnf/master_mysql57.cnf" + filee, // "mycnf/master_mysql80.cnf" + filef, // "mycnf/sbr.cnf" + + }, + } + dirh := &embedded.EmbeddedDir{ + Filename: "zkcfg", + DirModTime: time.Unix(1578087479, 0), + ChildFiles: []*embedded.EmbeddedFile{ + filei, // "zkcfg/zoo.cfg" + + }, + } + + // link ChildDirs + dir1.ChildDirs = []*embedded.EmbeddedDir{ + dir4, // "mycnf" + dirh, // "zkcfg" + + } + dir4.ChildDirs = []*embedded.EmbeddedDir{} + dirh.ChildDirs = []*embedded.EmbeddedDir{} + + // register embeddedBox + embedded.RegisterEmbeddedBox(`../../../config`, &embedded.EmbeddedBox{ + Name: `../../../config`, + Time: time.Unix(1578267519, 0), + Dirs: map[string]*embedded.EmbeddedDir{ + "": dir1, + "mycnf": dir4, + "zkcfg": dirh, + }, + Files: map[string]*embedded.EmbeddedFile{ + "gomysql.pc.tmpl": file2, + "init_db.sql": file3, + "mycnf/default-fast.cnf": file5, + "mycnf/default.cnf": file6, + "mycnf/master_mariadb100.cnf": file7, + "mycnf/master_mariadb101.cnf": file8, + "mycnf/master_mariadb102.cnf": file9, + "mycnf/master_mariadb103.cnf": filea, + "mycnf/master_mariadb104.cnf": fileb, + "mycnf/master_mysql56.cnf": filec, + "mycnf/master_mysql57.cnf": filed, + "mycnf/master_mysql80.cnf": filee, + "mycnf/sbr.cnf": filef, + "zk-client-dev.json": fileg, + "zkcfg/zoo.cfg": filei, + }, + }) +} diff --git a/go/vt/mysqlctl/schema.go b/go/vt/mysqlctl/schema.go index dd2a91e15d9..18706cb36ed 100644 --- a/go/vt/mysqlctl/schema.go +++ b/go/vt/mysqlctl/schema.go @@ -25,7 +25,6 @@ import ( "vitess.io/vitess/go/sqlescape" "vitess.io/vitess/go/sqltypes" - "vitess.io/vitess/go/vt/dbconfigs" "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/mysqlctl/tmutils" @@ -38,7 +37,7 @@ var autoIncr = regexp.MustCompile(` AUTO_INCREMENT=\d+`) // executeSchemaCommands executes some SQL commands, using the mysql // command line tool. It uses the dba connection parameters, with credentials. func (mysqld *Mysqld) executeSchemaCommands(sql string) error { - params, err := dbconfigs.WithCredentials(mysqld.dbcfgs.Dba()) + params, err := mysqld.dbcfgs.Dba().MysqlParams() if err != nil { return err } diff --git a/go/vt/mysqlctl/xtrabackupengine.go b/go/vt/mysqlctl/xtrabackupengine.go index 08d18638bce..6572064fa86 100644 --- a/go/vt/mysqlctl/xtrabackupengine.go +++ b/go/vt/mysqlctl/xtrabackupengine.go @@ -328,7 +328,11 @@ func (be *XtrabackupEngine) backupFiles(ctx context.Context, params BackupParams // Enforce minimum block size. blockSize = 1024 } - if _, err := copyToStripes(destWriters, backupOut, blockSize); err != nil { + // Add a buffer in front of the raw stdout pipe so io.CopyN() can use the + // buffered reader's WriteTo() method instead of allocating a new buffer + // every time. + backupOutBuf := bufio.NewReaderSize(backupOut, int(blockSize)) + if _, err := copyToStripes(destWriters, backupOutBuf, blockSize); err != nil { return replicationPosition, vterrors.Wrap(err, "cannot copy output from xtrabackup command") } diff --git a/go/vt/proto/binlogdata/binlogdata.pb.go b/go/vt/proto/binlogdata/binlogdata.pb.go index 904d001d423..564619addf2 100644 --- a/go/vt/proto/binlogdata/binlogdata.pb.go +++ b/go/vt/proto/binlogdata/binlogdata.pb.go @@ -56,29 +56,36 @@ func (OnDDLAction) EnumDescriptor() ([]byte, []int) { return fileDescriptor_5fd02bcb2e350dad, []int{0} } -// VEventType enumerates the event types. -// This list is comprehensive. Many of these types +// VEventType enumerates the event types. Many of these types // will not be encountered in RBR mode. type VEventType int32 const ( - VEventType_UNKNOWN VEventType = 0 - VEventType_GTID VEventType = 1 - VEventType_BEGIN VEventType = 2 - VEventType_COMMIT VEventType = 3 - VEventType_ROLLBACK VEventType = 4 - VEventType_DDL VEventType = 5 - VEventType_INSERT VEventType = 6 - VEventType_REPLACE VEventType = 7 - VEventType_UPDATE VEventType = 8 - VEventType_DELETE VEventType = 9 - VEventType_SET VEventType = 10 - VEventType_OTHER VEventType = 11 - VEventType_ROW VEventType = 12 - VEventType_FIELD VEventType = 13 + VEventType_UNKNOWN VEventType = 0 + VEventType_GTID VEventType = 1 + VEventType_BEGIN VEventType = 2 + VEventType_COMMIT VEventType = 3 + VEventType_ROLLBACK VEventType = 4 + VEventType_DDL VEventType = 5 + // INSERT, REPLACE, UPDATE, DELETE and SET will not be seen in RBR mode. + VEventType_INSERT VEventType = 6 + VEventType_REPLACE VEventType = 7 + VEventType_UPDATE VEventType = 8 + VEventType_DELETE VEventType = 9 + VEventType_SET VEventType = 10 + // OTHER is a dummy event. If encountered, the current GTID must be + // recorded by the client to be able to resume. + VEventType_OTHER VEventType = 11 + VEventType_ROW VEventType = 12 + VEventType_FIELD VEventType = 13 + // HEARTBEAT is sent if there is inactivity. If a client does not + // receive events beyond the hearbeat interval, it can assume that it's + // lost connection to the vstreamer. VEventType_HEARTBEAT VEventType = 14 - VEventType_VGTID VEventType = 15 - VEventType_JOURNAL VEventType = 16 + // VGTID is generated by VTGate's VStream that combines multiple + // GTIDs. + VEventType_VGTID VEventType = 15 + VEventType_JOURNAL VEventType = 16 ) var VEventType_name = map[int32]string{ @@ -596,14 +603,28 @@ func (m *StreamTablesResponse) GetBinlogTransaction() *BinlogTransaction { return nil } -// Rule represents one rule. +// Rule represents one rule in a Filter. type Rule struct { - // match can be a table name or a regular expression - // delineated by '/' and '/'. + // Match can be a table name or a regular expression. + // If it starts with a '/', it's a regular expression. + // For example, "t" matches a table named "t", whereas + // "/t.*" matches all tables that begin with 't'. Match string `protobuf:"bytes,1,opt,name=match,proto3" json:"match,omitempty"` - // filter can be an empty string or keyrange if the match - // is a regular expression. Otherwise, it must be a select - // query. + // Filter: If empty, all columns and rows of the matching tables + // are sent. If it's a keyrange like "-80", only rows that + // match the keyrange are sent. + // If Match is a table name instead of a regular expression, + // the Filter can also be a select expression like this: + // "select * from t", same as an empty Filter, or + // "select * from t where in_keyrange('-80')", same as "-80", or + // "select col1, col2 from t where in_keyrange(col1, 'hash', '-80'), or + // What is allowed in a select expression depends on whether + // it's a vstreamer or vreplication request. For more details, + // please refer to the specific package documentation. + // On the vreplication side, Filter can also accept a special + // "exclude" value, which will cause the matched tables + // to be excluded. + // TODO(sougou): support this on vstreamer side also. Filter string `protobuf:"bytes,2,opt,name=filter,proto3" json:"filter,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -649,10 +670,18 @@ func (m *Rule) GetFilter() string { return "" } -// Filter represents a list of ordered rules. First match -// wins. +// Filter represents a list of ordered rules. The first +// match wins. type Filter struct { - Rules []*Rule `protobuf:"bytes,1,rep,name=rules,proto3" json:"rules,omitempty"` + Rules []*Rule `protobuf:"bytes,1,rep,name=rules,proto3" json:"rules,omitempty"` + // FieldEventMode specifies the behavior if there is a mismatch + // between the current schema and the fields in the binlog. This + // can happen if the binlog position is before a DDL that would + // cause the fields to change. If vstreamer detects such + // an inconsistency, the behavior depends on the FieldEventMode. + // If the value is ERR_ON_MISMATCH (default), then it errors out. + // If it's BEST_EFFORT, it sends a field event with fake column + // names as "@1", "@2", etc. FieldEventMode Filter_FieldEventMode `protobuf:"varint,2,opt,name=fieldEventMode,proto3,enum=binlogdata.Filter_FieldEventMode" json:"fieldEventMode,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -699,8 +728,8 @@ func (m *Filter) GetFieldEventMode() Filter_FieldEventMode { } // BinlogSource specifies the source and filter parameters for -// Filtered Replication. It currently supports a keyrange -// or a list of tables. +// Filtered Replication. KeyRange and Tables are legacy. Filter +// is the new way to specify the filtering rules. type BinlogSource struct { // the source keyspace Keyspace string `protobuf:"bytes,1,opt,name=keyspace,proto3" json:"keyspace,omitempty"` @@ -708,18 +737,24 @@ type BinlogSource struct { Shard string `protobuf:"bytes,2,opt,name=shard,proto3" json:"shard,omitempty"` // the source tablet type TabletType topodata.TabletType `protobuf:"varint,3,opt,name=tablet_type,json=tabletType,proto3,enum=topodata.TabletType" json:"tablet_type,omitempty"` - // key_range is set if the request is for a keyrange + // KeyRange is set if the request is for a keyrange KeyRange *topodata.KeyRange `protobuf:"bytes,4,opt,name=key_range,json=keyRange,proto3" json:"key_range,omitempty"` - // tables is set if the request is for a list of tables + // Tables is set if the request is for a list of tables Tables []string `protobuf:"bytes,5,rep,name=tables,proto3" json:"tables,omitempty"` - // filter is set if we're using the generalized representation + // Filter is set if we're using the generalized representation // for the filter. Filter *Filter `protobuf:"bytes,6,opt,name=filter,proto3" json:"filter,omitempty"` - // on_ddl specifies the action to be taken when a DDL is encountered. - OnDdl OnDDLAction `protobuf:"varint,7,opt,name=on_ddl,json=onDdl,proto3,enum=binlogdata.OnDDLAction" json:"on_ddl,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + // OnDdl specifies the action to be taken when a DDL is encountered. + OnDdl OnDDLAction `protobuf:"varint,7,opt,name=on_ddl,json=onDdl,proto3,enum=binlogdata.OnDDLAction" json:"on_ddl,omitempty"` + // Source is an external mysql. This attribute should be set to the username + // to use in the connection + ExternalMysql string `protobuf:"bytes,8,opt,name=external_mysql,json=externalMysql,proto3" json:"external_mysql,omitempty"` + // StopAfterCopy specifies if vreplication should be stopped + // after copying is done. + StopAfterCopy bool `protobuf:"varint,9,opt,name=stop_after_copy,json=stopAfterCopy,proto3" json:"stop_after_copy,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *BinlogSource) Reset() { *m = BinlogSource{} } @@ -796,7 +831,24 @@ func (m *BinlogSource) GetOnDdl() OnDDLAction { return OnDDLAction_IGNORE } -// RowChange represents one row change +func (m *BinlogSource) GetExternalMysql() string { + if m != nil { + return m.ExternalMysql + } + return "" +} + +func (m *BinlogSource) GetStopAfterCopy() bool { + if m != nil { + return m.StopAfterCopy + } + return false +} + +// RowChange represents one row change. +// If Before is set and not After, it's a delete. +// If After is set and not Before, it's an insert. +// If both are set, it's an update. type RowChange struct { Before *query.Row `protobuf:"bytes,1,opt,name=before,proto3" json:"before,omitempty"` After *query.Row `protobuf:"bytes,2,opt,name=after,proto3" json:"after,omitempty"` @@ -844,7 +896,7 @@ func (m *RowChange) GetAfter() *query.Row { return nil } -// RowEvent represent row events for one table +// RowEvent represent row events for one table. type RowEvent struct { TableName string `protobuf:"bytes,1,opt,name=table_name,json=tableName,proto3" json:"table_name,omitempty"` RowChanges []*RowChange `protobuf:"bytes,2,rep,name=row_changes,json=rowChanges,proto3" json:"row_changes,omitempty"` @@ -892,6 +944,7 @@ func (m *RowEvent) GetRowChanges() []*RowChange { return nil } +// FieldEvent represents the field info for a table. type FieldEvent struct { TableName string `protobuf:"bytes,1,opt,name=table_name,json=tableName,proto3" json:"table_name,omitempty"` Fields []*query.Field `protobuf:"bytes,2,rep,name=fields,proto3" json:"fields,omitempty"` @@ -939,6 +992,11 @@ func (m *FieldEvent) GetFields() []*query.Field { return nil } +// ShardGtid contains the GTID position for one shard. +// It's used in a request for requesting a starting position. +// It's used in a response to transmit the current position +// of a shard. It's also used in a Journal to indicate the +// list of targets and shard positions to migrate to. type ShardGtid struct { Keyspace string `protobuf:"bytes,1,opt,name=keyspace,proto3" json:"keyspace,omitempty"` Shard string `protobuf:"bytes,2,opt,name=shard,proto3" json:"shard,omitempty"` @@ -994,6 +1052,7 @@ func (m *ShardGtid) GetGtid() string { return "" } +// A VGtid is a list of ShardGtids. type VGtid struct { ShardGtids []*ShardGtid `protobuf:"bytes,1,rep,name=shard_gtids,json=shardGtids,proto3" json:"shard_gtids,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -1033,6 +1092,7 @@ func (m *VGtid) GetShardGtids() []*ShardGtid { return nil } +// KeyspaceShard represents a keyspace and shard. type KeyspaceShard struct { Keyspace string `protobuf:"bytes,1,opt,name=keyspace,proto3" json:"keyspace,omitempty"` Shard string `protobuf:"bytes,2,opt,name=shard,proto3" json:"shard,omitempty"` @@ -1080,17 +1140,35 @@ func (m *KeyspaceShard) GetShard() string { return "" } +// Journal contains the metadata for a journal event. +// The commit of a journal event indicates the point of no return +// for a migration. type Journal struct { - Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` - MigrationType MigrationType `protobuf:"varint,2,opt,name=migration_type,json=migrationType,proto3,enum=binlogdata.MigrationType" json:"migration_type,omitempty"` - Tables []string `protobuf:"bytes,3,rep,name=tables,proto3" json:"tables,omitempty"` - LocalPosition string `protobuf:"bytes,4,opt,name=local_position,json=localPosition,proto3" json:"local_position,omitempty"` - ShardGtids []*ShardGtid `protobuf:"bytes,5,rep,name=shard_gtids,json=shardGtids,proto3" json:"shard_gtids,omitempty"` - Participants []*KeyspaceShard `protobuf:"bytes,6,rep,name=participants,proto3" json:"participants,omitempty"` - SourceWorkflows []string `protobuf:"bytes,7,rep,name=source_workflows,json=sourceWorkflows,proto3" json:"source_workflows,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + // Id represents a unique journal id. + Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + MigrationType MigrationType `protobuf:"varint,2,opt,name=migration_type,json=migrationType,proto3,enum=binlogdata.MigrationType" json:"migration_type,omitempty"` + // Tables is set if the journal represents a TABLES migration. + Tables []string `protobuf:"bytes,3,rep,name=tables,proto3" json:"tables,omitempty"` + // LocalPosition is the source position at which the migration happened. + LocalPosition string `protobuf:"bytes,4,opt,name=local_position,json=localPosition,proto3" json:"local_position,omitempty"` + // ShardGtids is the list of targets to which the migration took place. + ShardGtids []*ShardGtid `protobuf:"bytes,5,rep,name=shard_gtids,json=shardGtids,proto3" json:"shard_gtids,omitempty"` + // Participants is the list of source participants for a migration. + // Every participant is expected to have an identical journal entry. + // While streaming, the client must wait for the journal entry to + // be received from all pariticipants, and then replace them with new + // streams specified by ShardGtid. + // If a stream does not have all participants, a consistent migration + // is not possible. + Participants []*KeyspaceShard `protobuf:"bytes,6,rep,name=participants,proto3" json:"participants,omitempty"` + // SourceWorkflows is the list of workflows in the source shard that + // were migrated to the target. If a migration fails after a Journal + // is committed, this information is used to start the target streams + // that were created prior to the creation of the journal. + SourceWorkflows []string `protobuf:"bytes,7,rep,name=source_workflows,json=sourceWorkflows,proto3" json:"source_workflows,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *Journal) Reset() { *m = Journal{} } @@ -1167,17 +1245,36 @@ func (m *Journal) GetSourceWorkflows() []string { return nil } -// VEvent represents a vstream event +// VEvent represents a vstream event. +// A FieldEvent is sent once for every table, just before +// the first event for that table. The client is expected +// to cache this information and match it against the RowEvent +// which contains the table name. +// A GTID event always precedes a commitable event, which can be +// COMMIT, DDL or OTHER. +// OTHER events are non-material events that have no additional metadata. type VEvent struct { - Type VEventType `protobuf:"varint,1,opt,name=type,proto3,enum=binlogdata.VEventType" json:"type,omitempty"` - Timestamp int64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - Gtid string `protobuf:"bytes,3,opt,name=gtid,proto3" json:"gtid,omitempty"` - Ddl string `protobuf:"bytes,4,opt,name=ddl,proto3" json:"ddl,omitempty"` - RowEvent *RowEvent `protobuf:"bytes,5,opt,name=row_event,json=rowEvent,proto3" json:"row_event,omitempty"` + Type VEventType `protobuf:"varint,1,opt,name=type,proto3,enum=binlogdata.VEventType" json:"type,omitempty"` + // Timestamp is the binlog timestamp in seconds. + // The value should be ignored if 0. + Timestamp int64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + // Gtid is set if the event type is GTID. + Gtid string `protobuf:"bytes,3,opt,name=gtid,proto3" json:"gtid,omitempty"` + // Ddl is set if the event type is DDL. + Ddl string `protobuf:"bytes,4,opt,name=ddl,proto3" json:"ddl,omitempty"` + // RowEvent is set if the event type is ROW. + RowEvent *RowEvent `protobuf:"bytes,5,opt,name=row_event,json=rowEvent,proto3" json:"row_event,omitempty"` + // FieldEvent is set if the event type is FIELD. FieldEvent *FieldEvent `protobuf:"bytes,6,opt,name=field_event,json=fieldEvent,proto3" json:"field_event,omitempty"` - Vgtid *VGtid `protobuf:"bytes,7,opt,name=vgtid,proto3" json:"vgtid,omitempty"` - Journal *Journal `protobuf:"bytes,8,opt,name=journal,proto3" json:"journal,omitempty"` - // current_time specifies the current time to handle clock skew. + // Vgtid is set if the event type is VGTID. + // This event is only generated by VTGate's VStream function. + Vgtid *VGtid `protobuf:"bytes,7,opt,name=vgtid,proto3" json:"vgtid,omitempty"` + // Journal is set if the event type is JOURNAL. + Journal *Journal `protobuf:"bytes,8,opt,name=journal,proto3" json:"journal,omitempty"` + // Dml is set if the event type is INSERT, REPLACE, UPDATE or DELETE. + Dml string `protobuf:"bytes,9,opt,name=dml,proto3" json:"dml,omitempty"` + // CurrentTime specifies the current time when the message was sent. + // This can be used to compenssate for clock skew. CurrentTime int64 `protobuf:"varint,20,opt,name=current_time,json=currentTime,proto3" json:"current_time,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -1265,6 +1362,13 @@ func (m *VEvent) GetJournal() *Journal { return nil } +func (m *VEvent) GetDml() string { + if m != nil { + return m.Dml + } + return "" +} + func (m *VEvent) GetCurrentTime() int64 { if m != nil { return m.CurrentTime @@ -1272,7 +1376,7 @@ func (m *VEvent) GetCurrentTime() int64 { return 0 } -// VStreamRequest is the payload for VStream +// VStreamRequest is the payload for VStreamer type VStreamRequest struct { EffectiveCallerId *vtrpc.CallerID `protobuf:"bytes,1,opt,name=effective_caller_id,json=effectiveCallerId,proto3" json:"effective_caller_id,omitempty"` ImmediateCallerId *query.VTGateCallerID `protobuf:"bytes,2,opt,name=immediate_caller_id,json=immediateCallerId,proto3" json:"immediate_caller_id,omitempty"` @@ -1344,7 +1448,7 @@ func (m *VStreamRequest) GetFilter() *Filter { return nil } -// VStreamResponse is the response from VStream +// VStreamResponse is the response from VStreamer type VStreamResponse struct { Events []*VEvent `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -1685,108 +1789,112 @@ func init() { func init() { proto.RegisterFile("binlogdata.proto", fileDescriptor_5fd02bcb2e350dad) } var fileDescriptor_5fd02bcb2e350dad = []byte{ - // 1648 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x58, 0x4b, 0x73, 0xe3, 0x4a, - 0x15, 0x8e, 0x6c, 0xf9, 0x75, 0x94, 0x38, 0x4a, 0xe7, 0x81, 0x49, 0x71, 0xa9, 0x5c, 0x15, 0x97, - 0xe4, 0xa6, 0x0a, 0x07, 0x0c, 0x0c, 0xab, 0xcb, 0xc5, 0x0f, 0x25, 0x71, 0x22, 0xdb, 0x99, 0xb6, - 0x92, 0xa1, 0x66, 0xa3, 0x52, 0xec, 0x76, 0x22, 0x22, 0x4b, 0x1e, 0xa9, 0x9d, 0x90, 0x1f, 0x40, - 0xf1, 0x03, 0xd8, 0xf2, 0x07, 0x58, 0xb3, 0x85, 0x2d, 0x7b, 0xf6, 0x54, 0xb1, 0xe2, 0x7f, 0x50, - 0xfd, 0x90, 0x6c, 0x25, 0xc3, 0x4c, 0x66, 0xaa, 0x58, 0xc0, 0xc6, 0x75, 0xfa, 0xf4, 0x39, 0xa7, - 0xcf, 0xf9, 0xce, 0xa3, 0xd5, 0x06, 0xfd, 0xda, 0x0b, 0xfc, 0xf0, 0x66, 0xec, 0x52, 0xb7, 0x3e, - 0x8b, 0x42, 0x1a, 0x22, 0x58, 0x70, 0x76, 0xb5, 0x7b, 0x1a, 0xcd, 0x46, 0x62, 0x63, 0x57, 0x7b, - 0x37, 0x27, 0xd1, 0xa3, 0x5c, 0x54, 0x69, 0x38, 0x0b, 0x17, 0x5a, 0x46, 0x0f, 0x4a, 0xed, 0x5b, - 0x37, 0x8a, 0x09, 0x45, 0x3b, 0x50, 0x1c, 0xf9, 0x1e, 0x09, 0x68, 0x4d, 0xd9, 0x53, 0x0e, 0x0a, - 0x58, 0xae, 0x10, 0x02, 0x75, 0x14, 0x06, 0x41, 0x2d, 0xc7, 0xb9, 0x9c, 0x66, 0xb2, 0x31, 0x89, - 0xee, 0x49, 0x54, 0xcb, 0x0b, 0x59, 0xb1, 0x32, 0xfe, 0x95, 0x87, 0x8d, 0x16, 0xf7, 0xc3, 0x8e, - 0xdc, 0x20, 0x76, 0x47, 0xd4, 0x0b, 0x03, 0x74, 0x02, 0x10, 0x53, 0x97, 0x92, 0x29, 0x09, 0x68, - 0x5c, 0x53, 0xf6, 0xf2, 0x07, 0x5a, 0x63, 0xbf, 0xbe, 0x14, 0xc1, 0x33, 0x95, 0xfa, 0x30, 0x91, - 0xc7, 0x4b, 0xaa, 0xa8, 0x01, 0x1a, 0xb9, 0x27, 0x01, 0x75, 0x68, 0x78, 0x47, 0x82, 0x9a, 0xba, - 0xa7, 0x1c, 0x68, 0x8d, 0x8d, 0xba, 0x08, 0xd0, 0x64, 0x3b, 0x36, 0xdb, 0xc0, 0x40, 0x52, 0x7a, - 0xf7, 0x6f, 0x39, 0xa8, 0xa4, 0xd6, 0x90, 0x05, 0xe5, 0x91, 0x4b, 0xc9, 0x4d, 0x18, 0x3d, 0xf2, - 0x30, 0xab, 0x8d, 0x1f, 0xbf, 0xd0, 0x91, 0x7a, 0x5b, 0xea, 0xe1, 0xd4, 0x02, 0xfa, 0x11, 0x94, - 0x46, 0x02, 0x3d, 0x8e, 0x8e, 0xd6, 0xd8, 0x5c, 0x36, 0x26, 0x81, 0xc5, 0x89, 0x0c, 0xd2, 0x21, - 0x1f, 0xbf, 0xf3, 0x39, 0x64, 0xab, 0x98, 0x91, 0xc6, 0x9f, 0x14, 0x28, 0x27, 0x76, 0xd1, 0x26, - 0xac, 0xb7, 0x2c, 0xe7, 0xb2, 0x8f, 0xcd, 0xf6, 0xe0, 0xa4, 0xdf, 0x7d, 0x6b, 0x76, 0xf4, 0x15, - 0xb4, 0x0a, 0xe5, 0x96, 0xe5, 0xb4, 0xcc, 0x93, 0x6e, 0x5f, 0x57, 0xd0, 0x1a, 0x54, 0x5a, 0x96, - 0xd3, 0x1e, 0xf4, 0x7a, 0x5d, 0x5b, 0xcf, 0xa1, 0x75, 0xd0, 0x5a, 0x96, 0x83, 0x07, 0x96, 0xd5, - 0x6a, 0xb6, 0xcf, 0xf5, 0x3c, 0xda, 0x86, 0x8d, 0x96, 0xe5, 0x74, 0x7a, 0x96, 0xd3, 0x31, 0x2f, - 0xb0, 0xd9, 0x6e, 0xda, 0x66, 0x47, 0x57, 0x11, 0x40, 0x91, 0xb1, 0x3b, 0x96, 0x5e, 0x90, 0xf4, - 0xd0, 0xb4, 0xf5, 0xa2, 0x34, 0xd7, 0xed, 0x0f, 0x4d, 0x6c, 0xeb, 0x25, 0xb9, 0xbc, 0xbc, 0xe8, - 0x34, 0x6d, 0x53, 0x2f, 0xcb, 0x65, 0xc7, 0xb4, 0x4c, 0xdb, 0xd4, 0x2b, 0x67, 0x6a, 0x39, 0xa7, - 0xe7, 0xcf, 0xd4, 0x72, 0x5e, 0x57, 0x8d, 0x3f, 0x28, 0xb0, 0x3d, 0xa4, 0x11, 0x71, 0xa7, 0xe7, - 0xe4, 0x11, 0xbb, 0xc1, 0x0d, 0xc1, 0xe4, 0xdd, 0x9c, 0xc4, 0x14, 0xed, 0x42, 0x79, 0x16, 0xc6, - 0x1e, 0xc3, 0x8e, 0x03, 0x5c, 0xc1, 0xe9, 0x1a, 0x1d, 0x41, 0xe5, 0x8e, 0x3c, 0x3a, 0x11, 0x93, - 0x97, 0x80, 0xa1, 0x7a, 0x5a, 0x90, 0xa9, 0xa5, 0xf2, 0x9d, 0xa4, 0x96, 0xf1, 0xcd, 0x7f, 0x1c, - 0x5f, 0x63, 0x02, 0x3b, 0x4f, 0x9d, 0x8a, 0x67, 0x61, 0x10, 0x13, 0x64, 0x01, 0x12, 0x8a, 0x0e, - 0x5d, 0xe4, 0x96, 0xfb, 0xa7, 0x35, 0xbe, 0xf8, 0x60, 0x01, 0xe0, 0x8d, 0xeb, 0xa7, 0x2c, 0xe3, - 0xb7, 0xb0, 0x29, 0xce, 0xb1, 0xdd, 0x6b, 0x9f, 0xc4, 0x2f, 0x09, 0x7d, 0x07, 0x8a, 0x94, 0x0b, - 0xd7, 0x72, 0x7b, 0xf9, 0x83, 0x0a, 0x96, 0xab, 0x4f, 0x8d, 0x70, 0x0c, 0x5b, 0xd9, 0x93, 0xff, - 0x2b, 0xf1, 0xfd, 0x0c, 0x54, 0x3c, 0xf7, 0x09, 0xda, 0x82, 0xc2, 0xd4, 0xa5, 0xa3, 0x5b, 0x19, - 0x8d, 0x58, 0xb0, 0x50, 0x26, 0x9e, 0x4f, 0x49, 0xc4, 0x53, 0x58, 0xc1, 0x72, 0x65, 0xfc, 0x59, - 0x81, 0xe2, 0x31, 0x27, 0xd1, 0x0f, 0xa1, 0x10, 0xcd, 0x59, 0xb0, 0xa2, 0xd7, 0xf5, 0x65, 0x0f, - 0x98, 0x65, 0x2c, 0xb6, 0x51, 0x17, 0xaa, 0x13, 0x8f, 0xf8, 0x63, 0xde, 0xba, 0xbd, 0x70, 0x2c, - 0xaa, 0xa2, 0xda, 0xf8, 0x72, 0x59, 0x41, 0xd8, 0xac, 0x1f, 0x67, 0x04, 0xf1, 0x13, 0x45, 0xe3, - 0x15, 0x54, 0xb3, 0x12, 0xac, 0x9d, 0x4c, 0x8c, 0x9d, 0x41, 0xdf, 0xe9, 0x75, 0x87, 0xbd, 0xa6, - 0xdd, 0x3e, 0xd5, 0x57, 0x78, 0xc7, 0x98, 0x43, 0xdb, 0x31, 0x8f, 0x8f, 0x07, 0xd8, 0xd6, 0x15, - 0xe3, 0x8f, 0x39, 0x58, 0x15, 0xa0, 0x0c, 0xc3, 0x79, 0x34, 0x22, 0x2c, 0x8b, 0x77, 0xe4, 0x31, - 0x9e, 0xb9, 0x23, 0x92, 0x64, 0x31, 0x59, 0x33, 0x40, 0xe2, 0x5b, 0x37, 0x1a, 0xcb, 0xc8, 0xc5, - 0x02, 0xfd, 0x1c, 0x34, 0x9e, 0x4d, 0xea, 0xd0, 0xc7, 0x19, 0xe1, 0x79, 0xac, 0x36, 0xb6, 0x16, - 0x85, 0xcd, 0x73, 0x45, 0xed, 0xc7, 0x19, 0xc1, 0x40, 0x53, 0x3a, 0xdb, 0x0d, 0xea, 0x0b, 0xba, - 0x61, 0x51, 0x43, 0x85, 0x4c, 0x0d, 0x1d, 0xa6, 0x09, 0x29, 0x4a, 0x2b, 0xcf, 0xd0, 0x4b, 0x92, - 0x84, 0xea, 0x50, 0x0c, 0x03, 0x67, 0x3c, 0xf6, 0x6b, 0x25, 0xee, 0xe6, 0x77, 0x96, 0x65, 0x07, - 0x41, 0xa7, 0x63, 0x35, 0x45, 0x59, 0x14, 0xc2, 0xa0, 0x33, 0xf6, 0x8d, 0xd7, 0x50, 0xc1, 0xe1, - 0x43, 0xfb, 0x96, 0x3b, 0x60, 0x40, 0xf1, 0x9a, 0x4c, 0xc2, 0x88, 0xc8, 0xca, 0x02, 0x39, 0x79, - 0x71, 0xf8, 0x80, 0xe5, 0x0e, 0xda, 0x83, 0x82, 0x3b, 0x49, 0x8a, 0x23, 0x2b, 0x22, 0x36, 0x0c, - 0x17, 0xca, 0x38, 0x7c, 0xe0, 0x79, 0x42, 0x5f, 0x80, 0x40, 0xc4, 0x09, 0xdc, 0x69, 0x02, 0x77, - 0x85, 0x73, 0xfa, 0xee, 0x94, 0xa0, 0x57, 0xa0, 0x45, 0xe1, 0x83, 0x33, 0xe2, 0xc7, 0x8b, 0xd6, - 0xd1, 0x1a, 0xdb, 0x99, 0x6a, 0x4a, 0x9c, 0xc3, 0x10, 0x25, 0x64, 0x6c, 0xbc, 0x06, 0x58, 0x14, - 0xc3, 0xc7, 0x0e, 0xf9, 0x01, 0x83, 0x8f, 0xf8, 0xe3, 0xc4, 0xfe, 0xaa, 0x74, 0x99, 0x5b, 0xc0, - 0x72, 0x8f, 0x01, 0x31, 0x64, 0xd9, 0x3e, 0xa1, 0xde, 0xf8, 0x33, 0x6a, 0x04, 0x81, 0x7a, 0x43, - 0xbd, 0x31, 0x2f, 0x8e, 0x0a, 0xe6, 0xb4, 0xf1, 0x2d, 0x14, 0xae, 0xb8, 0xb9, 0x57, 0xa0, 0x71, - 0x29, 0x87, 0xb1, 0x93, 0xa6, 0xc9, 0x84, 0x99, 0x1e, 0x8d, 0x21, 0x4e, 0xc8, 0xd8, 0x68, 0xc2, - 0xda, 0xb9, 0x3c, 0x96, 0x0b, 0x7c, 0xba, 0x5f, 0xc6, 0x5f, 0x72, 0x50, 0x3a, 0x0b, 0xe7, 0x51, - 0xe0, 0xfa, 0xa8, 0x0a, 0x39, 0x6f, 0xcc, 0xf5, 0xf2, 0x38, 0xe7, 0x8d, 0xd1, 0xaf, 0xa0, 0x3a, - 0xf5, 0x6e, 0x22, 0x97, 0xd5, 0x83, 0x28, 0x6d, 0xd1, 0x9d, 0xdf, 0x5d, 0xf6, 0xac, 0x97, 0x48, - 0xf0, 0xfa, 0x5e, 0x9b, 0x2e, 0x2f, 0x97, 0x2a, 0x36, 0x9f, 0xa9, 0xd8, 0xaf, 0xa0, 0xea, 0x87, - 0x23, 0xd7, 0x77, 0xd2, 0x79, 0xa9, 0x72, 0xa7, 0xd6, 0x38, 0xf7, 0x22, 0x19, 0x9a, 0x4f, 0x70, - 0x29, 0xbc, 0x10, 0x17, 0xf4, 0x0d, 0xac, 0xce, 0xdc, 0x88, 0x7a, 0x23, 0x6f, 0xe6, 0xb2, 0x2f, - 0x8e, 0x22, 0x57, 0xcc, 0xb8, 0x9d, 0xc1, 0x0d, 0x67, 0xc4, 0xd1, 0xd7, 0xa0, 0xc7, 0x7c, 0x16, - 0x38, 0x0f, 0x61, 0x74, 0x37, 0xf1, 0xc3, 0x87, 0xb8, 0x56, 0xe2, 0xfe, 0xaf, 0x0b, 0xfe, 0x9b, - 0x84, 0x6d, 0xfc, 0x33, 0x07, 0xc5, 0x2b, 0x51, 0x65, 0x87, 0xa0, 0x72, 0x8c, 0xc4, 0x57, 0xc5, - 0xce, 0xf2, 0x61, 0x42, 0x82, 0x03, 0xc4, 0x65, 0xd0, 0xf7, 0xa0, 0x42, 0xbd, 0x29, 0x89, 0xa9, - 0x3b, 0x9d, 0x71, 0x50, 0xf3, 0x78, 0xc1, 0x78, 0x5f, 0xad, 0xb0, 0x4f, 0x07, 0xd6, 0xb4, 0x02, - 0x26, 0x46, 0xa2, 0x9f, 0x40, 0x85, 0xf5, 0x06, 0xff, 0xd2, 0xa9, 0x15, 0x78, 0xb3, 0x6d, 0x3d, - 0xe9, 0x0c, 0x7e, 0x2c, 0x2e, 0x47, 0x49, 0xb7, 0xfd, 0x02, 0x34, 0x5e, 0xcd, 0x52, 0x49, 0x4c, - 0x8b, 0x9d, 0xec, 0xb4, 0x48, 0xba, 0x06, 0xc3, 0x62, 0xc0, 0xa2, 0x7d, 0x28, 0xdc, 0x73, 0x97, - 0x4a, 0xf2, 0x8b, 0x6b, 0x39, 0x38, 0x0e, 0xbf, 0xd8, 0x67, 0xd7, 0xd9, 0x6f, 0x44, 0x35, 0xd5, - 0xca, 0xcf, 0xaf, 0x33, 0x59, 0x68, 0x38, 0x91, 0x41, 0x5f, 0xc2, 0xea, 0x68, 0x1e, 0x45, 0xfc, - 0x8b, 0xce, 0x9b, 0x92, 0xda, 0x16, 0x87, 0x42, 0x93, 0x3c, 0xdb, 0x9b, 0x12, 0xe3, 0xf7, 0x39, - 0xa8, 0x5e, 0x89, 0x3b, 0x2f, 0xb9, 0x67, 0xbf, 0x85, 0x4d, 0x32, 0x99, 0x90, 0x11, 0xf5, 0xee, - 0x89, 0x33, 0x72, 0x7d, 0x9f, 0x44, 0x8e, 0x2c, 0x5c, 0xad, 0xb1, 0x5e, 0x17, 0xdf, 0xbe, 0x6d, - 0xce, 0xef, 0x76, 0xf0, 0x46, 0x2a, 0x2b, 0x59, 0x63, 0x64, 0xc2, 0xa6, 0x37, 0x9d, 0x92, 0xb1, - 0xe7, 0xd2, 0x65, 0x03, 0x62, 0x62, 0x6d, 0xcb, 0xf6, 0xbf, 0xb2, 0x4f, 0x5c, 0x4a, 0x16, 0x66, - 0x52, 0x8d, 0xd4, 0xcc, 0x57, 0xac, 0xba, 0xa3, 0x9b, 0xf4, 0xea, 0x5e, 0x93, 0x9a, 0x36, 0x67, - 0x62, 0xb9, 0x99, 0xf9, 0x2c, 0x50, 0x9f, 0x7c, 0x16, 0x2c, 0x46, 0x77, 0xe1, 0x63, 0xa3, 0xdb, - 0xf8, 0x06, 0xd6, 0x53, 0x20, 0xe4, 0xb5, 0x7f, 0x08, 0x45, 0x9e, 0xca, 0x64, 0x66, 0xa0, 0xe7, - 0x55, 0x87, 0xa5, 0x84, 0xf1, 0xbb, 0x1c, 0xa0, 0x44, 0x3f, 0x7c, 0x88, 0xff, 0x47, 0xc1, 0xdc, - 0x82, 0x02, 0xe7, 0x4b, 0x24, 0xc5, 0x82, 0xe1, 0xe0, 0xbb, 0x31, 0x9d, 0xdd, 0xa5, 0x30, 0x0a, - 0xe5, 0xd7, 0xec, 0x17, 0x93, 0x78, 0xee, 0x53, 0x2c, 0x25, 0x8c, 0xbf, 0x2a, 0xb0, 0x99, 0xc1, - 0x41, 0x62, 0xb9, 0xb8, 0x06, 0x94, 0xff, 0x7c, 0x0d, 0xa0, 0x03, 0x28, 0xcf, 0xee, 0x3e, 0x70, - 0x5d, 0xa4, 0xbb, 0xef, 0xed, 0xe2, 0xef, 0x83, 0x1a, 0xb1, 0x69, 0xa2, 0x72, 0xcd, 0xe5, 0xbb, - 0x91, 0xf3, 0xd9, 0x05, 0x9b, 0x89, 0x23, 0x73, 0xc1, 0x4a, 0xff, 0xff, 0xa1, 0xc0, 0xf6, 0xa2, - 0x0e, 0xe6, 0x3e, 0xfd, 0xbf, 0x4a, 0xa5, 0x11, 0xc1, 0xce, 0xd3, 0xe8, 0x3e, 0x29, 0x41, 0x9f, - 0x01, 0xfb, 0xe1, 0x2f, 0x41, 0x5b, 0xfa, 0xf4, 0x61, 0x2f, 0xa4, 0xee, 0x49, 0x7f, 0x80, 0x4d, - 0x7d, 0x05, 0x95, 0x41, 0x1d, 0xda, 0x83, 0x0b, 0x5d, 0x61, 0x94, 0xf9, 0x6b, 0xb3, 0x2d, 0x5e, - 0x5d, 0x8c, 0x72, 0xa4, 0x50, 0xfe, 0xf0, 0xef, 0x0a, 0xc0, 0x62, 0xc6, 0x23, 0x0d, 0x4a, 0x97, - 0xfd, 0xf3, 0xfe, 0xe0, 0x4d, 0x5f, 0x18, 0x38, 0xb1, 0xbb, 0x1d, 0x5d, 0x41, 0x15, 0x28, 0x88, - 0x67, 0x5c, 0x8e, 0x9d, 0x20, 0xdf, 0x70, 0x79, 0xf6, 0xc0, 0x4b, 0x1f, 0x70, 0x2a, 0x2a, 0x41, - 0x3e, 0x7d, 0xa6, 0xc9, 0x77, 0x59, 0x91, 0x19, 0xc4, 0xe6, 0x85, 0xd5, 0x6c, 0x9b, 0x7a, 0x89, - 0x6d, 0xa4, 0x2f, 0x34, 0x80, 0x62, 0xf2, 0x3c, 0x63, 0x9a, 0xec, 0x51, 0x07, 0xec, 0x9c, 0x81, - 0x7d, 0x6a, 0x62, 0x5d, 0x63, 0x3c, 0x3c, 0x78, 0xa3, 0xaf, 0x32, 0xde, 0x71, 0xd7, 0xb4, 0x3a, - 0xfa, 0x1a, 0x7b, 0xd5, 0x9d, 0x9a, 0x4d, 0x6c, 0xb7, 0xcc, 0xa6, 0xad, 0x57, 0xd9, 0xce, 0x15, - 0x77, 0x70, 0x9d, 0x1d, 0x73, 0x36, 0xb8, 0xc4, 0xfd, 0xa6, 0xa5, 0xeb, 0x87, 0xfb, 0xb0, 0x96, - 0xb9, 0xda, 0xd9, 0x59, 0x76, 0xb3, 0x65, 0x99, 0x43, 0x7d, 0x85, 0xd1, 0xc3, 0xd3, 0x26, 0xee, - 0x0c, 0x75, 0xa5, 0xf5, 0xf5, 0xdb, 0xfd, 0x7b, 0x8f, 0x92, 0x38, 0xae, 0x7b, 0xe1, 0x91, 0xa0, - 0x8e, 0x6e, 0xc2, 0xa3, 0x7b, 0x7a, 0xc4, 0xff, 0x61, 0x38, 0x5a, 0x4c, 0xa4, 0xeb, 0x22, 0xe7, - 0xfc, 0xf4, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xe4, 0x09, 0xf3, 0xd7, 0xbd, 0x10, 0x00, 0x00, + // 1709 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x58, 0x4b, 0x73, 0x23, 0x49, + 0x11, 0x9e, 0xd6, 0x5b, 0xd9, 0xb6, 0xdc, 0x2e, 0x3f, 0x10, 0x13, 0x2c, 0xe1, 0xed, 0x60, 0x76, + 0xbc, 0x8e, 0x40, 0x06, 0x01, 0xc3, 0x69, 0x59, 0xf4, 0x68, 0x7b, 0x34, 0xd3, 0x92, 0x3c, 0xa5, + 0x1e, 0x0f, 0xb1, 0x97, 0x8e, 0xb6, 0x54, 0xf6, 0x34, 0xee, 0xd7, 0x74, 0x97, 0xec, 0xd5, 0x0f, + 0x20, 0xf8, 0x01, 0xfc, 0x0a, 0xce, 0x5c, 0xe1, 0xca, 0x9d, 0x3b, 0x57, 0x4e, 0x9c, 0xf8, 0x07, + 0x44, 0x3d, 0xba, 0xd5, 0xad, 0x59, 0x76, 0x3c, 0x1b, 0xc1, 0x01, 0x2e, 0x8a, 0xac, 0xec, 0xcc, + 0xac, 0xcc, 0x2f, 0x1f, 0x55, 0x25, 0xd0, 0xae, 0xdc, 0xc0, 0x0b, 0x6f, 0x16, 0x0e, 0x75, 0x3a, + 0x51, 0x1c, 0xd2, 0x10, 0xc1, 0x9a, 0xf3, 0x58, 0xbd, 0xa3, 0x71, 0x34, 0x17, 0x1f, 0x1e, 0xab, + 0xef, 0x96, 0x24, 0x5e, 0xc9, 0x45, 0x8b, 0x86, 0x51, 0xb8, 0xd6, 0xd2, 0xc7, 0x50, 0x1f, 0xbc, + 0x75, 0xe2, 0x84, 0x50, 0x74, 0x08, 0xb5, 0xb9, 0xe7, 0x92, 0x80, 0xb6, 0x95, 0x23, 0xe5, 0xb8, + 0x8a, 0xe5, 0x0a, 0x21, 0xa8, 0xcc, 0xc3, 0x20, 0x68, 0x97, 0x38, 0x97, 0xd3, 0x4c, 0x36, 0x21, + 0xf1, 0x1d, 0x89, 0xdb, 0x65, 0x21, 0x2b, 0x56, 0xfa, 0x3f, 0xca, 0xb0, 0xdb, 0xe7, 0x7e, 0x58, + 0xb1, 0x13, 0x24, 0xce, 0x9c, 0xba, 0x61, 0x80, 0xce, 0x01, 0x12, 0xea, 0x50, 0xe2, 0x93, 0x80, + 0x26, 0x6d, 0xe5, 0xa8, 0x7c, 0xac, 0x76, 0x9f, 0x76, 0x72, 0x11, 0xbc, 0xa7, 0xd2, 0x99, 0xa5, + 0xf2, 0x38, 0xa7, 0x8a, 0xba, 0xa0, 0x92, 0x3b, 0x12, 0x50, 0x9b, 0x86, 0xb7, 0x24, 0x68, 0x57, + 0x8e, 0x94, 0x63, 0xb5, 0xbb, 0xdb, 0x11, 0x01, 0x1a, 0xec, 0x8b, 0xc5, 0x3e, 0x60, 0x20, 0x19, + 0xfd, 0xf8, 0xaf, 0x25, 0x68, 0x66, 0xd6, 0x90, 0x09, 0x8d, 0xb9, 0x43, 0xc9, 0x4d, 0x18, 0xaf, + 0x78, 0x98, 0xad, 0xee, 0x4f, 0x1e, 0xe8, 0x48, 0x67, 0x20, 0xf5, 0x70, 0x66, 0x01, 0xfd, 0x18, + 0xea, 0x73, 0x81, 0x1e, 0x47, 0x47, 0xed, 0xee, 0xe5, 0x8d, 0x49, 0x60, 0x71, 0x2a, 0x83, 0x34, + 0x28, 0x27, 0xef, 0x3c, 0x0e, 0xd9, 0x16, 0x66, 0xa4, 0xfe, 0x47, 0x05, 0x1a, 0xa9, 0x5d, 0xb4, + 0x07, 0x3b, 0x7d, 0xd3, 0x7e, 0x3d, 0xc1, 0xc6, 0x60, 0x7a, 0x3e, 0x19, 0x7d, 0x65, 0x0c, 0xb5, + 0x47, 0x68, 0x0b, 0x1a, 0x7d, 0xd3, 0xee, 0x1b, 0xe7, 0xa3, 0x89, 0xa6, 0xa0, 0x6d, 0x68, 0xf6, + 0x4d, 0x7b, 0x30, 0x1d, 0x8f, 0x47, 0x96, 0x56, 0x42, 0x3b, 0xa0, 0xf6, 0x4d, 0x1b, 0x4f, 0x4d, + 0xb3, 0xdf, 0x1b, 0xbc, 0xd4, 0xca, 0xe8, 0x00, 0x76, 0xfb, 0xa6, 0x3d, 0x1c, 0x9b, 0xf6, 0xd0, + 0xb8, 0xc0, 0xc6, 0xa0, 0x67, 0x19, 0x43, 0xad, 0x82, 0x00, 0x6a, 0x8c, 0x3d, 0x34, 0xb5, 0xaa, + 0xa4, 0x67, 0x86, 0xa5, 0xd5, 0xa4, 0xb9, 0xd1, 0x64, 0x66, 0x60, 0x4b, 0xab, 0xcb, 0xe5, 0xeb, + 0x8b, 0x61, 0xcf, 0x32, 0xb4, 0x86, 0x5c, 0x0e, 0x0d, 0xd3, 0xb0, 0x0c, 0xad, 0xf9, 0xa2, 0xd2, + 0x28, 0x69, 0xe5, 0x17, 0x95, 0x46, 0x59, 0xab, 0xe8, 0x7f, 0x50, 0xe0, 0x60, 0x46, 0x63, 0xe2, + 0xf8, 0x2f, 0xc9, 0x0a, 0x3b, 0xc1, 0x0d, 0xc1, 0xe4, 0xdd, 0x92, 0x24, 0x14, 0x3d, 0x86, 0x46, + 0x14, 0x26, 0x2e, 0xc3, 0x8e, 0x03, 0xdc, 0xc4, 0xd9, 0x1a, 0x9d, 0x42, 0xf3, 0x96, 0xac, 0xec, + 0x98, 0xc9, 0x4b, 0xc0, 0x50, 0x27, 0x2b, 0xc8, 0xcc, 0x52, 0xe3, 0x56, 0x52, 0x79, 0x7c, 0xcb, + 0x1f, 0xc6, 0x57, 0xbf, 0x86, 0xc3, 0x4d, 0xa7, 0x92, 0x28, 0x0c, 0x12, 0x82, 0x4c, 0x40, 0x42, + 0xd1, 0xa6, 0xeb, 0xdc, 0x72, 0xff, 0xd4, 0xee, 0x27, 0xdf, 0x5a, 0x00, 0x78, 0xf7, 0x6a, 0x93, + 0xa5, 0x7f, 0x0d, 0x7b, 0x62, 0x1f, 0xcb, 0xb9, 0xf2, 0x48, 0xf2, 0x90, 0xd0, 0x0f, 0xa1, 0x46, + 0xb9, 0x70, 0xbb, 0x74, 0x54, 0x3e, 0x6e, 0x62, 0xb9, 0xfa, 0xd8, 0x08, 0x17, 0xb0, 0x5f, 0xdc, + 0xf9, 0xbf, 0x12, 0xdf, 0xcf, 0xa1, 0x82, 0x97, 0x1e, 0x41, 0xfb, 0x50, 0xf5, 0x1d, 0x3a, 0x7f, + 0x2b, 0xa3, 0x11, 0x0b, 0x16, 0xca, 0xb5, 0xeb, 0x51, 0x12, 0xf3, 0x14, 0x36, 0xb1, 0x5c, 0xe9, + 0x7f, 0x52, 0xa0, 0x76, 0xc6, 0x49, 0xf4, 0x19, 0x54, 0xe3, 0x25, 0x0b, 0x56, 0xf4, 0xba, 0x96, + 0xf7, 0x80, 0x59, 0xc6, 0xe2, 0x33, 0x1a, 0x41, 0xeb, 0xda, 0x25, 0xde, 0x82, 0xb7, 0xee, 0x38, + 0x5c, 0x88, 0xaa, 0x68, 0x75, 0x3f, 0xcd, 0x2b, 0x08, 0x9b, 0x9d, 0xb3, 0x82, 0x20, 0xde, 0x50, + 0xd4, 0x9f, 0x41, 0xab, 0x28, 0xc1, 0xda, 0xc9, 0xc0, 0xd8, 0x9e, 0x4e, 0xec, 0xf1, 0x68, 0x36, + 0xee, 0x59, 0x83, 0xe7, 0xda, 0x23, 0xde, 0x31, 0xc6, 0xcc, 0xb2, 0x8d, 0xb3, 0xb3, 0x29, 0xb6, + 0x34, 0x45, 0xff, 0x67, 0x09, 0xb6, 0x04, 0x28, 0xb3, 0x70, 0x19, 0xcf, 0x09, 0xcb, 0xe2, 0x2d, + 0x59, 0x25, 0x91, 0x33, 0x27, 0x69, 0x16, 0xd3, 0x35, 0x03, 0x24, 0x79, 0xeb, 0xc4, 0x0b, 0x19, + 0xb9, 0x58, 0xa0, 0x5f, 0x80, 0xca, 0xb3, 0x49, 0x6d, 0xba, 0x8a, 0x08, 0xcf, 0x63, 0xab, 0xbb, + 0xbf, 0x2e, 0x6c, 0x9e, 0x2b, 0x6a, 0xad, 0x22, 0x82, 0x81, 0x66, 0x74, 0xb1, 0x1b, 0x2a, 0x0f, + 0xe8, 0x86, 0x75, 0x0d, 0x55, 0x0b, 0x35, 0x74, 0x92, 0x25, 0xa4, 0x26, 0xad, 0xbc, 0x87, 0x5e, + 0x9a, 0x24, 0xd4, 0x81, 0x5a, 0x18, 0xd8, 0x8b, 0x85, 0xd7, 0xae, 0x73, 0x37, 0xbf, 0x97, 0x97, + 0x9d, 0x06, 0xc3, 0xa1, 0xd9, 0x13, 0x65, 0x51, 0x0d, 0x83, 0xe1, 0xc2, 0x43, 0x4f, 0xa0, 0x45, + 0xbe, 0xa6, 0x24, 0x0e, 0x1c, 0xcf, 0xf6, 0x57, 0x6c, 0x7a, 0x35, 0x78, 0xe8, 0xdb, 0x29, 0x77, + 0xcc, 0x98, 0xe8, 0x33, 0xd8, 0x49, 0x68, 0x18, 0xd9, 0xce, 0x35, 0x25, 0xb1, 0x3d, 0x0f, 0xa3, + 0x55, 0xbb, 0x79, 0xa4, 0x1c, 0x37, 0xf0, 0x36, 0x63, 0xf7, 0x18, 0x77, 0x10, 0x46, 0x2b, 0xfd, + 0x15, 0x34, 0x71, 0x78, 0x3f, 0x78, 0xcb, 0xe3, 0xd1, 0xa1, 0x76, 0x45, 0xae, 0xc3, 0x98, 0xc8, + 0x42, 0x05, 0x39, 0xc8, 0x71, 0x78, 0x8f, 0xe5, 0x17, 0x74, 0x04, 0x55, 0x6e, 0x53, 0x8e, 0x8b, + 0xbc, 0x88, 0xf8, 0xa0, 0x3b, 0xd0, 0xc0, 0xe1, 0x3d, 0x4f, 0x3b, 0xfa, 0x04, 0x04, 0xc0, 0x76, + 0xe0, 0xf8, 0x69, 0xf6, 0x9a, 0x9c, 0x33, 0x71, 0x7c, 0x82, 0x9e, 0x81, 0x1a, 0x87, 0xf7, 0xf6, + 0x9c, 0x6f, 0x2f, 0x3a, 0x51, 0xed, 0x1e, 0x14, 0x8a, 0x33, 0x75, 0x0e, 0x43, 0x9c, 0x92, 0x89, + 0xfe, 0x0a, 0x60, 0x5d, 0x5b, 0x1f, 0xda, 0xe4, 0x47, 0x2c, 0x1b, 0xc4, 0x5b, 0xa4, 0xf6, 0xb7, + 0xa4, 0xcb, 0xdc, 0x02, 0x96, 0xdf, 0x18, 0x10, 0x33, 0x56, 0x3c, 0xe7, 0xd4, 0x5d, 0x7c, 0x87, + 0x92, 0x43, 0x50, 0xb9, 0xa1, 0xee, 0x82, 0xd7, 0x5a, 0x13, 0x73, 0x5a, 0xff, 0x12, 0xaa, 0x97, + 0xdc, 0xdc, 0x33, 0x50, 0xb9, 0x94, 0xcd, 0xd8, 0x69, 0x0f, 0x16, 0xc2, 0xcc, 0xb6, 0xc6, 0x90, + 0xa4, 0x64, 0xa2, 0xf7, 0x60, 0xfb, 0xa5, 0xdc, 0x96, 0x0b, 0x7c, 0xbc, 0x5f, 0xfa, 0x9f, 0x4b, + 0x50, 0x7f, 0x11, 0x2e, 0x59, 0x61, 0xa0, 0x16, 0x94, 0xdc, 0x05, 0xd7, 0x2b, 0xe3, 0x92, 0xbb, + 0x40, 0xbf, 0x86, 0x96, 0xef, 0xde, 0xc4, 0x0e, 0x2b, 0x2f, 0xd1, 0x29, 0xa2, 0xd9, 0xbf, 0x9f, + 0xf7, 0x6c, 0x9c, 0x4a, 0xf0, 0x76, 0xd9, 0xf6, 0xf3, 0xcb, 0x5c, 0x03, 0x94, 0x0b, 0x0d, 0xf0, + 0x04, 0x5a, 0x5e, 0x38, 0x77, 0x3c, 0x3b, 0x1b, 0xbf, 0x15, 0x51, 0xa4, 0x9c, 0x7b, 0x91, 0xce, + 0xe0, 0x0d, 0x5c, 0xaa, 0x0f, 0xc4, 0x05, 0x7d, 0x01, 0x5b, 0x91, 0x13, 0x53, 0x77, 0xee, 0x46, + 0x0e, 0xbb, 0xc0, 0xd4, 0xb8, 0x62, 0xc1, 0xed, 0x02, 0x6e, 0xb8, 0x20, 0x8e, 0x3e, 0x07, 0x2d, + 0xe1, 0xa3, 0xc5, 0xbe, 0x0f, 0xe3, 0xdb, 0x6b, 0x2f, 0xbc, 0x4f, 0xda, 0x75, 0xee, 0xff, 0x8e, + 0xe0, 0xbf, 0x49, 0xd9, 0xfa, 0xbf, 0x4a, 0x50, 0xbb, 0x14, 0x55, 0x76, 0x02, 0x15, 0x8e, 0x91, + 0xb8, 0xa4, 0x1c, 0xe6, 0x37, 0x13, 0x12, 0x1c, 0x20, 0x2e, 0x83, 0x7e, 0x00, 0x4d, 0xea, 0xfa, + 0x24, 0xa1, 0x8e, 0x1f, 0x71, 0x50, 0xcb, 0x78, 0xcd, 0xf8, 0xa6, 0x5a, 0x61, 0x37, 0x11, 0x36, + 0x03, 0x04, 0x4c, 0x8c, 0x44, 0x3f, 0x85, 0x26, 0xeb, 0x0d, 0x7e, 0x71, 0x6a, 0x57, 0x79, 0xb3, + 0xed, 0x6f, 0x74, 0x06, 0xdf, 0x16, 0x37, 0xe2, 0xb4, 0xdb, 0x7e, 0x09, 0x2a, 0xaf, 0x66, 0xa9, + 0x24, 0x86, 0xcf, 0x61, 0x71, 0xf8, 0xa4, 0x5d, 0x83, 0x61, 0x3d, 0xaf, 0xd1, 0x53, 0xa8, 0xde, + 0x71, 0x97, 0xea, 0xf2, 0x02, 0x97, 0x0f, 0x8e, 0xc3, 0x2f, 0xbe, 0xb3, 0xd3, 0xf1, 0xb7, 0xa2, + 0x9a, 0xf8, 0xd8, 0xd9, 0x38, 0x1d, 0x65, 0xa1, 0xe1, 0x54, 0x86, 0x47, 0xe5, 0x7b, 0x7c, 0xf2, + 0xb0, 0xa8, 0x7c, 0x0f, 0x7d, 0x0a, 0x5b, 0xf3, 0x65, 0x1c, 0xf3, 0x2b, 0xa3, 0xeb, 0x93, 0xf6, + 0x3e, 0x07, 0x47, 0x95, 0x3c, 0xcb, 0xf5, 0x89, 0xfe, 0xfb, 0x12, 0xb4, 0x2e, 0xc5, 0xa1, 0x9a, + 0x1e, 0xe4, 0x5f, 0xc2, 0x1e, 0xb9, 0xbe, 0x26, 0x73, 0xea, 0xde, 0x11, 0x7b, 0xee, 0x78, 0x1e, + 0x89, 0x6d, 0x59, 0xca, 0x6a, 0x77, 0xa7, 0x23, 0x2e, 0xd7, 0x03, 0xce, 0x1f, 0x0d, 0xf1, 0x6e, + 0x26, 0x2b, 0x59, 0x0b, 0x64, 0xc0, 0x9e, 0xeb, 0xfb, 0x64, 0xe1, 0x3a, 0x34, 0x6f, 0x40, 0xcc, + 0xb0, 0x03, 0x39, 0x10, 0x2e, 0xad, 0x73, 0x87, 0x92, 0xb5, 0x99, 0x4c, 0x23, 0x33, 0xf3, 0x84, + 0xd5, 0x7b, 0x7c, 0x93, 0xdd, 0x0d, 0xb6, 0xa5, 0xa6, 0xc5, 0x99, 0x58, 0x7e, 0x2c, 0xdc, 0x3b, + 0x2a, 0x1b, 0xf7, 0x8e, 0xf5, 0xd9, 0x50, 0xfd, 0xd0, 0xd9, 0xa0, 0x7f, 0x01, 0x3b, 0x19, 0x10, + 0xf2, 0x5e, 0x71, 0x02, 0x35, 0x9e, 0xdc, 0x74, 0x8a, 0xa0, 0xf7, 0xeb, 0x10, 0x4b, 0x09, 0xfd, + 0x77, 0x25, 0x40, 0xa9, 0x7e, 0x78, 0x9f, 0xfc, 0x8f, 0x82, 0xb9, 0x0f, 0x55, 0xce, 0x97, 0x48, + 0x8a, 0x05, 0xc3, 0xc1, 0x73, 0x12, 0x1a, 0xdd, 0x66, 0x30, 0x0a, 0xe5, 0x57, 0xec, 0x17, 0x93, + 0x64, 0xe9, 0x51, 0x2c, 0x25, 0xf4, 0xbf, 0x28, 0xb0, 0x57, 0xc0, 0x41, 0x62, 0xb9, 0x3e, 0x18, + 0x94, 0xff, 0x7c, 0x30, 0xa0, 0x63, 0x68, 0x44, 0xb7, 0xdf, 0x72, 0x80, 0x64, 0x5f, 0xbf, 0xb1, + 0xaf, 0x7f, 0x08, 0x95, 0x98, 0xcd, 0x97, 0x0a, 0xd7, 0xcc, 0x9f, 0x96, 0x9c, 0xcf, 0x8e, 0xdc, + 0x42, 0x1c, 0x85, 0x23, 0x57, 0xfa, 0xff, 0x77, 0x05, 0x0e, 0xd6, 0x75, 0xb0, 0xf4, 0xe8, 0xff, + 0x55, 0x2a, 0xf5, 0x18, 0x0e, 0x37, 0xa3, 0xfb, 0xa8, 0x04, 0x7d, 0x07, 0xd8, 0x4f, 0x7e, 0x05, + 0x6a, 0xee, 0x6e, 0xc5, 0x9e, 0x60, 0xa3, 0xf3, 0xc9, 0x14, 0x1b, 0xda, 0x23, 0xd4, 0x80, 0xca, + 0xcc, 0x9a, 0x5e, 0x68, 0x0a, 0xa3, 0x8c, 0xdf, 0x18, 0x03, 0xf1, 0xac, 0x63, 0x94, 0x2d, 0x85, + 0xca, 0x27, 0x7f, 0x53, 0x00, 0xd6, 0x53, 0x1f, 0xa9, 0x50, 0x7f, 0x3d, 0x79, 0x39, 0x99, 0xbe, + 0x99, 0x08, 0x03, 0xe7, 0xd6, 0x68, 0xa8, 0x29, 0xa8, 0x09, 0x55, 0xf1, 0x4e, 0x2c, 0xb1, 0x1d, + 0xe4, 0x23, 0xb1, 0xcc, 0x5e, 0x90, 0xd9, 0x0b, 0xb1, 0x82, 0xea, 0x50, 0xce, 0xde, 0x81, 0xf2, + 0xe1, 0x57, 0x63, 0x06, 0xb1, 0x71, 0x61, 0xf6, 0x06, 0x86, 0x56, 0x67, 0x1f, 0xb2, 0x27, 0x20, + 0x40, 0x2d, 0x7d, 0xff, 0x31, 0x4d, 0xf6, 0x6a, 0x04, 0xb6, 0xcf, 0xd4, 0x7a, 0x6e, 0x60, 0x4d, + 0x65, 0x3c, 0x3c, 0x7d, 0xa3, 0x6d, 0x31, 0xde, 0xd9, 0xc8, 0x30, 0x87, 0xda, 0x36, 0x7b, 0x36, + 0x3e, 0x37, 0x7a, 0xd8, 0xea, 0x1b, 0x3d, 0x4b, 0x6b, 0xb1, 0x2f, 0x97, 0xdc, 0xc1, 0x1d, 0xb6, + 0xcd, 0x8b, 0xe9, 0x6b, 0x3c, 0xe9, 0x99, 0x9a, 0x76, 0xf2, 0x14, 0xb6, 0x0b, 0x87, 0x3d, 0xdb, + 0xcb, 0xea, 0xf5, 0x4d, 0x63, 0xa6, 0x3d, 0x62, 0xf4, 0xec, 0x79, 0x0f, 0x0f, 0x67, 0x9a, 0xd2, + 0xff, 0xfc, 0xab, 0xa7, 0x77, 0x2e, 0x25, 0x49, 0xd2, 0x71, 0xc3, 0x53, 0x41, 0x9d, 0xde, 0x84, + 0xa7, 0x77, 0xf4, 0x94, 0xff, 0x85, 0x71, 0xba, 0x9e, 0x48, 0x57, 0x35, 0xce, 0xf9, 0xd9, 0xbf, + 0x03, 0x00, 0x00, 0xff, 0xff, 0x78, 0x33, 0x5b, 0xba, 0x1e, 0x11, 0x00, 0x00, } diff --git a/go/vt/proto/logutil/logutil.pb.go b/go/vt/proto/logutil/logutil.pb.go index 16f34fa049c..ce7f38070a3 100644 --- a/go/vt/proto/logutil/logutil.pb.go +++ b/go/vt/proto/logutil/logutil.pb.go @@ -138,20 +138,20 @@ func init() { func init() { proto.RegisterFile("logutil.proto", fileDescriptor_31f5dd3702a8edf9) } var fileDescriptor_31f5dd3702a8edf9 = []byte{ - // 235 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x34, 0x8f, 0x41, 0x4b, 0x03, 0x31, - 0x10, 0x85, 0x4d, 0x77, 0x63, 0xed, 0x54, 0xcb, 0x32, 0x78, 0x08, 0x9e, 0x82, 0x14, 0x59, 0x3c, - 0x6c, 0xa0, 0x82, 0x77, 0x95, 0x55, 0x0a, 0x65, 0x17, 0xa2, 0x20, 0x78, 0x53, 0x18, 0x4b, 0x20, - 0x6d, 0xc4, 0xa6, 0xf9, 0x17, 0xfe, 0x67, 0xd9, 0x49, 0x7b, 0x7b, 0xef, 0x7b, 0x8f, 0xc7, 0x0c, - 0x5c, 0xf8, 0xb0, 0xde, 0x47, 0xe7, 0x9b, 0x9f, 0xdf, 0x10, 0x03, 0x8e, 0x0f, 0xf6, 0x0a, 0xa2, - 0xdb, 0x50, 0x86, 0xd7, 0x7f, 0x02, 0x64, 0x9b, 0x68, 0x1b, 0x51, 0x43, 0x39, 0x70, 0x25, 0xb4, - 0xa8, 0xa7, 0x8b, 0xf3, 0x26, 0x45, 0xae, 0xbd, 0xb9, 0x0d, 0x59, 0x4e, 0x70, 0x0e, 0xd2, 0x53, - 0x22, 0xaf, 0x46, 0x5a, 0xd4, 0xb3, 0xc5, 0xac, 0x39, 0xee, 0xaf, 0x06, 0x6a, 0x73, 0x88, 0x08, - 0xe5, 0xb7, 0xf3, 0xa4, 0x0a, 0x2d, 0xea, 0x89, 0x65, 0x3d, 0x30, 0xef, 0xb6, 0xa4, 0x4a, 0x2d, - 0xea, 0xc2, 0xb2, 0xc6, 0x4b, 0x90, 0xe9, 0xd3, 0xef, 0x49, 0x49, 0x2e, 0x66, 0x73, 0x7b, 0x0f, - 0x92, 0xd7, 0xf0, 0x0c, 0xca, 0x65, 0xf7, 0xdc, 0x57, 0x27, 0x38, 0x85, 0xf1, 0xfb, 0x83, 0xed, - 0x96, 0xdd, 0x4b, 0x25, 0x70, 0x02, 0xb2, 0xb5, 0xb6, 0xb7, 0xd5, 0x68, 0xe0, 0x4f, 0x7d, 0xf7, - 0xda, 0xaf, 0xda, 0xaa, 0x78, 0xbc, 0xf9, 0x98, 0x27, 0x17, 0x69, 0xb7, 0x6b, 0x5c, 0x30, 0x59, - 0x99, 0x75, 0x30, 0x29, 0x1a, 0xfe, 0xd3, 0x1c, 0x4e, 0xfd, 0x3a, 0x65, 0x7b, 0xf7, 0x1f, 0x00, - 0x00, 0xff, 0xff, 0xdd, 0xfa, 0x9b, 0x9a, 0x1c, 0x01, 0x00, 0x00, + // 236 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x34, 0x8f, 0x5f, 0x4b, 0xc3, 0x30, + 0x14, 0xc5, 0xcd, 0xda, 0x38, 0x77, 0x37, 0x47, 0xb9, 0xf8, 0x10, 0x7c, 0x0a, 0x32, 0xa4, 0xf8, + 0xd0, 0xc0, 0x04, 0xdf, 0x55, 0xaa, 0x0c, 0x46, 0x0b, 0x57, 0x41, 0xf0, 0x4d, 0xe1, 0x3a, 0x02, + 0xd9, 0x22, 0x2e, 0xcd, 0xb7, 0xf0, 0x3b, 0x4b, 0xd3, 0xfa, 0x76, 0xce, 0xef, 0x1c, 0xee, 0x1f, + 0x38, 0x77, 0x7e, 0xd7, 0x05, 0xeb, 0xaa, 0xef, 0x1f, 0x1f, 0x3c, 0x4e, 0x47, 0x7b, 0xb9, 0x88, + 0x21, 0xd8, 0x3d, 0x0f, 0xf8, 0xea, 0x57, 0x80, 0xac, 0x23, 0x1f, 0x02, 0x6a, 0xc8, 0x7b, 0xae, + 0x84, 0x16, 0xe5, 0x7c, 0xbd, 0xa8, 0xc6, 0xda, 0xab, 0xdd, 0x33, 0xa5, 0x04, 0x57, 0x20, 0x1d, + 0x47, 0x76, 0x6a, 0xa2, 0x45, 0xb9, 0x5c, 0x2f, 0xab, 0xff, 0x0d, 0xdb, 0x9e, 0xd2, 0x10, 0x22, + 0x42, 0xfe, 0x65, 0x1d, 0xab, 0x4c, 0x8b, 0x72, 0x46, 0x49, 0xf7, 0xcc, 0xd9, 0x03, 0xab, 0x5c, + 0x8b, 0x32, 0xa3, 0xa4, 0xf1, 0x02, 0x64, 0xfc, 0x70, 0x1d, 0x2b, 0x99, 0x8a, 0x83, 0xb9, 0xb9, + 0x03, 0x99, 0xa6, 0xe1, 0x19, 0xe4, 0x9b, 0xe6, 0xa9, 0x2d, 0x4e, 0x70, 0x0e, 0xd3, 0xb7, 0x7b, + 0x6a, 0x36, 0xcd, 0x73, 0x21, 0x70, 0x06, 0xb2, 0x26, 0x6a, 0xa9, 0x98, 0xf4, 0xfc, 0xb1, 0x6d, + 0x5e, 0xda, 0x6d, 0x5d, 0x64, 0x0f, 0xd7, 0xef, 0xab, 0x68, 0x03, 0x1f, 0x8f, 0x95, 0xf5, 0x66, + 0x50, 0x66, 0xe7, 0x4d, 0x0c, 0x26, 0xfd, 0x69, 0xc6, 0x53, 0x3f, 0x4f, 0x93, 0xbd, 0xfd, 0x0b, + 0x00, 0x00, 0xff, 0xff, 0xa4, 0x27, 0x83, 0x63, 0x1e, 0x01, 0x00, 0x00, } diff --git a/go/vt/proto/query/query.pb.go b/go/vt/proto/query/query.pb.go index d536cc1c24c..acbf4ea49da 100644 --- a/go/vt/proto/query/query.pb.go +++ b/go/vt/proto/query/query.pb.go @@ -3882,14 +3882,10 @@ func (m *AggregateStats) GetSecondsBehindMasterMax() uint32 { } // StreamHealthResponse is streamed by StreamHealth on a regular basis. -// When StreamHealth is used between a vtgate and vttablet: +// It is expected to be used between a vtgate and vttablet: // - target describes the tablet. // - realtime_stats is set. -// - aggregate_stats is not set. -// When StreamHealth is used between two vtgates: -// - target describes the group of tablets. -// - realtime_stats is not set. -// - aggregate_stats is set. +// - aggregate_stats is not set (deprecated) type StreamHealthResponse struct { // target is the current server type. Only queries with that exact Target // record will be accepted (the cell may not match, however). @@ -3928,9 +3924,6 @@ type StreamHealthResponse struct { // realtime_stats contains information about the tablet status. // It is only filled in if the information is about a tablet. RealtimeStats *RealtimeStats `protobuf:"bytes,4,opt,name=realtime_stats,json=realtimeStats,proto3" json:"realtime_stats,omitempty"` - // AggregateStats constrains information about the group of tablet status. - // It is only filled in if the information is about a group of tablets. - AggregateStats *AggregateStats `protobuf:"bytes,6,opt,name=aggregate_stats,json=aggregateStats,proto3" json:"aggregate_stats,omitempty"` // tablet_alias is the alias of the sending tablet. The discovery/healthcheck.go // code uses it to verify that it's talking to the correct tablet and that it // hasn't changed in the meantime e.g. due to tablet restarts where ports or @@ -3994,13 +3987,6 @@ func (m *StreamHealthResponse) GetRealtimeStats() *RealtimeStats { return nil } -func (m *StreamHealthResponse) GetAggregateStats() *AggregateStats { - if m != nil { - return m.AggregateStats - } - return nil -} - func (m *StreamHealthResponse) GetTabletAlias() *topodata.TabletAlias { if m != nil { return m.TabletAlias @@ -4267,210 +4253,209 @@ func init() { func init() { proto.RegisterFile("query.proto", fileDescriptor_5c6ac9b241082464) } var fileDescriptor_5c6ac9b241082464 = []byte{ - // 3270 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5a, 0xcb, 0x73, 0x1b, 0xc9, - 0x79, 0xd7, 0xe0, 0x45, 0xe0, 0x03, 0x01, 0x36, 0x1b, 0xa4, 0x84, 0xe5, 0xbe, 0xe8, 0xb1, 0xd7, - 0x66, 0x68, 0x87, 0xd2, 0x72, 0x65, 0x45, 0x59, 0x3b, 0x8e, 0x86, 0xe0, 0x50, 0x0b, 0x0b, 0x18, - 0x40, 0x8d, 0x81, 0x64, 0x6d, 0xb9, 0x6a, 0x6a, 0x08, 0xb4, 0xc0, 0x29, 0x0e, 0x66, 0xa0, 0x99, - 0x01, 0x29, 0xde, 0x94, 0x38, 0xce, 0xfb, 0xb1, 0x79, 0x6e, 0x9c, 0x54, 0x36, 0xa9, 0xca, 0x21, - 0xb7, 0xfc, 0x0d, 0xa9, 0x1c, 0x72, 0xcc, 0x2d, 0x87, 0x24, 0x87, 0x1c, 0x52, 0xa9, 0xdc, 0x5c, - 0x39, 0xe5, 0x90, 0x43, 0x2a, 0xd5, 0x8f, 0x19, 0x0c, 0x48, 0xec, 0x4a, 0x56, 0x7c, 0xa1, 0x76, - 0x6f, 0xdd, 0xdf, 0xf7, 0xf5, 0xe3, 0xf7, 0xfb, 0xbe, 0xf9, 0xba, 0xa7, 0xbb, 0xa1, 0xfc, 0x64, - 0x4a, 0x83, 0xb3, 0x9d, 0x49, 0xe0, 0x47, 0x3e, 0xce, 0xf3, 0xca, 0x46, 0x35, 0xf2, 0x27, 0xfe, - 0xd0, 0x8e, 0x6c, 0x21, 0xde, 0x28, 0x9f, 0x44, 0xc1, 0x64, 0x20, 0x2a, 0xea, 0x0f, 0x15, 0x28, - 0x98, 0x76, 0x30, 0xa2, 0x11, 0xde, 0x80, 0xe2, 0x31, 0x3d, 0x0b, 0x27, 0xf6, 0x80, 0xd6, 0x95, - 0x4d, 0x65, 0xab, 0x44, 0x92, 0x3a, 0x5e, 0x83, 0x7c, 0x78, 0x64, 0x07, 0xc3, 0x7a, 0x86, 0x2b, - 0x44, 0x05, 0x7f, 0x13, 0xca, 0x91, 0x7d, 0xe8, 0xd2, 0xc8, 0x8a, 0xce, 0x26, 0xb4, 0x9e, 0xdd, - 0x54, 0xb6, 0xaa, 0xbb, 0x6b, 0x3b, 0xc9, 0x78, 0x26, 0x57, 0x9a, 0x67, 0x13, 0x4a, 0x20, 0x4a, - 0xca, 0x18, 0x43, 0x6e, 0x40, 0x5d, 0xb7, 0x9e, 0xe3, 0x7d, 0xf1, 0xb2, 0xba, 0x0f, 0xd5, 0x07, - 0xe6, 0x5d, 0x3b, 0xa2, 0x0d, 0xdb, 0x75, 0x69, 0xd0, 0xdc, 0x67, 0xd3, 0x99, 0x86, 0x34, 0xf0, - 0xec, 0x71, 0x32, 0x9d, 0xb8, 0x8e, 0xaf, 0x42, 0x61, 0x14, 0xf8, 0xd3, 0x49, 0x58, 0xcf, 0x6c, - 0x66, 0xb7, 0x4a, 0x44, 0xd6, 0xd4, 0xef, 0x03, 0xe8, 0x27, 0xd4, 0x8b, 0x4c, 0xff, 0x98, 0x7a, - 0xf8, 0x0d, 0x28, 0x45, 0xce, 0x98, 0x86, 0x91, 0x3d, 0x9e, 0xf0, 0x2e, 0xb2, 0x64, 0x26, 0xf8, - 0x14, 0x48, 0x1b, 0x50, 0x9c, 0xf8, 0xa1, 0x13, 0x39, 0xbe, 0xc7, 0xf1, 0x94, 0x48, 0x52, 0x57, - 0xbf, 0x03, 0xf9, 0x07, 0xb6, 0x3b, 0xa5, 0xf8, 0x6d, 0xc8, 0x71, 0xc0, 0x0a, 0x07, 0x5c, 0xde, - 0x11, 0xa4, 0x73, 0x9c, 0x5c, 0xc1, 0xfa, 0x3e, 0x61, 0x96, 0xbc, 0xef, 0x65, 0x22, 0x2a, 0xea, - 0x31, 0x2c, 0xef, 0x39, 0xde, 0xf0, 0x81, 0x1d, 0x38, 0x8c, 0x8c, 0x97, 0xec, 0x06, 0x7f, 0x05, - 0x0a, 0xbc, 0x10, 0xd6, 0xb3, 0x9b, 0xd9, 0xad, 0xf2, 0xee, 0xb2, 0x6c, 0xc8, 0xe7, 0x46, 0xa4, - 0x4e, 0xfd, 0x7b, 0x05, 0x60, 0xcf, 0x9f, 0x7a, 0xc3, 0xfb, 0x4c, 0x89, 0x11, 0x64, 0xc3, 0x27, - 0xae, 0x24, 0x92, 0x15, 0xf1, 0x3d, 0xa8, 0x1e, 0x3a, 0xde, 0xd0, 0x3a, 0x91, 0xd3, 0x11, 0x5c, - 0x96, 0x77, 0xbf, 0x22, 0xbb, 0x9b, 0x35, 0xde, 0x49, 0xcf, 0x3a, 0xd4, 0xbd, 0x28, 0x38, 0x23, - 0x95, 0xc3, 0xb4, 0x6c, 0xa3, 0x0f, 0xf8, 0xa2, 0x11, 0x1b, 0xf4, 0x98, 0x9e, 0xc5, 0x83, 0x1e, - 0xd3, 0x33, 0xfc, 0x33, 0x69, 0x44, 0xe5, 0xdd, 0x5a, 0x3c, 0x56, 0xaa, 0xad, 0x84, 0xf9, 0x7e, - 0xe6, 0xb6, 0xa2, 0xfe, 0x65, 0x01, 0xaa, 0xfa, 0x53, 0x3a, 0x98, 0x46, 0xb4, 0x33, 0x61, 0x3e, - 0x08, 0xf1, 0x0e, 0xd4, 0x1c, 0x6f, 0xe0, 0x4e, 0x87, 0xd4, 0xa2, 0xcc, 0xd5, 0x56, 0xc4, 0x7c, - 0xcd, 0xfb, 0x2b, 0x92, 0x55, 0xa9, 0x4a, 0x05, 0x81, 0x06, 0xb5, 0x81, 0x3f, 0x9e, 0xd8, 0xc1, - 0xbc, 0x7d, 0x96, 0x8f, 0xbf, 0x2a, 0xc7, 0x9f, 0xd9, 0x93, 0x55, 0x69, 0x9d, 0xea, 0xa2, 0x0d, - 0x2b, 0xb2, 0xdf, 0xa1, 0xf5, 0xd8, 0xa1, 0xee, 0x30, 0xe4, 0xa1, 0x5b, 0x4d, 0xa8, 0x9a, 0x9f, - 0xe2, 0x4e, 0x53, 0x1a, 0x1f, 0x70, 0x5b, 0x52, 0x75, 0xe6, 0xea, 0x78, 0x1b, 0x56, 0x07, 0xae, - 0xc3, 0xa6, 0xf2, 0x98, 0x51, 0x6c, 0x05, 0xfe, 0x69, 0x58, 0xcf, 0xf3, 0xf9, 0xaf, 0x08, 0xc5, - 0x01, 0x93, 0x13, 0xff, 0x34, 0xc4, 0xef, 0x43, 0xf1, 0xd4, 0x0f, 0x8e, 0x5d, 0xdf, 0x1e, 0xd6, - 0x0b, 0x7c, 0xcc, 0xb7, 0x16, 0x8f, 0xf9, 0x50, 0x5a, 0x91, 0xc4, 0x1e, 0x6f, 0x01, 0x0a, 0x9f, - 0xb8, 0x56, 0x48, 0x5d, 0x3a, 0x88, 0x2c, 0xd7, 0x19, 0x3b, 0x51, 0xbd, 0xc8, 0xbf, 0x82, 0x6a, - 0xf8, 0xc4, 0xed, 0x71, 0x71, 0x8b, 0x49, 0xb1, 0x05, 0xeb, 0x51, 0x60, 0x7b, 0xa1, 0x3d, 0x60, - 0x9d, 0x59, 0x4e, 0xe8, 0xbb, 0x36, 0xff, 0x02, 0x4a, 0x7c, 0xc8, 0xed, 0xc5, 0x43, 0x9a, 0xb3, - 0x26, 0xcd, 0xb8, 0x05, 0x59, 0x8b, 0x16, 0x48, 0xf1, 0xbb, 0xb0, 0x1e, 0x1e, 0x3b, 0x13, 0x8b, - 0xf7, 0x63, 0x4d, 0x5c, 0xdb, 0xb3, 0x06, 0xf6, 0xe0, 0x88, 0xd6, 0x81, 0xc3, 0xc6, 0x4c, 0xc9, - 0x43, 0xad, 0xeb, 0xda, 0x5e, 0x83, 0x69, 0xd4, 0x6f, 0x41, 0x75, 0x9e, 0x47, 0xbc, 0x0a, 0x15, - 0xf3, 0x51, 0x57, 0xb7, 0x34, 0x63, 0xdf, 0x32, 0xb4, 0xb6, 0x8e, 0xae, 0xe0, 0x0a, 0x94, 0xb8, - 0xa8, 0x63, 0xb4, 0x1e, 0x21, 0x05, 0x2f, 0x41, 0x56, 0x6b, 0xb5, 0x50, 0x46, 0xbd, 0x0d, 0xc5, - 0x98, 0x10, 0xbc, 0x02, 0xe5, 0xbe, 0xd1, 0xeb, 0xea, 0x8d, 0xe6, 0x41, 0x53, 0xdf, 0x47, 0x57, - 0x70, 0x11, 0x72, 0x9d, 0x96, 0xd9, 0x45, 0x8a, 0x28, 0x69, 0x5d, 0x94, 0x61, 0x2d, 0xf7, 0xf7, - 0x34, 0x94, 0x55, 0xff, 0x46, 0x81, 0xb5, 0x45, 0xc0, 0x70, 0x19, 0x96, 0xf6, 0xf5, 0x03, 0xad, - 0xdf, 0x32, 0xd1, 0x15, 0x5c, 0x83, 0x15, 0xa2, 0x77, 0x75, 0xcd, 0xd4, 0xf6, 0x5a, 0xba, 0x45, - 0x74, 0x6d, 0x1f, 0x29, 0x18, 0x43, 0x95, 0x95, 0xac, 0x46, 0xa7, 0xdd, 0x6e, 0x9a, 0xa6, 0xbe, - 0x8f, 0x32, 0x78, 0x0d, 0x10, 0x97, 0xf5, 0x8d, 0x99, 0x34, 0x8b, 0x11, 0x2c, 0xf7, 0x74, 0xd2, - 0xd4, 0x5a, 0xcd, 0x0f, 0x59, 0x07, 0x28, 0x87, 0xbf, 0x04, 0x6f, 0x36, 0x3a, 0x46, 0xaf, 0xd9, - 0x33, 0x75, 0xc3, 0xb4, 0x7a, 0x86, 0xd6, 0xed, 0x7d, 0xd0, 0x31, 0x79, 0xcf, 0x02, 0x5c, 0x1e, - 0x57, 0x01, 0xb4, 0xbe, 0xd9, 0x11, 0xfd, 0xa0, 0xc2, 0x77, 0x73, 0x45, 0x05, 0x65, 0xd4, 0x8f, - 0x33, 0x90, 0xe7, 0xfc, 0xb0, 0xac, 0x9a, 0xca, 0x95, 0xbc, 0x9c, 0x64, 0x98, 0xcc, 0x67, 0x64, - 0x18, 0x9e, 0x98, 0x65, 0xae, 0x13, 0x15, 0xfc, 0x3a, 0x94, 0xfc, 0x60, 0x64, 0x09, 0x8d, 0xc8, - 0xd2, 0x45, 0x3f, 0x18, 0xf1, 0x74, 0xce, 0x32, 0x24, 0x4b, 0xee, 0x87, 0x76, 0x48, 0x79, 0xd4, - 0x96, 0x48, 0x52, 0xc7, 0xaf, 0x01, 0xb3, 0xb3, 0xf8, 0x3c, 0x0a, 0x5c, 0xb7, 0xe4, 0x07, 0x23, - 0x83, 0x4d, 0xe5, 0xcb, 0x50, 0x19, 0xf8, 0xee, 0x74, 0xec, 0x59, 0x2e, 0xf5, 0x46, 0xd1, 0x51, - 0x7d, 0x69, 0x53, 0xd9, 0xaa, 0x90, 0x65, 0x21, 0x6c, 0x71, 0x19, 0xae, 0xc3, 0xd2, 0xe0, 0xc8, - 0x0e, 0x42, 0x2a, 0x22, 0xb5, 0x42, 0xe2, 0x2a, 0x1f, 0x95, 0x0e, 0x9c, 0xb1, 0xed, 0x86, 0x3c, - 0x2a, 0x2b, 0x24, 0xa9, 0x33, 0x10, 0x8f, 0x5d, 0x7b, 0x14, 0xf2, 0x68, 0xaa, 0x10, 0x51, 0x51, - 0x7f, 0x0e, 0xb2, 0xc4, 0x3f, 0x65, 0x5d, 0x8a, 0x01, 0xc3, 0xba, 0xb2, 0x99, 0xdd, 0xc2, 0x24, - 0xae, 0xb2, 0x45, 0x44, 0xe6, 0x51, 0x91, 0x5e, 0xe3, 0xcc, 0xf9, 0x7d, 0x58, 0x26, 0x34, 0x9c, - 0xba, 0x91, 0xfe, 0x34, 0x0a, 0xec, 0x10, 0xef, 0x42, 0x39, 0x9d, 0x39, 0x94, 0x4f, 0xcb, 0x1c, - 0x40, 0x67, 0x29, 0xa3, 0x0e, 0x4b, 0x8f, 0x03, 0x1a, 0x1e, 0xd1, 0x40, 0x66, 0xa6, 0xb8, 0xca, - 0xf2, 0x72, 0x99, 0x87, 0xba, 0x18, 0x83, 0x65, 0x73, 0x99, 0x53, 0x94, 0xb9, 0x6c, 0xce, 0x9d, - 0x4a, 0xa4, 0x8e, 0xb1, 0xc7, 0xd2, 0x84, 0x65, 0x3f, 0x7e, 0x4c, 0x07, 0x11, 0x15, 0x8b, 0x56, - 0x8e, 0x2c, 0x33, 0xa1, 0x26, 0x65, 0xcc, 0x6d, 0x8e, 0x17, 0xd2, 0x20, 0xb2, 0x9c, 0x21, 0x77, - 0x68, 0x8e, 0x14, 0x85, 0xa0, 0x39, 0xc4, 0x6f, 0x41, 0x8e, 0x27, 0x9a, 0x1c, 0x1f, 0x05, 0xe4, - 0x28, 0xc4, 0x3f, 0x25, 0x5c, 0x8e, 0xbf, 0x0e, 0x05, 0xca, 0xf1, 0x72, 0xa7, 0xce, 0x52, 0x73, - 0x9a, 0x0a, 0x22, 0x4d, 0xd4, 0x6f, 0xc3, 0x32, 0xc7, 0xf0, 0xd0, 0x0e, 0x3c, 0xc7, 0x1b, 0xf1, - 0x15, 0xdd, 0x1f, 0x8a, 0xd8, 0xab, 0x10, 0x5e, 0x66, 0x14, 0x8c, 0x69, 0x18, 0xda, 0x23, 0x2a, - 0x57, 0xd8, 0xb8, 0xaa, 0xfe, 0x55, 0x16, 0xca, 0xbd, 0x28, 0xa0, 0xf6, 0x98, 0xb3, 0x87, 0xbf, - 0x0d, 0x10, 0x46, 0x76, 0x44, 0xc7, 0xd4, 0x8b, 0x62, 0x1a, 0xde, 0x90, 0xc3, 0xa7, 0xec, 0x76, - 0x7a, 0xb1, 0x11, 0x49, 0xd9, 0x9f, 0x77, 0x4f, 0xe6, 0x05, 0xdc, 0xb3, 0xf1, 0x49, 0x06, 0x4a, - 0x49, 0x6f, 0x58, 0x83, 0xe2, 0xc0, 0x8e, 0xe8, 0xc8, 0x0f, 0xce, 0xe4, 0x5a, 0xfc, 0xce, 0x67, - 0x8d, 0xbe, 0xd3, 0x90, 0xc6, 0x24, 0x69, 0x86, 0xdf, 0x04, 0xb1, 0xc1, 0x11, 0xa1, 0x2f, 0xf0, - 0x96, 0xb8, 0x84, 0x07, 0xff, 0xfb, 0x80, 0x27, 0x81, 0x33, 0xb6, 0x83, 0x33, 0xeb, 0x98, 0x9e, - 0xc5, 0x8b, 0x48, 0x76, 0x81, 0xc3, 0x91, 0xb4, 0xbb, 0x47, 0xcf, 0x64, 0xda, 0xbb, 0x3d, 0xdf, - 0x56, 0x86, 0xec, 0x45, 0x37, 0xa6, 0x5a, 0xf2, 0x9d, 0x40, 0x18, 0xaf, 0xf9, 0x79, 0x1e, 0xdd, - 0xac, 0xa8, 0x7e, 0x0d, 0x8a, 0xf1, 0xe4, 0x71, 0x09, 0xf2, 0x7a, 0x10, 0xf8, 0x01, 0xba, 0xc2, - 0xb3, 0x5f, 0xbb, 0x25, 0x12, 0xe8, 0xfe, 0x3e, 0x4b, 0xa0, 0x7f, 0x97, 0x49, 0x16, 0x5e, 0x42, - 0x9f, 0x4c, 0x69, 0x18, 0xe1, 0x5f, 0x84, 0x1a, 0xe5, 0x91, 0xe6, 0x9c, 0x50, 0x6b, 0xc0, 0x77, - 0x69, 0x2c, 0xce, 0xc4, 0xe7, 0xb0, 0xb2, 0x23, 0x36, 0x95, 0xf1, 0xee, 0x8d, 0xac, 0x26, 0xb6, - 0x52, 0x34, 0xc4, 0x3a, 0xd4, 0x9c, 0xf1, 0x98, 0x0e, 0x1d, 0x3b, 0x4a, 0x77, 0x20, 0x1c, 0xb6, - 0x1e, 0x6f, 0x62, 0xe6, 0x36, 0x81, 0x64, 0x35, 0x69, 0x91, 0x74, 0xf3, 0x0e, 0x14, 0x22, 0xbe, - 0x61, 0x95, 0x6b, 0x78, 0x25, 0xce, 0x6a, 0x5c, 0x48, 0xa4, 0x12, 0x7f, 0x0d, 0xc4, 0xf6, 0x97, - 0xe7, 0xaf, 0x59, 0x40, 0xcc, 0x76, 0x35, 0x44, 0xe8, 0xf1, 0x3b, 0x50, 0x9d, 0x5b, 0xfc, 0x86, - 0x9c, 0xb0, 0x2c, 0xa9, 0xa4, 0x57, 0xb2, 0x21, 0xbe, 0x0e, 0x4b, 0xbe, 0x58, 0xf8, 0x78, 0x66, - 0x9b, 0xcd, 0x78, 0x7e, 0x55, 0x24, 0xb1, 0x95, 0xfa, 0x0b, 0xb0, 0x92, 0x30, 0x18, 0x4e, 0x7c, - 0x2f, 0xa4, 0x78, 0x1b, 0x0a, 0x01, 0xff, 0x9c, 0x24, 0x6b, 0x58, 0x76, 0x91, 0xca, 0x07, 0x44, - 0x5a, 0xa8, 0x43, 0x58, 0x11, 0x92, 0x87, 0x4e, 0x74, 0xc4, 0x1d, 0x85, 0xdf, 0x81, 0x3c, 0x65, - 0x85, 0x73, 0x9c, 0x93, 0x6e, 0x83, 0xeb, 0x89, 0xd0, 0xa6, 0x46, 0xc9, 0x3c, 0x77, 0x94, 0xff, - 0xca, 0x40, 0x4d, 0xce, 0x72, 0xcf, 0x8e, 0x06, 0x47, 0x97, 0xd4, 0xd9, 0x5f, 0x87, 0x25, 0x26, - 0x77, 0x92, 0x0f, 0x63, 0x81, 0xbb, 0x63, 0x0b, 0xe6, 0x70, 0x3b, 0xb4, 0x52, 0xde, 0x95, 0x9b, - 0xaf, 0x8a, 0x1d, 0xa6, 0x56, 0xfe, 0x05, 0x71, 0x51, 0x78, 0x4e, 0x5c, 0x2c, 0xbd, 0x50, 0x5c, - 0xec, 0xc3, 0xda, 0x3c, 0xe3, 0x32, 0x38, 0xbe, 0x01, 0x4b, 0xc2, 0x29, 0x71, 0x0a, 0x5c, 0xe4, - 0xb7, 0xd8, 0x44, 0xfd, 0x87, 0x0c, 0xac, 0xc9, 0xec, 0xf4, 0xf9, 0xf8, 0x4c, 0x53, 0x3c, 0xe7, - 0x5f, 0x84, 0xe7, 0x17, 0xf4, 0x9f, 0xda, 0x80, 0xf5, 0x73, 0x3c, 0xbe, 0xc4, 0xc7, 0xfa, 0x63, - 0x05, 0x96, 0xf7, 0xe8, 0xc8, 0xf1, 0x2e, 0xa9, 0x17, 0x52, 0xe4, 0xe6, 0x5e, 0x28, 0x88, 0x6f, - 0x41, 0x45, 0xe2, 0x95, 0x6c, 0x5d, 0x64, 0x5b, 0x59, 0xc4, 0xf6, 0x7f, 0x28, 0x50, 0x69, 0xf8, - 0xe3, 0xb1, 0x13, 0x5d, 0x52, 0xa6, 0x2e, 0xe2, 0xcc, 0x2d, 0xc2, 0x89, 0xa0, 0x1a, 0xc3, 0x14, - 0x04, 0xa9, 0xff, 0xa9, 0xc0, 0x0a, 0xf1, 0x5d, 0xf7, 0xd0, 0x1e, 0x1c, 0xbf, 0xda, 0xd8, 0x31, - 0xa0, 0x19, 0x50, 0x89, 0xfe, 0x7f, 0x14, 0xa8, 0x76, 0x03, 0xca, 0x7e, 0xac, 0x5f, 0x69, 0xf0, - 0x6c, 0x27, 0x3c, 0x8c, 0xe4, 0x1e, 0xa2, 0x44, 0x78, 0x59, 0x5d, 0x85, 0x95, 0x04, 0xbb, 0xe4, - 0xe3, 0x5f, 0x14, 0x58, 0x17, 0x01, 0x22, 0x35, 0xc3, 0x4b, 0x4a, 0x4b, 0x8c, 0x37, 0x97, 0xc2, - 0x5b, 0x87, 0xab, 0xe7, 0xb1, 0x49, 0xd8, 0x3f, 0xc8, 0xc0, 0xb5, 0x38, 0x36, 0x2e, 0x39, 0xf0, - 0xff, 0x47, 0x3c, 0x6c, 0x40, 0xfd, 0x22, 0x09, 0x92, 0xa1, 0x8f, 0x32, 0x50, 0x6f, 0x04, 0xd4, - 0x8e, 0x68, 0x6a, 0x2f, 0xf2, 0xea, 0xc4, 0x06, 0x7e, 0x17, 0x96, 0x27, 0x76, 0x10, 0x39, 0x03, - 0x67, 0x62, 0xb3, 0xbf, 0xbd, 0x3c, 0xdf, 0xea, 0x9c, 0xeb, 0x60, 0xce, 0x44, 0x7d, 0x1d, 0x5e, - 0x5b, 0xc0, 0x88, 0xe4, 0xeb, 0x7f, 0x15, 0xc0, 0xbd, 0xc8, 0x0e, 0xa2, 0xcf, 0xc1, 0xaa, 0xb2, - 0x30, 0x98, 0xd6, 0xa1, 0x36, 0x87, 0x3f, 0xcd, 0x0b, 0x8d, 0x3e, 0x17, 0x2b, 0xce, 0xa7, 0xf2, - 0x92, 0xc6, 0x2f, 0x79, 0xf9, 0x37, 0x05, 0x36, 0x1a, 0xbe, 0x38, 0x58, 0x7c, 0x25, 0xbf, 0x30, - 0xf5, 0x4d, 0x78, 0x7d, 0x21, 0x40, 0x49, 0xc0, 0xbf, 0x2a, 0x70, 0x95, 0x50, 0x7b, 0xf8, 0x6a, - 0x82, 0xbf, 0x0f, 0xd7, 0x2e, 0x80, 0x93, 0x3b, 0xd4, 0x5b, 0x50, 0x1c, 0xd3, 0xc8, 0x1e, 0xda, - 0x91, 0x2d, 0x21, 0x6d, 0xc4, 0xfd, 0xce, 0xac, 0xdb, 0xd2, 0x82, 0x24, 0xb6, 0xea, 0x27, 0x19, - 0xa8, 0xf1, 0xbd, 0xee, 0x17, 0x3f, 0x5a, 0x8b, 0xff, 0x05, 0x3e, 0x52, 0x60, 0x6d, 0x9e, 0xa0, - 0xe4, 0x9f, 0xe0, 0xa7, 0x7d, 0x5e, 0xb1, 0x20, 0x21, 0x64, 0x17, 0x6d, 0x41, 0xff, 0x31, 0x03, - 0xf5, 0xf4, 0x94, 0xbe, 0x38, 0xdb, 0x98, 0x3f, 0xdb, 0xf8, 0x89, 0x0f, 0xb3, 0x3e, 0x56, 0xe0, - 0xb5, 0x05, 0x84, 0xfe, 0x64, 0x8e, 0x4e, 0x9d, 0x70, 0x64, 0x9e, 0x7b, 0xc2, 0xf1, 0xa2, 0xae, - 0xfe, 0x67, 0x05, 0xd6, 0xda, 0xe2, 0x60, 0x59, 0xfc, 0xc7, 0x5f, 0xde, 0x6c, 0xc6, 0xcf, 0x8e, - 0x73, 0xb3, 0xeb, 0x1b, 0xb5, 0x01, 0xeb, 0xe7, 0xa0, 0xbd, 0xc4, 0xd9, 0xc4, 0x7f, 0x2b, 0xb0, - 0x2a, 0x7b, 0xd1, 0x2e, 0xed, 0x46, 0x60, 0x01, 0x3b, 0xf8, 0x2d, 0xc8, 0x3a, 0xc3, 0x78, 0x07, - 0x39, 0x7f, 0x09, 0xce, 0x14, 0xea, 0x1d, 0xc0, 0x69, 0xdc, 0x2f, 0x41, 0xdd, 0x3f, 0x65, 0x61, - 0xb5, 0x37, 0x71, 0x9d, 0x48, 0x2a, 0x5f, 0xed, 0xc4, 0xff, 0x25, 0x58, 0x0e, 0x19, 0x58, 0x4b, - 0x5c, 0xc9, 0x71, 0x62, 0x4b, 0xa4, 0xcc, 0x65, 0x0d, 0x2e, 0xc2, 0x6f, 0x43, 0x39, 0x36, 0x99, - 0x7a, 0x91, 0x3c, 0x50, 0x03, 0x69, 0x31, 0xf5, 0x22, 0x7c, 0x13, 0xae, 0x79, 0xd3, 0x31, 0xbf, - 0xd2, 0xb6, 0x26, 0x34, 0x88, 0x2f, 0x7c, 0xed, 0x20, 0xbe, 0x7a, 0xae, 0x79, 0xd3, 0x31, 0xf1, - 0x4f, 0xc3, 0x2e, 0x0d, 0xc4, 0x85, 0xaf, 0x1d, 0x44, 0xf8, 0x0e, 0x94, 0x6c, 0x77, 0xe4, 0x07, - 0x4e, 0x74, 0x34, 0x96, 0x77, 0xce, 0x6a, 0x7c, 0x03, 0x73, 0x9e, 0xfe, 0x1d, 0x2d, 0xb6, 0x24, - 0xb3, 0x46, 0xea, 0x37, 0xa0, 0x94, 0xc8, 0x31, 0x82, 0x65, 0xfd, 0x7e, 0x5f, 0x6b, 0x59, 0xbd, - 0x6e, 0xab, 0x69, 0xf6, 0xc4, 0x3d, 0xf1, 0x41, 0xbf, 0xd5, 0xb2, 0x7a, 0x0d, 0xcd, 0x40, 0x8a, - 0x4a, 0x00, 0x78, 0x97, 0xbc, 0xf3, 0x19, 0x41, 0xca, 0x73, 0x08, 0x7a, 0x1d, 0x4a, 0x81, 0x7f, - 0x2a, 0xb1, 0x67, 0x38, 0x9c, 0x62, 0xe0, 0x9f, 0x72, 0xe4, 0xaa, 0x06, 0x38, 0x3d, 0x57, 0x19, - 0x6d, 0xa9, 0xe4, 0xad, 0xcc, 0x25, 0xef, 0xd9, 0xf8, 0x49, 0xf2, 0x16, 0x5b, 0x79, 0xf6, 0x9d, - 0x7f, 0x40, 0x6d, 0x37, 0x8a, 0xd7, 0x2b, 0xf5, 0xaf, 0x33, 0x50, 0x21, 0x4c, 0xe2, 0x8c, 0x69, - 0x2f, 0xb2, 0xa3, 0x90, 0x79, 0xea, 0x88, 0x9b, 0x58, 0xb3, 0xb4, 0x5b, 0x22, 0x65, 0x21, 0x13, - 0x77, 0x05, 0xbb, 0xb0, 0x1e, 0xd2, 0x81, 0xef, 0x0d, 0x43, 0xeb, 0x90, 0x1e, 0x39, 0xde, 0xd0, - 0x1a, 0xdb, 0x61, 0x24, 0xaf, 0x23, 0x2b, 0xa4, 0x26, 0x95, 0x7b, 0x5c, 0xd7, 0xe6, 0x2a, 0x7c, - 0x03, 0xd6, 0x0e, 0x1d, 0xcf, 0xf5, 0x47, 0xd6, 0xc4, 0xb5, 0xcf, 0x68, 0x10, 0x4a, 0xa8, 0x2c, - 0xbc, 0xf2, 0x04, 0x0b, 0x5d, 0x57, 0xa8, 0x84, 0xbb, 0x3f, 0x84, 0xed, 0x85, 0xa3, 0x58, 0x8f, - 0x1d, 0x37, 0xa2, 0x01, 0x1d, 0x5a, 0x01, 0x9d, 0xb8, 0xce, 0x40, 0xbc, 0x26, 0x10, 0x7b, 0xf7, - 0xaf, 0x2e, 0x18, 0xfa, 0x40, 0x9a, 0x93, 0x99, 0x35, 0x63, 0x7b, 0x30, 0x99, 0x5a, 0x53, 0x7e, - 0x83, 0xc8, 0x56, 0x31, 0x85, 0x14, 0x07, 0x93, 0x69, 0x9f, 0xd5, 0x31, 0x82, 0xec, 0x93, 0x89, - 0x58, 0xbc, 0x14, 0xc2, 0x8a, 0xea, 0x8f, 0x15, 0xa8, 0x6a, 0xa3, 0x51, 0x40, 0x47, 0x76, 0x24, - 0x69, 0xba, 0x01, 0x6b, 0x82, 0x92, 0x33, 0x4b, 0x3e, 0x53, 0x12, 0x78, 0x14, 0x81, 0x47, 0xea, - 0xc4, 0x23, 0xa5, 0x38, 0x7c, 0xaf, 0x4e, 0xbd, 0x85, 0x6d, 0x32, 0xbc, 0xcd, 0x5a, 0xa2, 0x4d, - 0xb7, 0xfa, 0x79, 0x78, 0x6d, 0x31, 0x0b, 0x63, 0x47, 0x3c, 0x34, 0xa9, 0x90, 0xab, 0x0b, 0x40, - 0xb7, 0x1d, 0xef, 0x33, 0x9a, 0xda, 0x4f, 0x39, 0x5f, 0x9f, 0xd2, 0xd4, 0x7e, 0xaa, 0xfe, 0x7b, - 0x72, 0x03, 0x10, 0x87, 0x4b, 0xb2, 0x1a, 0xc7, 0x79, 0x41, 0xf9, 0xac, 0xbc, 0x50, 0x87, 0xa5, - 0x90, 0x06, 0x27, 0x8e, 0x37, 0x8a, 0xaf, 0xa8, 0x65, 0x15, 0xf7, 0xe0, 0xab, 0x12, 0x3b, 0x7d, - 0x1a, 0xd1, 0xc0, 0xb3, 0x5d, 0xf7, 0xcc, 0x12, 0x07, 0x15, 0x5e, 0x44, 0x87, 0xd6, 0xec, 0x51, - 0x95, 0x58, 0x91, 0xbf, 0x2c, 0xac, 0xf5, 0xc4, 0x98, 0x24, 0xb6, 0x66, 0xf2, 0xdc, 0xea, 0x5b, - 0x50, 0x0d, 0x64, 0x10, 0x5b, 0x21, 0x73, 0x8f, 0xcc, 0x47, 0x6b, 0xc9, 0x3d, 0x73, 0x2a, 0xc2, - 0x49, 0x25, 0x98, 0x0b, 0xf8, 0xef, 0xc0, 0x8a, 0x1d, 0xfb, 0x56, 0xb6, 0x9e, 0xdf, 0xb7, 0xcc, - 0x7b, 0x9e, 0x54, 0xed, 0xf9, 0x48, 0xb8, 0x0d, 0xcb, 0x12, 0x91, 0xed, 0x3a, 0xf6, 0x6c, 0x63, - 0x7b, 0xee, 0xa5, 0x9a, 0xc6, 0x94, 0x44, 0xbe, 0x69, 0xe3, 0x15, 0xf6, 0x1f, 0x5d, 0xeb, 0x4f, - 0x86, 0xbc, 0xa7, 0x4b, 0xbc, 0xbb, 0x48, 0x3f, 0x6b, 0xcb, 0xcd, 0x3f, 0x6b, 0x9b, 0x7f, 0x26, - 0x97, 0x3f, 0xf7, 0x4c, 0x4e, 0xbd, 0x03, 0x6b, 0xf3, 0xf8, 0x65, 0x94, 0x6d, 0x41, 0x9e, 0x5f, - 0xa8, 0x9f, 0x5b, 0x46, 0x53, 0x37, 0xe6, 0x44, 0x18, 0xa8, 0x7f, 0xab, 0x40, 0x6d, 0xc1, 0x2f, - 0x56, 0xf2, 0xff, 0xa6, 0xa4, 0x8e, 0x87, 0x7e, 0x16, 0xf2, 0xfc, 0x6a, 0x5f, 0xbe, 0x58, 0xb9, - 0x76, 0xf1, 0x0f, 0x8d, 0x5f, 0xc3, 0x13, 0x61, 0xc5, 0x12, 0x21, 0x0f, 0xa8, 0x01, 0x3f, 0x1f, - 0x8a, 0x77, 0x88, 0x65, 0x26, 0x13, 0x47, 0x46, 0x17, 0x0f, 0x9c, 0x72, 0xcf, 0x3d, 0x70, 0xda, - 0xfe, 0x83, 0x2c, 0x94, 0xda, 0x67, 0xbd, 0x27, 0xee, 0x81, 0x6b, 0x8f, 0xf8, 0x3d, 0x79, 0xbb, - 0x6b, 0x3e, 0x42, 0x57, 0xf0, 0x2a, 0x54, 0x8c, 0x8e, 0x69, 0x19, 0x6c, 0x29, 0x39, 0x68, 0x69, - 0x77, 0x91, 0xc2, 0xd6, 0x9a, 0x2e, 0x69, 0x5a, 0xf7, 0xf4, 0x47, 0x42, 0x92, 0xc1, 0x35, 0x58, - 0xe9, 0x1b, 0xcd, 0xfb, 0x7d, 0x7d, 0x26, 0xcc, 0xe1, 0x75, 0x58, 0x6d, 0xf7, 0x5b, 0x66, 0xb3, - 0xdb, 0x4a, 0x89, 0x8b, 0x6c, 0x5d, 0xda, 0x6b, 0x75, 0xf6, 0x44, 0x15, 0xb1, 0xfe, 0xfb, 0x46, - 0xaf, 0x79, 0xd7, 0xd0, 0xf7, 0x85, 0x68, 0x93, 0x89, 0x3e, 0xd4, 0x49, 0xe7, 0xa0, 0x19, 0x0f, - 0x79, 0x07, 0x23, 0x28, 0xef, 0x35, 0x0d, 0x8d, 0xc8, 0x5e, 0x9e, 0x29, 0xb8, 0x0a, 0x25, 0xdd, - 0xe8, 0xb7, 0x65, 0x3d, 0x83, 0xeb, 0x50, 0xd3, 0xfa, 0x66, 0xc7, 0x6a, 0x1a, 0x0d, 0xa2, 0xb7, - 0x75, 0xc3, 0x94, 0x9a, 0x1c, 0xae, 0x41, 0xd5, 0x6c, 0xb6, 0xf5, 0x9e, 0xa9, 0xb5, 0xbb, 0x52, - 0xc8, 0x66, 0x51, 0xec, 0xe9, 0xb1, 0x0d, 0xc2, 0x1b, 0xb0, 0x6e, 0x74, 0x2c, 0xf9, 0xd8, 0xc9, - 0x7a, 0xa0, 0xb5, 0xfa, 0xba, 0xd4, 0x6d, 0xe2, 0x6b, 0x80, 0x3b, 0x86, 0xd5, 0xef, 0xee, 0x6b, - 0xa6, 0x6e, 0x19, 0x9d, 0x87, 0x52, 0x71, 0x07, 0x57, 0xa1, 0x38, 0x9b, 0xc1, 0x33, 0xc6, 0x42, - 0xa5, 0xab, 0x11, 0x73, 0x06, 0xf6, 0xd9, 0x33, 0x46, 0x16, 0xdc, 0x25, 0x9d, 0x7e, 0x77, 0x66, - 0xb6, 0x0a, 0x65, 0x49, 0x96, 0x14, 0xe5, 0x98, 0x68, 0xaf, 0x69, 0x34, 0x92, 0xf9, 0x3d, 0x2b, - 0x6e, 0x64, 0x90, 0xb2, 0x7d, 0x0c, 0x39, 0xee, 0x8e, 0x22, 0xe4, 0x8c, 0x8e, 0xa1, 0xa3, 0x2b, - 0x78, 0x05, 0xa0, 0xd9, 0x6b, 0x1a, 0xa6, 0x7e, 0x97, 0x68, 0x2d, 0x06, 0x9b, 0x0b, 0x62, 0x02, - 0x19, 0xda, 0x65, 0x58, 0x6a, 0xf6, 0x0e, 0x5a, 0x1d, 0xcd, 0x94, 0x30, 0x9b, 0xbd, 0xfb, 0xfd, - 0x8e, 0xc9, 0x94, 0x08, 0x97, 0xa1, 0xd0, 0xec, 0x99, 0xfa, 0xf7, 0x4c, 0x86, 0x8b, 0xeb, 0x04, - 0xab, 0xe8, 0xd9, 0x9d, 0xed, 0x1f, 0x65, 0x21, 0xc7, 0x9f, 0xaa, 0x56, 0xa0, 0xc4, 0xbd, 0x6d, - 0x3e, 0xea, 0xb2, 0x21, 0x4b, 0x90, 0x6b, 0x1a, 0xe6, 0x6d, 0xf4, 0x4b, 0x19, 0x0c, 0x90, 0xef, - 0xf3, 0xf2, 0x2f, 0x17, 0x58, 0xb9, 0x69, 0x98, 0xef, 0xde, 0x42, 0x3f, 0xc8, 0xb0, 0x6e, 0xfb, - 0xa2, 0xf2, 0x2b, 0xb1, 0x62, 0xf7, 0x26, 0xfa, 0x61, 0xa2, 0xd8, 0xbd, 0x89, 0x7e, 0x35, 0x56, - 0xbc, 0xb7, 0x8b, 0x7e, 0x2d, 0x51, 0xbc, 0xb7, 0x8b, 0x7e, 0x3d, 0x56, 0xdc, 0xba, 0x89, 0x7e, - 0x23, 0x51, 0xdc, 0xba, 0x89, 0x7e, 0xb3, 0xc0, 0xb0, 0x70, 0x24, 0xef, 0xed, 0xa2, 0xdf, 0x2a, - 0x26, 0xb5, 0x5b, 0x37, 0xd1, 0x6f, 0x17, 0x99, 0xff, 0x13, 0xaf, 0xa2, 0xdf, 0x41, 0x6c, 0x9a, - 0xcc, 0x41, 0xe8, 0x77, 0x79, 0x91, 0xa9, 0xd0, 0xef, 0x21, 0x86, 0x91, 0x49, 0x79, 0xf5, 0x23, - 0xae, 0x79, 0xa4, 0x6b, 0x04, 0xfd, 0x7e, 0x41, 0xbc, 0x6d, 0x6b, 0x34, 0xdb, 0x5a, 0x0b, 0x61, - 0xde, 0x82, 0xb1, 0xf2, 0x87, 0x37, 0x58, 0x91, 0x85, 0x27, 0xfa, 0xa3, 0x2e, 0x1b, 0xf0, 0x81, - 0x46, 0x1a, 0x1f, 0x68, 0x04, 0xfd, 0xf1, 0x0d, 0x36, 0xe0, 0x03, 0x8d, 0x48, 0xbe, 0xfe, 0xa4, - 0xcb, 0x0c, 0xb9, 0xea, 0xe3, 0x1b, 0x6c, 0xd2, 0x52, 0xfe, 0xa7, 0x5d, 0x5c, 0x84, 0xec, 0x5e, - 0xd3, 0x44, 0x3f, 0xe2, 0xa3, 0xb1, 0x10, 0x45, 0x7f, 0x86, 0x98, 0xb0, 0xa7, 0x9b, 0xe8, 0xcf, - 0x99, 0x30, 0x6f, 0xf6, 0xbb, 0x2d, 0x1d, 0xbd, 0xc1, 0x26, 0x77, 0x57, 0xef, 0xb4, 0x75, 0x93, - 0x3c, 0x42, 0x7f, 0xc1, 0xcd, 0xbf, 0xdb, 0xeb, 0x18, 0xe8, 0x13, 0x84, 0xab, 0x00, 0xfa, 0xf7, - 0xba, 0x44, 0xef, 0xf5, 0x9a, 0x1d, 0x03, 0xbd, 0xbd, 0x7d, 0x00, 0xe8, 0x7c, 0x3a, 0x60, 0x00, - 0xfa, 0xc6, 0x3d, 0xa3, 0xf3, 0xd0, 0x40, 0x57, 0x58, 0xa5, 0x4b, 0xf4, 0xae, 0x46, 0x74, 0xa4, - 0x60, 0x80, 0x82, 0x7c, 0x31, 0x97, 0xc1, 0xcb, 0x50, 0x24, 0x9d, 0x56, 0x6b, 0x4f, 0x6b, 0xdc, - 0x43, 0xd9, 0xbd, 0x6f, 0xc2, 0x8a, 0xe3, 0xef, 0x9c, 0x38, 0x11, 0x0d, 0x43, 0xf1, 0x18, 0xfa, - 0x43, 0x55, 0xd6, 0x1c, 0xff, 0xba, 0x28, 0x5d, 0x1f, 0xf9, 0xd7, 0x4f, 0xa2, 0xeb, 0x5c, 0x7b, - 0x9d, 0x67, 0x8c, 0xc3, 0x02, 0xaf, 0xbc, 0xf7, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xc5, 0x5b, - 0xfa, 0xe7, 0x6a, 0x2d, 0x00, 0x00, + // 3258 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5a, 0xcb, 0x73, 0xdb, 0x48, + 0x7a, 0x37, 0xf8, 0x12, 0xf9, 0x51, 0xa4, 0x5a, 0x4d, 0xc9, 0xe6, 0x68, 0x5e, 0x5a, 0xec, 0xce, + 0xae, 0xa2, 0xdd, 0xc8, 0x1e, 0x8d, 0xd7, 0x71, 0x66, 0x37, 0x89, 0x21, 0x0a, 0xf2, 0x70, 0x4c, + 0x82, 0x74, 0x13, 0xb4, 0xd7, 0x53, 0x5b, 0x85, 0x82, 0xc8, 0x36, 0x85, 0x12, 0x08, 0xd0, 0x00, + 0x28, 0x59, 0x37, 0x27, 0x9b, 0xcd, 0xfb, 0x31, 0x79, 0x4e, 0x36, 0xa9, 0x4c, 0x52, 0x95, 0x43, + 0x2a, 0x97, 0xfc, 0x0d, 0xa9, 0x1c, 0x72, 0xcc, 0x2d, 0x87, 0x24, 0x87, 0x9c, 0x52, 0xb9, 0x6d, + 0xe5, 0x94, 0x43, 0x0e, 0xa9, 0x54, 0x3f, 0x00, 0x82, 0x12, 0x67, 0xec, 0x75, 0x72, 0x91, 0x67, + 0x6e, 0xdd, 0xdf, 0xf7, 0xf5, 0xe3, 0xf7, 0xfb, 0x3e, 0x7c, 0xdd, 0xe8, 0x6e, 0x28, 0x3f, 0x99, + 0xd2, 0xe0, 0x6c, 0x67, 0x12, 0xf8, 0x91, 0x8f, 0xf3, 0xbc, 0xb2, 0x51, 0x8d, 0xfc, 0x89, 0x3f, + 0xb4, 0x23, 0x5b, 0x88, 0x37, 0xca, 0x27, 0x51, 0x30, 0x19, 0x88, 0x8a, 0xfa, 0x43, 0x05, 0x0a, + 0xa6, 0x1d, 0x8c, 0x68, 0x84, 0x37, 0xa0, 0x78, 0x4c, 0xcf, 0xc2, 0x89, 0x3d, 0xa0, 0x75, 0x65, + 0x53, 0xd9, 0x2a, 0x91, 0xa4, 0x8e, 0xd7, 0x20, 0x1f, 0x1e, 0xd9, 0xc1, 0xb0, 0x9e, 0xe1, 0x0a, + 0x51, 0xc1, 0xdf, 0x86, 0x72, 0x64, 0x1f, 0xba, 0x34, 0xb2, 0xa2, 0xb3, 0x09, 0xad, 0x67, 0x37, + 0x95, 0xad, 0xea, 0xee, 0xda, 0x4e, 0x32, 0x9e, 0xc9, 0x95, 0xe6, 0xd9, 0x84, 0x12, 0x88, 0x92, + 0x32, 0xc6, 0x90, 0x1b, 0x50, 0xd7, 0xad, 0xe7, 0x78, 0x5f, 0xbc, 0xac, 0xee, 0x43, 0xf5, 0x81, + 0x79, 0xd7, 0x8e, 0x68, 0xc3, 0x76, 0x5d, 0x1a, 0x34, 0xf7, 0xd9, 0x74, 0xa6, 0x21, 0x0d, 0x3c, + 0x7b, 0x9c, 0x4c, 0x27, 0xae, 0xe3, 0xab, 0x50, 0x18, 0x05, 0xfe, 0x74, 0x12, 0xd6, 0x33, 0x9b, + 0xd9, 0xad, 0x12, 0x91, 0x35, 0xf5, 0xfb, 0x00, 0xfa, 0x09, 0xf5, 0x22, 0xd3, 0x3f, 0xa6, 0x1e, + 0x7e, 0x03, 0x4a, 0x91, 0x33, 0xa6, 0x61, 0x64, 0x8f, 0x27, 0xbc, 0x8b, 0x2c, 0x99, 0x09, 0x3e, + 0x03, 0xd2, 0x06, 0x14, 0x27, 0x7e, 0xe8, 0x44, 0x8e, 0xef, 0x71, 0x3c, 0x25, 0x92, 0xd4, 0xd5, + 0x9f, 0x87, 0xfc, 0x03, 0xdb, 0x9d, 0x52, 0xfc, 0x36, 0xe4, 0x38, 0x60, 0x85, 0x03, 0x2e, 0xef, + 0x08, 0xd2, 0x39, 0x4e, 0xae, 0x60, 0x7d, 0x9f, 0x30, 0x4b, 0xde, 0xf7, 0x32, 0x11, 0x15, 0xf5, + 0x18, 0x96, 0xf7, 0x1c, 0x6f, 0xf8, 0xc0, 0x0e, 0x1c, 0x46, 0xc6, 0x4b, 0x76, 0x83, 0xbf, 0x06, + 0x05, 0x5e, 0x08, 0xeb, 0xd9, 0xcd, 0xec, 0x56, 0x79, 0x77, 0x59, 0x36, 0xe4, 0x73, 0x23, 0x52, + 0xa7, 0xfe, 0xbd, 0x02, 0xb0, 0xe7, 0x4f, 0xbd, 0xe1, 0x7d, 0xa6, 0xc4, 0x08, 0xb2, 0xe1, 0x13, + 0x57, 0x12, 0xc9, 0x8a, 0xf8, 0x1e, 0x54, 0x0f, 0x1d, 0x6f, 0x68, 0x9d, 0xc8, 0xe9, 0x08, 0x2e, + 0xcb, 0xbb, 0x5f, 0x93, 0xdd, 0xcd, 0x1a, 0xef, 0xa4, 0x67, 0x1d, 0xea, 0x5e, 0x14, 0x9c, 0x91, + 0xca, 0x61, 0x5a, 0xb6, 0xd1, 0x07, 0x7c, 0xd1, 0x88, 0x0d, 0x7a, 0x4c, 0xcf, 0xe2, 0x41, 0x8f, + 0xe9, 0x19, 0xfe, 0xa9, 0x34, 0xa2, 0xf2, 0x6e, 0x2d, 0x1e, 0x2b, 0xd5, 0x56, 0xc2, 0x7c, 0x3f, + 0x73, 0x5b, 0x51, 0xff, 0xa2, 0x00, 0x55, 0xfd, 0x29, 0x1d, 0x4c, 0x23, 0xda, 0x99, 0x30, 0x1f, + 0x84, 0x78, 0x07, 0x6a, 0x8e, 0x37, 0x70, 0xa7, 0x43, 0x6a, 0x51, 0xe6, 0x6a, 0x2b, 0x62, 0xbe, + 0xe6, 0xfd, 0x15, 0xc9, 0xaa, 0x54, 0xa5, 0x82, 0x40, 0x83, 0xda, 0xc0, 0x1f, 0x4f, 0xec, 0x60, + 0xde, 0x3e, 0xcb, 0xc7, 0x5f, 0x95, 0xe3, 0xcf, 0xec, 0xc9, 0xaa, 0xb4, 0x4e, 0x75, 0xd1, 0x86, + 0x15, 0xd9, 0xef, 0xd0, 0x7a, 0xec, 0x50, 0x77, 0x18, 0xf2, 0xd0, 0xad, 0x26, 0x54, 0xcd, 0x4f, + 0x71, 0xa7, 0x29, 0x8d, 0x0f, 0xb8, 0x2d, 0xa9, 0x3a, 0x73, 0x75, 0xbc, 0x0d, 0xab, 0x03, 0xd7, + 0x61, 0x53, 0x79, 0xcc, 0x28, 0xb6, 0x02, 0xff, 0x34, 0xac, 0xe7, 0xf9, 0xfc, 0x57, 0x84, 0xe2, + 0x80, 0xc9, 0x89, 0x7f, 0x1a, 0xe2, 0xf7, 0xa1, 0x78, 0xea, 0x07, 0xc7, 0xae, 0x6f, 0x0f, 0xeb, + 0x05, 0x3e, 0xe6, 0x5b, 0x8b, 0xc7, 0x7c, 0x28, 0xad, 0x48, 0x62, 0x8f, 0xb7, 0x00, 0x85, 0x4f, + 0x5c, 0x2b, 0xa4, 0x2e, 0x1d, 0x44, 0x96, 0xeb, 0x8c, 0x9d, 0xa8, 0x5e, 0xe4, 0x5f, 0x41, 0x35, + 0x7c, 0xe2, 0xf6, 0xb8, 0xb8, 0xc5, 0xa4, 0xd8, 0x82, 0xf5, 0x28, 0xb0, 0xbd, 0xd0, 0x1e, 0xb0, + 0xce, 0x2c, 0x27, 0xf4, 0x5d, 0x9b, 0x7f, 0x01, 0x25, 0x3e, 0xe4, 0xf6, 0xe2, 0x21, 0xcd, 0x59, + 0x93, 0x66, 0xdc, 0x82, 0xac, 0x45, 0x0b, 0xa4, 0xf8, 0x5d, 0x58, 0x0f, 0x8f, 0x9d, 0x89, 0xc5, + 0xfb, 0xb1, 0x26, 0xae, 0xed, 0x59, 0x03, 0x7b, 0x70, 0x44, 0xeb, 0xc0, 0x61, 0x63, 0xa6, 0xe4, + 0xa1, 0xd6, 0x75, 0x6d, 0xaf, 0xc1, 0x34, 0xea, 0x77, 0xa0, 0x3a, 0xcf, 0x23, 0x5e, 0x85, 0x8a, + 0xf9, 0xa8, 0xab, 0x5b, 0x9a, 0xb1, 0x6f, 0x19, 0x5a, 0x5b, 0x47, 0x57, 0x70, 0x05, 0x4a, 0x5c, + 0xd4, 0x31, 0x5a, 0x8f, 0x90, 0x82, 0x97, 0x20, 0xab, 0xb5, 0x5a, 0x28, 0xa3, 0xde, 0x86, 0x62, + 0x4c, 0x08, 0x5e, 0x81, 0x72, 0xdf, 0xe8, 0x75, 0xf5, 0x46, 0xf3, 0xa0, 0xa9, 0xef, 0xa3, 0x2b, + 0xb8, 0x08, 0xb9, 0x4e, 0xcb, 0xec, 0x22, 0x45, 0x94, 0xb4, 0x2e, 0xca, 0xb0, 0x96, 0xfb, 0x7b, + 0x1a, 0xca, 0xaa, 0x7f, 0xad, 0xc0, 0xda, 0x22, 0x60, 0xb8, 0x0c, 0x4b, 0xfb, 0xfa, 0x81, 0xd6, + 0x6f, 0x99, 0xe8, 0x0a, 0xae, 0xc1, 0x0a, 0xd1, 0xbb, 0xba, 0x66, 0x6a, 0x7b, 0x2d, 0xdd, 0x22, + 0xba, 0xb6, 0x8f, 0x14, 0x8c, 0xa1, 0xca, 0x4a, 0x56, 0xa3, 0xd3, 0x6e, 0x37, 0x4d, 0x53, 0xdf, + 0x47, 0x19, 0xbc, 0x06, 0x88, 0xcb, 0xfa, 0xc6, 0x4c, 0x9a, 0xc5, 0x08, 0x96, 0x7b, 0x3a, 0x69, + 0x6a, 0xad, 0xe6, 0x47, 0xac, 0x03, 0x94, 0xc3, 0x5f, 0x81, 0x37, 0x1b, 0x1d, 0xa3, 0xd7, 0xec, + 0x99, 0xba, 0x61, 0x5a, 0x3d, 0x43, 0xeb, 0xf6, 0x3e, 0xe8, 0x98, 0xbc, 0x67, 0x01, 0x2e, 0x8f, + 0xab, 0x00, 0x5a, 0xdf, 0xec, 0x88, 0x7e, 0x50, 0xe1, 0xc3, 0x5c, 0x51, 0x41, 0x19, 0xf5, 0x93, + 0x0c, 0xe4, 0x39, 0x3f, 0x2c, 0xab, 0xa6, 0x72, 0x25, 0x2f, 0x27, 0x19, 0x26, 0xf3, 0x39, 0x19, + 0x86, 0x27, 0x66, 0x99, 0xeb, 0x44, 0x05, 0xbf, 0x0e, 0x25, 0x3f, 0x18, 0x59, 0x42, 0x23, 0xb2, + 0x74, 0xd1, 0x0f, 0x46, 0x3c, 0x9d, 0xb3, 0x0c, 0xc9, 0x92, 0xfb, 0xa1, 0x1d, 0x52, 0x1e, 0xb5, + 0x25, 0x92, 0xd4, 0xf1, 0x6b, 0xc0, 0xec, 0x2c, 0x3e, 0x8f, 0x02, 0xd7, 0x2d, 0xf9, 0xc1, 0xc8, + 0x60, 0x53, 0xf9, 0x2a, 0x54, 0x06, 0xbe, 0x3b, 0x1d, 0x7b, 0x96, 0x4b, 0xbd, 0x51, 0x74, 0x54, + 0x5f, 0xda, 0x54, 0xb6, 0x2a, 0x64, 0x59, 0x08, 0x5b, 0x5c, 0x86, 0xeb, 0xb0, 0x34, 0x38, 0xb2, + 0x83, 0x90, 0x8a, 0x48, 0xad, 0x90, 0xb8, 0xca, 0x47, 0xa5, 0x03, 0x67, 0x6c, 0xbb, 0x21, 0x8f, + 0xca, 0x0a, 0x49, 0xea, 0x0c, 0xc4, 0x63, 0xd7, 0x1e, 0x85, 0x3c, 0x9a, 0x2a, 0x44, 0x54, 0xd4, + 0x9f, 0x81, 0x2c, 0xf1, 0x4f, 0x59, 0x97, 0x62, 0xc0, 0xb0, 0xae, 0x6c, 0x66, 0xb7, 0x30, 0x89, + 0xab, 0x6c, 0x11, 0x91, 0x79, 0x54, 0xa4, 0xd7, 0x38, 0x73, 0x7e, 0x1f, 0x96, 0x09, 0x0d, 0xa7, + 0x6e, 0xa4, 0x3f, 0x8d, 0x02, 0x3b, 0xc4, 0xbb, 0x50, 0x4e, 0x67, 0x0e, 0xe5, 0xb3, 0x32, 0x07, + 0xd0, 0x59, 0xca, 0xa8, 0xc3, 0xd2, 0xe3, 0x80, 0x86, 0x47, 0x34, 0x90, 0x99, 0x29, 0xae, 0xb2, + 0xbc, 0x5c, 0xe6, 0xa1, 0x2e, 0xc6, 0x60, 0xd9, 0x5c, 0xe6, 0x14, 0x65, 0x2e, 0x9b, 0x73, 0xa7, + 0x12, 0xa9, 0x63, 0xec, 0xb1, 0x34, 0x61, 0xd9, 0x8f, 0x1f, 0xd3, 0x41, 0x44, 0xc5, 0xa2, 0x95, + 0x23, 0xcb, 0x4c, 0xa8, 0x49, 0x19, 0x73, 0x9b, 0xe3, 0x85, 0x34, 0x88, 0x2c, 0x67, 0xc8, 0x1d, + 0x9a, 0x23, 0x45, 0x21, 0x68, 0x0e, 0xf1, 0x5b, 0x90, 0xe3, 0x89, 0x26, 0xc7, 0x47, 0x01, 0x39, + 0x0a, 0xf1, 0x4f, 0x09, 0x97, 0xe3, 0x6f, 0x42, 0x81, 0x72, 0xbc, 0xdc, 0xa9, 0xb3, 0xd4, 0x9c, + 0xa6, 0x82, 0x48, 0x13, 0xf5, 0xbb, 0xb0, 0xcc, 0x31, 0x3c, 0xb4, 0x03, 0xcf, 0xf1, 0x46, 0x7c, + 0x45, 0xf7, 0x87, 0x22, 0xf6, 0x2a, 0x84, 0x97, 0x19, 0x05, 0x63, 0x1a, 0x86, 0xf6, 0x88, 0xca, + 0x15, 0x36, 0xae, 0xaa, 0x7f, 0x99, 0x85, 0x72, 0x2f, 0x0a, 0xa8, 0x3d, 0xe6, 0xec, 0xe1, 0xef, + 0x02, 0x84, 0x91, 0x1d, 0xd1, 0x31, 0xf5, 0xa2, 0x98, 0x86, 0x37, 0xe4, 0xf0, 0x29, 0xbb, 0x9d, + 0x5e, 0x6c, 0x44, 0x52, 0xf6, 0xe7, 0xdd, 0x93, 0x79, 0x01, 0xf7, 0x6c, 0x7c, 0x9a, 0x81, 0x52, + 0xd2, 0x1b, 0xd6, 0xa0, 0x38, 0xb0, 0x23, 0x3a, 0xf2, 0x83, 0x33, 0xb9, 0x16, 0xbf, 0xf3, 0x79, + 0xa3, 0xef, 0x34, 0xa4, 0x31, 0x49, 0x9a, 0xe1, 0x37, 0x41, 0x6c, 0x70, 0x44, 0xe8, 0x0b, 0xbc, + 0x25, 0x2e, 0xe1, 0xc1, 0xff, 0x3e, 0xe0, 0x49, 0xe0, 0x8c, 0xed, 0xe0, 0xcc, 0x3a, 0xa6, 0x67, + 0xf1, 0x22, 0x92, 0x5d, 0xe0, 0x70, 0x24, 0xed, 0xee, 0xd1, 0x33, 0x99, 0xf6, 0x6e, 0xcf, 0xb7, + 0x95, 0x21, 0x7b, 0xd1, 0x8d, 0xa9, 0x96, 0x7c, 0x27, 0x10, 0xc6, 0x6b, 0x7e, 0x9e, 0x47, 0x37, + 0x2b, 0xaa, 0xdf, 0x80, 0x62, 0x3c, 0x79, 0x5c, 0x82, 0xbc, 0x1e, 0x04, 0x7e, 0x80, 0xae, 0xf0, + 0xec, 0xd7, 0x6e, 0x89, 0x04, 0xba, 0xbf, 0xcf, 0x12, 0xe8, 0xdf, 0x65, 0x92, 0x85, 0x97, 0xd0, + 0x27, 0x53, 0x1a, 0x46, 0xf8, 0x17, 0xa0, 0x46, 0x79, 0xa4, 0x39, 0x27, 0xd4, 0x1a, 0xf0, 0x5d, + 0x1a, 0x8b, 0x33, 0xf1, 0x39, 0xac, 0xec, 0x88, 0x4d, 0x65, 0xbc, 0x7b, 0x23, 0xab, 0x89, 0xad, + 0x14, 0x0d, 0xb1, 0x0e, 0x35, 0x67, 0x3c, 0xa6, 0x43, 0xc7, 0x8e, 0xd2, 0x1d, 0x08, 0x87, 0xad, + 0xc7, 0x9b, 0x98, 0xb9, 0x4d, 0x20, 0x59, 0x4d, 0x5a, 0x24, 0xdd, 0xbc, 0x03, 0x85, 0x88, 0x6f, + 0x58, 0xe5, 0x1a, 0x5e, 0x89, 0xb3, 0x1a, 0x17, 0x12, 0xa9, 0xc4, 0xdf, 0x00, 0xb1, 0xfd, 0xe5, + 0xf9, 0x6b, 0x16, 0x10, 0xb3, 0x5d, 0x0d, 0x11, 0x7a, 0xfc, 0x0e, 0x54, 0xe7, 0x16, 0xbf, 0x21, + 0x27, 0x2c, 0x4b, 0x2a, 0xe9, 0x95, 0x6c, 0x88, 0xaf, 0xc3, 0x92, 0x2f, 0x16, 0x3e, 0x9e, 0xd9, + 0x66, 0x33, 0x9e, 0x5f, 0x15, 0x49, 0x6c, 0xa5, 0xfe, 0x1c, 0xac, 0x24, 0x0c, 0x86, 0x13, 0xdf, + 0x0b, 0x29, 0xde, 0x86, 0x42, 0xc0, 0x3f, 0x27, 0xc9, 0x1a, 0x96, 0x5d, 0xa4, 0xf2, 0x01, 0x91, + 0x16, 0xea, 0x10, 0x56, 0x84, 0xe4, 0xa1, 0x13, 0x1d, 0x71, 0x47, 0xe1, 0x77, 0x20, 0x4f, 0x59, + 0xe1, 0x1c, 0xe7, 0xa4, 0xdb, 0xe0, 0x7a, 0x22, 0xb4, 0xa9, 0x51, 0x32, 0xcf, 0x1d, 0xe5, 0x3f, + 0x33, 0x50, 0x93, 0xb3, 0xdc, 0xb3, 0xa3, 0xc1, 0xd1, 0x25, 0x75, 0xf6, 0x37, 0x61, 0x89, 0xc9, + 0x9d, 0xe4, 0xc3, 0x58, 0xe0, 0xee, 0xd8, 0x82, 0x39, 0xdc, 0x0e, 0xad, 0x94, 0x77, 0xe5, 0xe6, + 0xab, 0x62, 0x87, 0xa9, 0x95, 0x7f, 0x41, 0x5c, 0x14, 0x9e, 0x13, 0x17, 0x4b, 0x2f, 0x14, 0x17, + 0xfb, 0xb0, 0x36, 0xcf, 0xb8, 0x0c, 0x8e, 0x6f, 0xc1, 0x92, 0x70, 0x4a, 0x9c, 0x02, 0x17, 0xf9, + 0x2d, 0x36, 0x51, 0xff, 0x21, 0x03, 0x6b, 0x32, 0x3b, 0x7d, 0x31, 0x3e, 0xd3, 0x14, 0xcf, 0xf9, + 0x17, 0xe1, 0xf9, 0x05, 0xfd, 0xa7, 0x36, 0x60, 0xfd, 0x1c, 0x8f, 0x2f, 0xf1, 0xb1, 0xfe, 0x58, + 0x81, 0xe5, 0x3d, 0x3a, 0x72, 0xbc, 0x4b, 0xea, 0x85, 0x14, 0xb9, 0xb9, 0x17, 0x0a, 0xe2, 0x5b, + 0x50, 0x91, 0x78, 0x25, 0x5b, 0x17, 0xd9, 0x56, 0x16, 0xb1, 0xfd, 0xef, 0x0a, 0x54, 0x1a, 0xfe, + 0x78, 0xec, 0x44, 0x97, 0x94, 0xa9, 0x8b, 0x38, 0x73, 0x8b, 0x70, 0x22, 0xa8, 0xc6, 0x30, 0x05, + 0x41, 0xea, 0x7f, 0x28, 0xb0, 0x42, 0x7c, 0xd7, 0x3d, 0xb4, 0x07, 0xc7, 0xaf, 0x36, 0x76, 0x0c, + 0x68, 0x06, 0x54, 0xa2, 0xff, 0x6f, 0x05, 0xaa, 0xdd, 0x80, 0xb2, 0x1f, 0xeb, 0x57, 0x1a, 0x3c, + 0xdb, 0x09, 0x0f, 0x23, 0xb9, 0x87, 0x28, 0x11, 0x5e, 0x56, 0x57, 0x61, 0x25, 0xc1, 0x2e, 0xf9, + 0xf8, 0x17, 0x05, 0xd6, 0x45, 0x80, 0x48, 0xcd, 0xf0, 0x92, 0xd2, 0x12, 0xe3, 0xcd, 0xa5, 0xf0, + 0xd6, 0xe1, 0xea, 0x79, 0x6c, 0x12, 0xf6, 0x0f, 0x32, 0x70, 0x2d, 0x8e, 0x8d, 0x4b, 0x0e, 0xfc, + 0xff, 0x10, 0x0f, 0x1b, 0x50, 0xbf, 0x48, 0x82, 0x64, 0xe8, 0xe3, 0x0c, 0xd4, 0x1b, 0x01, 0xb5, + 0x23, 0x9a, 0xda, 0x8b, 0xbc, 0x3a, 0xb1, 0x81, 0xdf, 0x85, 0xe5, 0x89, 0x1d, 0x44, 0xce, 0xc0, + 0x99, 0xd8, 0xec, 0x6f, 0x2f, 0xcf, 0xb7, 0x3a, 0xe7, 0x3a, 0x98, 0x33, 0x51, 0x5f, 0x87, 0xd7, + 0x16, 0x30, 0x22, 0xf9, 0xfa, 0x1f, 0x05, 0x70, 0x2f, 0xb2, 0x83, 0xe8, 0x0b, 0xb0, 0xaa, 0x2c, + 0x0c, 0xa6, 0x75, 0xa8, 0xcd, 0xe1, 0x4f, 0xf3, 0x42, 0xa3, 0x2f, 0xc4, 0x8a, 0xf3, 0x99, 0xbc, + 0xa4, 0xf1, 0x4b, 0x5e, 0xfe, 0x4d, 0x81, 0x8d, 0x86, 0x2f, 0x0e, 0x16, 0x5f, 0xc9, 0x2f, 0x4c, + 0x7d, 0x13, 0x5e, 0x5f, 0x08, 0x50, 0x12, 0xf0, 0xaf, 0x0a, 0x5c, 0x25, 0xd4, 0x1e, 0xbe, 0x9a, + 0xe0, 0xef, 0xc3, 0xb5, 0x0b, 0xe0, 0xe4, 0x0e, 0xf5, 0x16, 0x14, 0xc7, 0x34, 0xb2, 0x87, 0x76, + 0x64, 0x4b, 0x48, 0x1b, 0x71, 0xbf, 0x33, 0xeb, 0xb6, 0xb4, 0x20, 0x89, 0xad, 0xfa, 0x69, 0x06, + 0x6a, 0x7c, 0xaf, 0xfb, 0xe5, 0x8f, 0xd6, 0xe2, 0x7f, 0x81, 0x8f, 0x15, 0x58, 0x9b, 0x27, 0x28, + 0xf9, 0x27, 0xf8, 0xff, 0x3e, 0xaf, 0x58, 0x90, 0x10, 0xb2, 0x8b, 0xb6, 0xa0, 0xff, 0x98, 0x81, + 0x7a, 0x7a, 0x4a, 0x5f, 0x9e, 0x6d, 0xcc, 0x9f, 0x6d, 0xfc, 0xc4, 0x87, 0x59, 0x9f, 0x28, 0xf0, + 0xda, 0x02, 0x42, 0x7f, 0x32, 0x47, 0xa7, 0x4e, 0x38, 0x32, 0xcf, 0x3d, 0xe1, 0x78, 0x51, 0x57, + 0xff, 0xb3, 0x02, 0x6b, 0x6d, 0x71, 0xb0, 0x2c, 0xfe, 0xe3, 0x2f, 0x6f, 0x36, 0xe3, 0x67, 0xc7, + 0xb9, 0xd9, 0xf5, 0x8d, 0xda, 0x80, 0xf5, 0x73, 0xd0, 0x5e, 0xe2, 0x6c, 0xe2, 0xbf, 0x14, 0x58, + 0x95, 0xbd, 0x68, 0x97, 0x76, 0x23, 0xb0, 0x80, 0x1d, 0xfc, 0x16, 0x64, 0x9d, 0x61, 0xbc, 0x83, + 0x9c, 0xbf, 0x04, 0x67, 0x0a, 0xf5, 0x0e, 0xe0, 0x34, 0xee, 0x97, 0xa0, 0xee, 0x9f, 0xb2, 0xb0, + 0xda, 0x9b, 0xb8, 0x4e, 0x24, 0x95, 0xaf, 0x76, 0xe2, 0xff, 0x0a, 0x2c, 0x87, 0x0c, 0xac, 0x25, + 0xae, 0xe4, 0x38, 0xb1, 0x25, 0x52, 0xe6, 0xb2, 0x06, 0x17, 0xe1, 0xb7, 0xa1, 0x1c, 0x9b, 0x4c, + 0xbd, 0x48, 0x1e, 0xa8, 0x81, 0xb4, 0x98, 0x7a, 0x11, 0xbe, 0x09, 0xd7, 0xbc, 0xe9, 0x98, 0x5f, + 0x69, 0x5b, 0x13, 0x1a, 0xc4, 0x17, 0xbe, 0x76, 0x10, 0x5f, 0x3d, 0xd7, 0xbc, 0xe9, 0x98, 0xf8, + 0xa7, 0x61, 0x97, 0x06, 0xe2, 0xc2, 0xd7, 0x0e, 0x22, 0x7c, 0x07, 0x4a, 0xb6, 0x3b, 0xf2, 0x03, + 0x27, 0x3a, 0x1a, 0xcb, 0x3b, 0x67, 0x35, 0xbe, 0x81, 0x39, 0x4f, 0xff, 0x8e, 0x16, 0x5b, 0x92, + 0x59, 0x23, 0xf5, 0x5b, 0x50, 0x4a, 0xe4, 0x18, 0xc1, 0xb2, 0x7e, 0xbf, 0xaf, 0xb5, 0xac, 0x5e, + 0xb7, 0xd5, 0x34, 0x7b, 0xe2, 0x9e, 0xf8, 0xa0, 0xdf, 0x6a, 0x59, 0xbd, 0x86, 0x66, 0x20, 0x45, + 0x25, 0x00, 0xbc, 0x4b, 0xde, 0xf9, 0x8c, 0x20, 0xe5, 0x39, 0x04, 0xbd, 0x0e, 0xa5, 0xc0, 0x3f, + 0x95, 0xd8, 0x33, 0x1c, 0x4e, 0x31, 0xf0, 0x4f, 0x39, 0x72, 0x55, 0x03, 0x9c, 0x9e, 0xab, 0x8c, + 0xb6, 0x54, 0xf2, 0x56, 0xe6, 0x92, 0xf7, 0x6c, 0xfc, 0x24, 0x79, 0x8b, 0xad, 0x3c, 0xfb, 0xce, + 0x3f, 0xa0, 0xb6, 0x1b, 0xc5, 0xeb, 0x95, 0xfa, 0x57, 0x19, 0xa8, 0x10, 0x26, 0x71, 0xc6, 0xb4, + 0x17, 0xd9, 0x51, 0xc8, 0x3c, 0x75, 0xc4, 0x4d, 0xac, 0x59, 0xda, 0x2d, 0x91, 0xb2, 0x90, 0x89, + 0xbb, 0x82, 0x5d, 0x58, 0x0f, 0xe9, 0xc0, 0xf7, 0x86, 0xa1, 0x75, 0x48, 0x8f, 0x1c, 0x6f, 0x68, + 0x8d, 0xed, 0x30, 0x92, 0xd7, 0x91, 0x15, 0x52, 0x93, 0xca, 0x3d, 0xae, 0x6b, 0x73, 0x15, 0xbe, + 0x01, 0x6b, 0x87, 0x8e, 0xe7, 0xfa, 0x23, 0x6b, 0xe2, 0xda, 0x67, 0x34, 0x08, 0x25, 0x54, 0x16, + 0x5e, 0x79, 0x82, 0x85, 0xae, 0x2b, 0x54, 0xc2, 0xdd, 0x1f, 0xc1, 0xf6, 0xc2, 0x51, 0xac, 0xc7, + 0x8e, 0x1b, 0xd1, 0x80, 0x0e, 0xad, 0x80, 0x4e, 0x5c, 0x67, 0x20, 0x5e, 0x13, 0x88, 0xbd, 0xfb, + 0xd7, 0x17, 0x0c, 0x7d, 0x20, 0xcd, 0xc9, 0xcc, 0x9a, 0xb1, 0x3d, 0x98, 0x4c, 0xad, 0x29, 0xbf, + 0x41, 0x64, 0xab, 0x98, 0x42, 0x8a, 0x83, 0xc9, 0xb4, 0xcf, 0xea, 0x18, 0x41, 0xf6, 0xc9, 0x44, + 0x2c, 0x5e, 0x0a, 0x61, 0x45, 0xf5, 0xc7, 0x0a, 0x54, 0xb5, 0xd1, 0x28, 0xa0, 0x23, 0x3b, 0x92, + 0x34, 0xdd, 0x80, 0x35, 0x41, 0xc9, 0x99, 0x25, 0x9f, 0x29, 0x09, 0x3c, 0x8a, 0xc0, 0x23, 0x75, + 0xe2, 0x91, 0x52, 0x1c, 0xbe, 0x57, 0xa7, 0xde, 0xc2, 0x36, 0x19, 0xde, 0x66, 0x2d, 0xd1, 0xa6, + 0x5b, 0xfd, 0x2c, 0xbc, 0xb6, 0x98, 0x85, 0xb1, 0x23, 0x1e, 0x9a, 0x54, 0xc8, 0xd5, 0x05, 0xa0, + 0xdb, 0x8e, 0xf7, 0x39, 0x4d, 0xed, 0xa7, 0x9c, 0xaf, 0xcf, 0x68, 0x6a, 0x3f, 0x55, 0xff, 0x26, + 0xb9, 0x01, 0x88, 0xc3, 0x25, 0x59, 0x8d, 0xe3, 0xbc, 0xa0, 0x7c, 0x5e, 0x5e, 0xa8, 0xc3, 0x52, + 0x48, 0x83, 0x13, 0xc7, 0x1b, 0xc5, 0x57, 0xd4, 0xb2, 0x8a, 0x7b, 0xf0, 0x75, 0x89, 0x9d, 0x3e, + 0x8d, 0x68, 0xe0, 0xd9, 0xae, 0x7b, 0x66, 0x89, 0x83, 0x0a, 0x2f, 0xa2, 0x43, 0x6b, 0xf6, 0xa8, + 0x4a, 0xac, 0xc8, 0x5f, 0x15, 0xd6, 0x7a, 0x62, 0x4c, 0x12, 0x5b, 0x33, 0x79, 0x6e, 0xf5, 0x1d, + 0xa8, 0x06, 0x32, 0x88, 0xad, 0x90, 0xb9, 0x47, 0xe6, 0xa3, 0xb5, 0xe4, 0x9e, 0x39, 0x15, 0xe1, + 0xa4, 0x12, 0xcc, 0x05, 0xfc, 0x6d, 0x58, 0x96, 0x33, 0xb2, 0x5d, 0xc7, 0x9e, 0x6d, 0x4c, 0xcf, + 0xbd, 0x34, 0xd3, 0x98, 0x92, 0xc8, 0x37, 0x69, 0xbc, 0xf2, 0x61, 0xae, 0x58, 0x40, 0x4b, 0xec, + 0x6f, 0xb8, 0xd6, 0x9f, 0x0c, 0x79, 0x64, 0x5c, 0xe2, 0x3d, 0x42, 0xfa, 0x71, 0x5a, 0x6e, 0xfe, + 0x71, 0xda, 0xfc, 0x63, 0xb7, 0xfc, 0xb9, 0xc7, 0x6e, 0xea, 0x1d, 0x58, 0x9b, 0xc7, 0x2f, 0x63, + 0x65, 0x0b, 0xf2, 0xfc, 0x5a, 0xfc, 0xdc, 0x62, 0x98, 0xba, 0xf7, 0x26, 0xc2, 0x40, 0xfd, 0x5b, + 0x05, 0x6a, 0x0b, 0x7e, 0x94, 0x92, 0xbf, 0x30, 0x25, 0x75, 0xc8, 0xf3, 0xd3, 0x90, 0xe7, 0x17, + 0xf4, 0xf2, 0xdd, 0xc9, 0xb5, 0x8b, 0xff, 0x59, 0xfc, 0x32, 0x9d, 0x08, 0x2b, 0x96, 0xce, 0x78, + 0x58, 0x0c, 0xf8, 0x29, 0x4f, 0xbc, 0xcf, 0x2b, 0x33, 0x99, 0x38, 0xf8, 0xb9, 0x78, 0x6c, 0x94, + 0x7b, 0xee, 0xb1, 0xd1, 0xf6, 0xef, 0x67, 0xa1, 0xd4, 0x3e, 0xeb, 0x3d, 0x71, 0x0f, 0x5c, 0x7b, + 0xc4, 0x6f, 0xbb, 0xdb, 0x5d, 0xf3, 0x11, 0xba, 0x82, 0x57, 0xa1, 0x62, 0x74, 0x4c, 0xcb, 0x60, + 0x0b, 0xc2, 0x41, 0x4b, 0xbb, 0x8b, 0x14, 0xb6, 0x62, 0x74, 0x49, 0xd3, 0xba, 0xa7, 0x3f, 0x12, + 0x92, 0x0c, 0xae, 0xc1, 0x4a, 0xdf, 0x68, 0xde, 0xef, 0xeb, 0x33, 0x61, 0x0e, 0xaf, 0xc3, 0x6a, + 0xbb, 0xdf, 0x32, 0x9b, 0xdd, 0x56, 0x4a, 0x5c, 0x64, 0xab, 0xcb, 0x5e, 0xab, 0xb3, 0x27, 0xaa, + 0x88, 0xf5, 0xdf, 0x37, 0x7a, 0xcd, 0xbb, 0x86, 0xbe, 0x2f, 0x44, 0x9b, 0x4c, 0xf4, 0x91, 0x4e, + 0x3a, 0x07, 0xcd, 0x78, 0xc8, 0x3b, 0x18, 0x41, 0x79, 0xaf, 0x69, 0x68, 0x44, 0xf6, 0xf2, 0x4c, + 0xc1, 0x55, 0x28, 0xe9, 0x46, 0xbf, 0x2d, 0xeb, 0x19, 0x5c, 0x87, 0x9a, 0xd6, 0x37, 0x3b, 0x56, + 0xd3, 0x68, 0x10, 0xbd, 0xad, 0x1b, 0xa6, 0xd4, 0xe4, 0x70, 0x0d, 0xaa, 0x66, 0xb3, 0xad, 0xf7, + 0x4c, 0xad, 0xdd, 0x95, 0x42, 0x36, 0x8b, 0x62, 0x4f, 0x8f, 0x6d, 0x10, 0xde, 0x80, 0x75, 0xa3, + 0x63, 0xc9, 0x27, 0x4b, 0xd6, 0x03, 0xad, 0xd5, 0xd7, 0xa5, 0x6e, 0x13, 0x5f, 0x03, 0xdc, 0x31, + 0xac, 0x7e, 0x77, 0x5f, 0x33, 0x75, 0xcb, 0xe8, 0x3c, 0x94, 0x8a, 0x3b, 0xb8, 0x0a, 0xc5, 0xd9, + 0x0c, 0x9e, 0x31, 0x16, 0x2a, 0x5d, 0x8d, 0x98, 0x33, 0xb0, 0xcf, 0x9e, 0x31, 0xb2, 0xe0, 0x2e, + 0xe9, 0xf4, 0xbb, 0x33, 0xb3, 0x55, 0x28, 0x4b, 0xb2, 0xa4, 0x28, 0xc7, 0x44, 0x7b, 0x4d, 0xa3, + 0x91, 0xcc, 0xef, 0x59, 0x71, 0x23, 0x83, 0x94, 0xed, 0x63, 0xc8, 0x71, 0x77, 0x14, 0x21, 0x67, + 0x74, 0x0c, 0x1d, 0x5d, 0xc1, 0x2b, 0x00, 0xcd, 0x5e, 0xd3, 0x30, 0xf5, 0xbb, 0x44, 0x6b, 0x31, + 0xd8, 0x5c, 0x10, 0x13, 0xc8, 0xd0, 0x2e, 0xc3, 0x52, 0xb3, 0x77, 0xd0, 0xea, 0x68, 0xa6, 0x84, + 0xd9, 0xec, 0xdd, 0xef, 0x77, 0x4c, 0xa6, 0x44, 0xb8, 0x0c, 0x85, 0x66, 0xcf, 0xd4, 0xbf, 0x67, + 0x32, 0x5c, 0x5c, 0x27, 0x58, 0x45, 0xcf, 0xee, 0x6c, 0xff, 0x28, 0x0b, 0x39, 0xfe, 0xe0, 0xb4, + 0x02, 0x25, 0xee, 0x6d, 0xf3, 0x51, 0x97, 0x0d, 0x59, 0x82, 0x5c, 0xd3, 0x30, 0x6f, 0xa3, 0x5f, + 0xcc, 0x60, 0x80, 0x7c, 0x9f, 0x97, 0x7f, 0xa9, 0xc0, 0xca, 0x4d, 0xc3, 0x7c, 0xf7, 0x16, 0xfa, + 0x41, 0x86, 0x75, 0xdb, 0x17, 0x95, 0x5f, 0x8e, 0x15, 0xbb, 0x37, 0xd1, 0x0f, 0x13, 0xc5, 0xee, + 0x4d, 0xf4, 0x2b, 0xb1, 0xe2, 0xbd, 0x5d, 0xf4, 0xab, 0x89, 0xe2, 0xbd, 0x5d, 0xf4, 0x6b, 0xb1, + 0xe2, 0xd6, 0x4d, 0xf4, 0xeb, 0x89, 0xe2, 0xd6, 0x4d, 0xf4, 0x1b, 0x05, 0x86, 0x85, 0x23, 0x79, + 0x6f, 0x17, 0xfd, 0x66, 0x31, 0xa9, 0xdd, 0xba, 0x89, 0x7e, 0xab, 0xc8, 0xfc, 0x9f, 0x78, 0x15, + 0xfd, 0x36, 0x62, 0xd3, 0x64, 0x0e, 0x42, 0xbf, 0xc3, 0x8b, 0x4c, 0x85, 0x7e, 0x17, 0x31, 0x8c, + 0x4c, 0xca, 0xab, 0x1f, 0x73, 0xcd, 0x23, 0x5d, 0x23, 0xe8, 0xf7, 0x0a, 0xe2, 0x85, 0x5a, 0xa3, + 0xd9, 0xd6, 0x5a, 0x08, 0xf3, 0x16, 0x8c, 0x95, 0x3f, 0xb8, 0xc1, 0x8a, 0x2c, 0x3c, 0xd1, 0x1f, + 0x76, 0xd9, 0x80, 0x0f, 0x34, 0xd2, 0xf8, 0x40, 0x23, 0xe8, 0x8f, 0x6e, 0xb0, 0x01, 0x1f, 0x68, + 0x44, 0xf2, 0xf5, 0xc7, 0x5d, 0x66, 0xc8, 0x55, 0x9f, 0xdc, 0x60, 0x93, 0x96, 0xf2, 0x3f, 0xe9, + 0xe2, 0x22, 0x64, 0xf7, 0x9a, 0x26, 0xfa, 0x11, 0x1f, 0x8d, 0x85, 0x28, 0xfa, 0x53, 0xc4, 0x84, + 0x3d, 0xdd, 0x44, 0x7f, 0xc6, 0x84, 0x79, 0xb3, 0xdf, 0x6d, 0xe9, 0xe8, 0x0d, 0x36, 0xb9, 0xbb, + 0x7a, 0xa7, 0xad, 0x9b, 0xe4, 0x11, 0xfa, 0x73, 0x6e, 0xfe, 0x61, 0xaf, 0x63, 0xa0, 0x4f, 0x11, + 0xae, 0x02, 0xe8, 0xdf, 0xeb, 0x12, 0xbd, 0xd7, 0x6b, 0x76, 0x0c, 0xf4, 0xf6, 0xf6, 0x01, 0xa0, + 0xf3, 0xe9, 0x80, 0x01, 0xe8, 0x1b, 0xf7, 0x8c, 0xce, 0x43, 0x03, 0x5d, 0x61, 0x95, 0x2e, 0xd1, + 0xbb, 0x1a, 0xd1, 0x91, 0x82, 0x01, 0x0a, 0xf2, 0xdd, 0x5b, 0x06, 0x2f, 0x43, 0x91, 0x74, 0x5a, + 0xad, 0x3d, 0xad, 0x71, 0x0f, 0x65, 0xf7, 0xbe, 0x0d, 0x2b, 0x8e, 0xbf, 0x73, 0xe2, 0x44, 0x34, + 0x0c, 0xc5, 0x93, 0xe6, 0x8f, 0x54, 0x59, 0x73, 0xfc, 0xeb, 0xa2, 0x74, 0x7d, 0xe4, 0x5f, 0x3f, + 0x89, 0xae, 0x73, 0xed, 0x75, 0x9e, 0x31, 0x0e, 0x0b, 0xbc, 0xf2, 0xde, 0xff, 0x06, 0x00, 0x00, + 0xff, 0xff, 0x40, 0x99, 0x5d, 0x63, 0x30, 0x2d, 0x00, 0x00, } diff --git a/go/vt/proto/tabletmanagerdata/tabletmanagerdata.pb.go b/go/vt/proto/tabletmanagerdata/tabletmanagerdata.pb.go index fd1f76410e8..52c75655d2e 100644 --- a/go/vt/proto/tabletmanagerdata/tabletmanagerdata.pb.go +++ b/go/vt/proto/tabletmanagerdata/tabletmanagerdata.pb.go @@ -5,8 +5,9 @@ package tabletmanagerdata import ( fmt "fmt" - proto "github.com/golang/protobuf/proto" math "math" + + proto "github.com/golang/protobuf/proto" logutil "vitess.io/vitess/go/vt/proto/logutil" query "vitess.io/vitess/go/vt/proto/query" replicationdata "vitess.io/vitess/go/vt/proto/replicationdata" diff --git a/go/vt/proto/topodata/topodata.pb.go b/go/vt/proto/topodata/topodata.pb.go index b5a704f817b..d2cdc91a79b 100644 --- a/go/vt/proto/topodata/topodata.pb.go +++ b/go/vt/proto/topodata/topodata.pb.go @@ -1384,82 +1384,82 @@ var fileDescriptor_52c350cb619f972e = []byte{ 0x5f, 0xa1, 0x87, 0xf6, 0xdc, 0x37, 0xe8, 0xfb, 0xf4, 0xd8, 0x4b, 0xfb, 0x1c, 0x3d, 0x14, 0x3b, 0x4b, 0x52, 0x94, 0x14, 0xa7, 0x4e, 0xe1, 0xdb, 0xcc, 0xec, 0xcc, 0x70, 0xe6, 0xb7, 0xbf, 0x99, 0x95, 0xa0, 0x22, 0xc3, 0x49, 0x38, 0xf4, 0xa4, 0xd7, 0x98, 0xf0, 0x50, 0x86, 0xc4, 0x8c, 0xf5, - 0x2a, 0x48, 0x7f, 0xcc, 0xb4, 0xb5, 0xb6, 0x0b, 0xe6, 0x21, 0x9b, 0x51, 0x2f, 0xb8, 0x60, 0x64, - 0x03, 0xf2, 0x42, 0x7a, 0x5c, 0x3a, 0xc6, 0x96, 0x51, 0xb7, 0xa8, 0x56, 0x88, 0x0d, 0x59, 0x16, - 0x0c, 0x9d, 0x0c, 0xda, 0x94, 0x58, 0x7b, 0x04, 0xa5, 0xbe, 0x77, 0x36, 0x62, 0xb2, 0x39, 0xf2, - 0x3d, 0x41, 0x08, 0xe4, 0x06, 0x6c, 0x34, 0xc2, 0xa8, 0x22, 0x45, 0x59, 0x05, 0x5d, 0xf9, 0x3a, - 0xa8, 0x4c, 0x95, 0x58, 0xfb, 0x3b, 0x07, 0x05, 0x1d, 0x45, 0x3e, 0x85, 0xbc, 0xa7, 0x22, 0x31, - 0xa2, 0xb4, 0x7b, 0xbf, 0x91, 0x54, 0x9a, 0x4a, 0x4b, 0xb5, 0x0f, 0xa9, 0x82, 0xf9, 0x26, 0x14, - 0x32, 0xf0, 0xc6, 0x0c, 0xd3, 0x15, 0x69, 0xa2, 0x93, 0x3d, 0x30, 0x27, 0x21, 0x97, 0xee, 0xd8, - 0x9b, 0x38, 0xb9, 0xad, 0x6c, 0xbd, 0xb4, 0xfb, 0x60, 0x39, 0x57, 0xa3, 0x1b, 0x72, 0x79, 0xec, - 0x4d, 0xda, 0x81, 0xe4, 0x33, 0xba, 0x36, 0xd1, 0x9a, 0xca, 0x7a, 0xc9, 0x66, 0x62, 0xe2, 0x0d, - 0x98, 0x93, 0xd7, 0x59, 0x63, 0x1d, 0x61, 0x78, 0xe3, 0xf1, 0xa1, 0x53, 0xc0, 0x03, 0xad, 0x90, - 0x1d, 0x28, 0x5e, 0xb2, 0x99, 0xcb, 0x15, 0x52, 0xce, 0x1a, 0x16, 0x4e, 0xe6, 0x1f, 0x8b, 0x31, - 0xc4, 0x34, 0x1a, 0xcd, 0x3a, 0xe4, 0xe4, 0x6c, 0xc2, 0x1c, 0x73, 0xcb, 0xa8, 0x57, 0x76, 0x37, - 0x96, 0x0b, 0xeb, 0xcf, 0x26, 0x8c, 0xa2, 0x07, 0xa9, 0x83, 0x3d, 0x3c, 0x73, 0x55, 0x47, 0x6e, - 0x38, 0x65, 0x9c, 0xfb, 0x43, 0xe6, 0x14, 0xf1, 0xdb, 0x95, 0xe1, 0x59, 0xc7, 0x1b, 0xb3, 0x93, - 0xc8, 0x4a, 0x1a, 0x90, 0x93, 0xde, 0x85, 0x70, 0x00, 0x9b, 0xad, 0xae, 0x34, 0xdb, 0xf7, 0x2e, - 0x84, 0xee, 0x14, 0xfd, 0xc8, 0x43, 0xa8, 0x8c, 0x67, 0xe2, 0xed, 0xc8, 0x4d, 0x20, 0xb4, 0x30, - 0x6f, 0x19, 0xad, 0x2f, 0x63, 0x1c, 0x1f, 0x00, 0x68, 0x37, 0x05, 0x8f, 0x53, 0xde, 0x32, 0xea, - 0x79, 0x5a, 0x44, 0x8b, 0x42, 0x8f, 0x34, 0x61, 0x73, 0xec, 0x09, 0xc9, 0xb8, 0x2b, 0x19, 0x1f, - 0xbb, 0x48, 0x0b, 0x57, 0x71, 0xc8, 0xa9, 0x20, 0x0e, 0x56, 0x63, 0x2a, 0x91, 0x52, 0x7d, 0x7f, - 0xcc, 0xe8, 0x3d, 0xed, 0xdb, 0x67, 0x7c, 0xdc, 0x53, 0x9e, 0xca, 0x58, 0x7d, 0x0a, 0x56, 0xfa, - 0x22, 0x14, 0x3f, 0x2e, 0xd9, 0x2c, 0xa2, 0x8c, 0x12, 0x15, 0xea, 0x53, 0x6f, 0x74, 0xa5, 0x2f, - 0x39, 0x4f, 0xb5, 0xf2, 0x34, 0xb3, 0x67, 0x54, 0xbf, 0x82, 0x62, 0xd2, 0xd7, 0xbf, 0x05, 0x16, - 0x53, 0x81, 0xaf, 0x72, 0x66, 0xd6, 0xce, 0xbd, 0xca, 0x99, 0x25, 0xdb, 0xaa, 0xfd, 0x5e, 0x80, - 0x7c, 0x0f, 0x2f, 0x72, 0x0f, 0xac, 0xa8, 0x9b, 0x1b, 0x90, 0xb0, 0xa4, 0x5d, 0x35, 0xd1, 0xaf, - 0xc7, 0xc1, 0xbc, 0x21, 0x0e, 0x8b, 0x2c, 0xca, 0xdc, 0x80, 0x45, 0xdf, 0x80, 0x25, 0x18, 0x9f, - 0xb2, 0xa1, 0xab, 0xa8, 0x22, 0x9c, 0xec, 0xf2, 0xcd, 0x63, 0x53, 0x8d, 0x1e, 0xfa, 0x20, 0xa7, - 0x4a, 0x22, 0x91, 0x05, 0x79, 0x06, 0x65, 0x11, 0x5e, 0xf1, 0x01, 0x73, 0x91, 0xc5, 0x22, 0x1a, - 0x93, 0xff, 0xad, 0xc4, 0xa3, 0x13, 0xca, 0xd4, 0x12, 0x73, 0x45, 0x90, 0x17, 0xb0, 0x2e, 0x11, - 0x10, 0x77, 0x10, 0x06, 0x92, 0x87, 0x23, 0xe1, 0x14, 0x96, 0x47, 0x4d, 0xe7, 0xd0, 0xb8, 0xb5, - 0xb4, 0x17, 0xad, 0xc8, 0xb4, 0x2a, 0xc8, 0x36, 0xdc, 0xf5, 0x85, 0x1b, 0xe1, 0xa7, 0x4a, 0xf4, - 0x83, 0x0b, 0x9c, 0x23, 0x93, 0xae, 0xfb, 0xe2, 0x18, 0xed, 0x3d, 0x6d, 0xae, 0xbe, 0x06, 0x98, - 0x37, 0x44, 0x9e, 0x40, 0x29, 0xaa, 0x00, 0xe7, 0xc9, 0x78, 0xcf, 0x3c, 0x81, 0x4c, 0x64, 0xc5, - 0x0b, 0xb5, 0x8a, 0x84, 0x93, 0xd9, 0xca, 0x2a, 0x5e, 0xa0, 0x52, 0xfd, 0xd5, 0x80, 0x52, 0xaa, - 0xd9, 0x78, 0x51, 0x19, 0xc9, 0xa2, 0x5a, 0x58, 0x0d, 0x99, 0xeb, 0x56, 0x43, 0xf6, 0xda, 0xd5, - 0x90, 0xbb, 0xc1, 0xa5, 0x6e, 0x42, 0x01, 0x0b, 0x15, 0x4e, 0x1e, 0x6b, 0x8b, 0xb4, 0xea, 0x6f, - 0x06, 0x94, 0x17, 0x50, 0xbc, 0xd5, 0xde, 0xc9, 0x67, 0x40, 0xce, 0x46, 0xde, 0xe0, 0x72, 0xe4, - 0x0b, 0xa9, 0x08, 0xa5, 0x4b, 0xc8, 0xa1, 0xcb, 0xdd, 0xd4, 0x09, 0x26, 0x15, 0xaa, 0xca, 0x73, - 0x1e, 0xfe, 0xc8, 0x02, 0xdc, 0x90, 0x26, 0x8d, 0xb4, 0x64, 0xac, 0xf2, 0x76, 0xa1, 0xf6, 0x47, - 0x16, 0xdf, 0x0f, 0x8d, 0xce, 0xe7, 0xb0, 0x81, 0x80, 0xf8, 0xc1, 0x85, 0x3b, 0x08, 0x47, 0x57, - 0xe3, 0x00, 0x97, 0x5a, 0x34, 0xac, 0x24, 0x3e, 0x6b, 0xe1, 0x91, 0xda, 0x6b, 0xe4, 0xd5, 0x6a, - 0x04, 0xf6, 0x99, 0xc1, 0x3e, 0x9d, 0x05, 0x10, 0xf1, 0x1b, 0x07, 0x9a, 0xe3, 0x4b, 0xb9, 0xb0, - 0xe7, 0x67, 0xc9, 0xa4, 0x9c, 0xf3, 0x70, 0x2c, 0x56, 0x1f, 0x84, 0x38, 0x47, 0x34, 0x2c, 0x2f, - 0x78, 0x38, 0x8e, 0x87, 0x45, 0xc9, 0x82, 0x7c, 0x0d, 0xe5, 0xf8, 0xa6, 0x75, 0x19, 0x79, 0x2c, - 0x63, 0x73, 0x35, 0x05, 0x16, 0x61, 0x5d, 0xa6, 0x34, 0xf2, 0x31, 0x94, 0xcf, 0x3c, 0xc1, 0xdc, - 0x84, 0x3b, 0xfa, 0xf5, 0xb0, 0x94, 0x31, 0x41, 0xe8, 0x0b, 0x28, 0x8b, 0xc0, 0x9b, 0x88, 0x37, - 0x61, 0xb4, 0x38, 0xd6, 0xde, 0xb1, 0x38, 0xac, 0xd8, 0x05, 0x37, 0xe7, 0x55, 0x3c, 0x0b, 0xaa, - 0xc6, 0xdb, 0xe5, 0x43, 0x9a, 0xe9, 0xd9, 0x45, 0xa6, 0xeb, 0x4b, 0xae, 0xfd, 0x64, 0x80, 0xad, - 0x97, 0x02, 0x9b, 0x8c, 0xfc, 0x81, 0x27, 0xfd, 0x30, 0x20, 0x4f, 0x20, 0x1f, 0x84, 0x43, 0xa6, - 0x36, 0xa7, 0x42, 0xf8, 0xa3, 0xa5, 0x3d, 0x90, 0x72, 0x6d, 0x74, 0xc2, 0x21, 0xa3, 0xda, 0xbb, - 0xfa, 0x0c, 0x72, 0x4a, 0x55, 0xfb, 0x37, 0x6a, 0xe1, 0x26, 0xfb, 0x57, 0xce, 0x95, 0xda, 0x29, - 0x54, 0xa2, 0x2f, 0x9c, 0x33, 0xce, 0x82, 0x01, 0x53, 0x3f, 0x3d, 0x52, 0x0c, 0x43, 0xf9, 0x83, - 0x57, 0x6c, 0xed, 0x67, 0x03, 0x08, 0xe6, 0x5d, 0x1c, 0xbd, 0xdb, 0xc8, 0x4d, 0x1e, 0xc3, 0xe6, - 0xdb, 0x2b, 0xc6, 0x67, 0x7a, 0xe3, 0x0d, 0x98, 0x3b, 0xf4, 0x85, 0xfa, 0x8a, 0xde, 0x20, 0x26, - 0xdd, 0xc0, 0xd3, 0x9e, 0x3e, 0xdc, 0x8f, 0xce, 0x6a, 0x7f, 0xe5, 0xa0, 0xd4, 0xe3, 0xd3, 0x84, - 0x36, 0xdf, 0x02, 0x4c, 0x3c, 0x2e, 0x7d, 0x85, 0x69, 0x0c, 0xfb, 0x27, 0x29, 0xd8, 0xe7, 0xae, - 0x09, 0x43, 0xbb, 0xb1, 0x3f, 0x4d, 0x85, 0x5e, 0x3b, 0xa1, 0x99, 0x0f, 0x9e, 0xd0, 0xec, 0x7f, - 0x98, 0xd0, 0x26, 0x94, 0x52, 0x13, 0x1a, 0x0d, 0xe8, 0xd6, 0xbb, 0xfb, 0x48, 0xcd, 0x28, 0xcc, - 0x67, 0xb4, 0xfa, 0xa7, 0x01, 0x77, 0x57, 0x5a, 0x54, 0x53, 0x91, 0x7a, 0x24, 0xdf, 0x3f, 0x15, - 0xf3, 0xd7, 0x91, 0xb4, 0xc0, 0xc6, 0x2a, 0x5d, 0x1e, 0x13, 0x4a, 0x0f, 0x48, 0x29, 0xdd, 0xd7, - 0x22, 0xe3, 0xe8, 0xba, 0x58, 0xd0, 0x05, 0xe9, 0xc2, 0x7d, 0x9d, 0x64, 0xf9, 0x95, 0xd4, 0x2f, - 0xf5, 0xff, 0x97, 0x32, 0x2d, 0x3e, 0x92, 0xf7, 0xc4, 0x8a, 0x4d, 0x54, 0xdd, 0xdb, 0x98, 0xf8, - 0xf7, 0xbc, 0x62, 0xd1, 0xea, 0x3e, 0x04, 0xb3, 0xc5, 0x46, 0xa3, 0x83, 0xe0, 0x3c, 0x54, 0xbf, - 0x13, 0x11, 0x17, 0xee, 0x7a, 0xc3, 0x21, 0x67, 0x42, 0x44, 0xac, 0x2f, 0x6b, 0x6b, 0x53, 0x1b, - 0xd5, 0x48, 0xf0, 0x30, 0x94, 0x51, 0x42, 0x94, 0xa3, 0x45, 0x51, 0x03, 0x50, 0xc9, 0x84, 0xfe, - 0xa1, 0xf4, 0xce, 0x75, 0xb3, 0x5d, 0x07, 0x2b, 0xbd, 0x3f, 0x09, 0x40, 0xa1, 0x73, 0x42, 0x8f, - 0x9b, 0x47, 0xf6, 0x1d, 0x62, 0x81, 0xd9, 0xeb, 0x34, 0xbb, 0xbd, 0x97, 0x27, 0x7d, 0xdb, 0xd8, - 0xde, 0x85, 0xca, 0x22, 0x9d, 0x48, 0x11, 0xf2, 0xa7, 0x9d, 0x5e, 0xbb, 0x6f, 0xdf, 0x51, 0x61, - 0xa7, 0x07, 0x9d, 0xfe, 0x97, 0x8f, 0x6d, 0x43, 0x99, 0x9f, 0xbf, 0xee, 0xb7, 0x7b, 0x76, 0x66, - 0xfb, 0x17, 0x03, 0x60, 0x8e, 0x05, 0x29, 0xc1, 0xda, 0x69, 0xe7, 0xb0, 0x73, 0xf2, 0x5d, 0x47, - 0x87, 0x1c, 0x37, 0x7b, 0xfd, 0x36, 0xb5, 0x0d, 0x75, 0x40, 0xdb, 0xdd, 0xa3, 0x83, 0x56, 0xd3, - 0xce, 0xa8, 0x03, 0xba, 0x7f, 0xd2, 0x39, 0x7a, 0x6d, 0x67, 0x31, 0x57, 0xb3, 0xdf, 0x7a, 0xa9, - 0xc5, 0x5e, 0xb7, 0x49, 0xdb, 0x76, 0x8e, 0xd8, 0x60, 0xb5, 0xbf, 0xef, 0xb6, 0xe9, 0xc1, 0x71, - 0xbb, 0xd3, 0x6f, 0x1e, 0xd9, 0x79, 0x15, 0xf3, 0xbc, 0xd9, 0x3a, 0x3c, 0xed, 0xda, 0x05, 0x9d, - 0xac, 0xd7, 0x3f, 0xa1, 0x6d, 0x7b, 0x4d, 0x29, 0xfb, 0xb4, 0x79, 0xd0, 0x69, 0xef, 0xdb, 0x66, - 0x35, 0x63, 0x1b, 0xcf, 0xf7, 0x60, 0xdd, 0x0f, 0x1b, 0x53, 0x5f, 0x32, 0x21, 0xf4, 0xdf, 0xad, - 0x1f, 0x1e, 0x46, 0x9a, 0x1f, 0xee, 0x68, 0x69, 0xe7, 0x22, 0xdc, 0x99, 0xca, 0x1d, 0x3c, 0xdd, - 0x89, 0x2f, 0xf5, 0xac, 0x80, 0xfa, 0xa3, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xe2, 0xab, 0xbe, - 0xeb, 0xc4, 0x0d, 0x00, 0x00, + 0xaa, 0x35, 0x95, 0xd2, 0x1f, 0x33, 0x6d, 0xaf, 0xed, 0x82, 0x79, 0xc8, 0x66, 0xd4, 0x0b, 0x2e, + 0x18, 0xd9, 0x80, 0xbc, 0x90, 0x1e, 0x97, 0x8e, 0xb1, 0x65, 0xd4, 0x2d, 0xaa, 0x15, 0x62, 0x43, + 0x96, 0x05, 0x43, 0x27, 0x83, 0x36, 0x25, 0xd6, 0x1e, 0x41, 0xa9, 0xef, 0x9d, 0x8d, 0x98, 0x6c, + 0x8e, 0x7c, 0x4f, 0x10, 0x02, 0xb9, 0x01, 0x1b, 0x8d, 0x30, 0xaa, 0x48, 0x51, 0x56, 0x41, 0x57, + 0xbe, 0x0e, 0x2a, 0x53, 0x25, 0xd6, 0xfe, 0xce, 0x41, 0x41, 0x47, 0x91, 0x4f, 0x21, 0xef, 0xa9, + 0x48, 0x8c, 0x28, 0xed, 0xde, 0x6f, 0x24, 0xb5, 0xa6, 0xd2, 0x52, 0xed, 0x43, 0xaa, 0x60, 0xbe, + 0x09, 0x85, 0x0c, 0xbc, 0x31, 0xc3, 0x74, 0x45, 0x9a, 0xe8, 0x64, 0x0f, 0xcc, 0x49, 0xc8, 0xa5, + 0x3b, 0xf6, 0x26, 0x4e, 0x6e, 0x2b, 0x5b, 0x2f, 0xed, 0x3e, 0x58, 0xce, 0xd5, 0xe8, 0x86, 0x5c, + 0x1e, 0x7b, 0x93, 0x76, 0x20, 0xf9, 0x8c, 0xae, 0x4d, 0xb4, 0xa6, 0xb2, 0x5e, 0xb2, 0x99, 0x98, + 0x78, 0x03, 0xe6, 0xe4, 0x75, 0xd6, 0x58, 0x47, 0x18, 0xde, 0x78, 0x7c, 0xe8, 0x14, 0xf0, 0x40, + 0x2b, 0x64, 0x07, 0x8a, 0x97, 0x6c, 0xe6, 0x72, 0x85, 0x94, 0xb3, 0x86, 0x85, 0x93, 0xf9, 0xc7, + 0x62, 0x0c, 0x31, 0x8d, 0x46, 0xb3, 0x0e, 0x39, 0x39, 0x9b, 0x30, 0xc7, 0xdc, 0x32, 0xea, 0x95, + 0xdd, 0x8d, 0xe5, 0xc2, 0xfa, 0xb3, 0x09, 0xa3, 0xe8, 0x41, 0xea, 0x60, 0x0f, 0xcf, 0x5c, 0xd5, + 0x91, 0x1b, 0x4e, 0x19, 0xe7, 0xfe, 0x90, 0x39, 0x45, 0xfc, 0x76, 0x65, 0x78, 0xd6, 0xf1, 0xc6, + 0xec, 0x24, 0xb2, 0x92, 0x06, 0xe4, 0xa4, 0x77, 0x21, 0x1c, 0xc0, 0x66, 0xab, 0x2b, 0xcd, 0xf6, + 0xbd, 0x0b, 0xa1, 0x3b, 0x45, 0x3f, 0xf2, 0x10, 0x2a, 0xe3, 0x99, 0x78, 0x3b, 0x72, 0x13, 0x08, + 0x2d, 0xcc, 0x5b, 0x46, 0xeb, 0xcb, 0x18, 0xc7, 0x07, 0x00, 0xda, 0x4d, 0xc1, 0xe3, 0x94, 0xb7, + 0x8c, 0x7a, 0x9e, 0x16, 0xd1, 0xa2, 0xd0, 0x23, 0x4d, 0xd8, 0x1c, 0x7b, 0x42, 0x32, 0xee, 0x4a, + 0xc6, 0xc7, 0x2e, 0xd2, 0xc2, 0x55, 0x1c, 0x72, 0x2a, 0x88, 0x83, 0xd5, 0x88, 0x28, 0xd5, 0xf7, + 0xc7, 0x8c, 0xde, 0xd3, 0xbe, 0x7d, 0xc6, 0xc7, 0x3d, 0xe5, 0xa9, 0x8c, 0xd5, 0xa7, 0x60, 0xa5, + 0x2f, 0x42, 0xf1, 0xe3, 0x92, 0xcd, 0x22, 0xca, 0x28, 0x51, 0xa1, 0x3e, 0xf5, 0x46, 0x57, 0xfa, + 0x92, 0xf3, 0x54, 0x2b, 0x4f, 0x33, 0x7b, 0x46, 0xf5, 0x2b, 0x28, 0x26, 0x7d, 0xfd, 0x5b, 0x60, + 0x31, 0x15, 0xf8, 0x2a, 0x67, 0x66, 0xed, 0xdc, 0xab, 0x9c, 0x59, 0xb2, 0xad, 0xda, 0xef, 0x05, + 0xc8, 0xf7, 0xf0, 0x22, 0xf7, 0xc0, 0x8a, 0xba, 0xb9, 0x01, 0x09, 0x4b, 0xda, 0x55, 0x13, 0xfd, + 0x7a, 0x1c, 0xcc, 0x1b, 0xe2, 0xb0, 0xc8, 0xa2, 0xcc, 0x0d, 0x58, 0xf4, 0x0d, 0x58, 0x82, 0xf1, + 0x29, 0x1b, 0xba, 0x8a, 0x2a, 0xc2, 0xc9, 0x2e, 0xdf, 0x3c, 0x36, 0xd5, 0xe8, 0xa1, 0x0f, 0x72, + 0xaa, 0x24, 0x12, 0x59, 0x90, 0x67, 0x50, 0x16, 0xe1, 0x15, 0x1f, 0x30, 0x17, 0x59, 0x2c, 0xa2, + 0x31, 0xf9, 0xdf, 0x4a, 0x3c, 0x3a, 0xa1, 0x4c, 0x2d, 0x31, 0x57, 0x04, 0x79, 0x01, 0xeb, 0x12, + 0x01, 0x71, 0x07, 0x61, 0x20, 0x79, 0x38, 0x12, 0x4e, 0x61, 0x79, 0xd4, 0x74, 0x0e, 0x8d, 0x5b, + 0x4b, 0x7b, 0xd1, 0x8a, 0x4c, 0xab, 0x82, 0x6c, 0xc3, 0x5d, 0x5f, 0xb8, 0x11, 0x7e, 0xaa, 0x44, + 0x3f, 0xb8, 0xc0, 0x39, 0x32, 0xe9, 0xba, 0x2f, 0x8e, 0xd1, 0xde, 0xd3, 0xe6, 0xea, 0x6b, 0x80, + 0x79, 0x43, 0xe4, 0x09, 0x94, 0xa2, 0x0a, 0x70, 0x9e, 0x8c, 0xf7, 0xcc, 0x13, 0xc8, 0x44, 0x56, + 0xbc, 0x50, 0xab, 0x48, 0x38, 0x99, 0xad, 0xac, 0xe2, 0x05, 0x2a, 0xd5, 0x5f, 0x0d, 0x28, 0xa5, + 0x9a, 0x8d, 0x17, 0x95, 0x91, 0x2c, 0xaa, 0x85, 0xd5, 0x90, 0xb9, 0x6e, 0x35, 0x64, 0xaf, 0x5d, + 0x0d, 0xb9, 0x1b, 0x5c, 0xea, 0x26, 0x14, 0xb0, 0x50, 0xe1, 0xe4, 0xb1, 0xb6, 0x48, 0xab, 0xfe, + 0x66, 0x40, 0x79, 0x01, 0xc5, 0x5b, 0xed, 0x9d, 0x7c, 0x06, 0xe4, 0x6c, 0xe4, 0x0d, 0x2e, 0x47, + 0xbe, 0x90, 0x8a, 0x50, 0xba, 0x84, 0x1c, 0xba, 0xdc, 0x4d, 0x9d, 0x60, 0x52, 0xa1, 0xaa, 0x3c, + 0xe7, 0xe1, 0x8f, 0x2c, 0xc0, 0x0d, 0x69, 0xd2, 0x48, 0x4b, 0xc6, 0x2a, 0x6f, 0x17, 0x6a, 0x7f, + 0x64, 0xf1, 0xfd, 0xd0, 0xe8, 0x7c, 0x0e, 0x1b, 0x08, 0x88, 0x1f, 0x5c, 0xb8, 0x83, 0x70, 0x74, + 0x35, 0x0e, 0x70, 0xa9, 0x45, 0xc3, 0x4a, 0xe2, 0xb3, 0x16, 0x1e, 0xa9, 0xbd, 0x46, 0x5e, 0xad, + 0x46, 0x60, 0x9f, 0x19, 0xec, 0xd3, 0x59, 0x00, 0x11, 0xbf, 0x71, 0xa0, 0x39, 0xbe, 0x94, 0x0b, + 0x7b, 0x7e, 0x96, 0x4c, 0xca, 0x39, 0x0f, 0xc7, 0x62, 0xf5, 0x41, 0x88, 0x73, 0x44, 0xc3, 0xf2, + 0x82, 0x87, 0xe3, 0x78, 0x58, 0x94, 0x2c, 0xc8, 0xd7, 0x50, 0x8e, 0x6f, 0x5a, 0x97, 0x91, 0xc7, + 0x32, 0x36, 0x57, 0x53, 0x60, 0x11, 0xd6, 0x65, 0x4a, 0x23, 0x1f, 0x43, 0xf9, 0xcc, 0x13, 0xcc, + 0x4d, 0xb8, 0xa3, 0x5f, 0x0f, 0x4b, 0x19, 0x13, 0x84, 0xbe, 0x80, 0xb2, 0x08, 0xbc, 0x89, 0x78, + 0x13, 0x46, 0x8b, 0x63, 0xed, 0x1d, 0x8b, 0xc3, 0x8a, 0x5d, 0x70, 0x73, 0x5e, 0xc5, 0xb3, 0xa0, + 0x6a, 0xbc, 0x5d, 0x3e, 0xa4, 0x99, 0x9e, 0x5d, 0x64, 0xba, 0xbe, 0xe4, 0xda, 0x4f, 0x06, 0xd8, + 0x7a, 0x29, 0xb0, 0xc9, 0xc8, 0x1f, 0x78, 0xd2, 0x0f, 0x03, 0xf2, 0x04, 0xf2, 0x41, 0x38, 0x64, + 0x6a, 0x73, 0x2a, 0x84, 0x3f, 0x5a, 0xda, 0x03, 0x29, 0xd7, 0x46, 0x27, 0x1c, 0x32, 0xaa, 0xbd, + 0xab, 0xcf, 0x20, 0xa7, 0x54, 0xb5, 0x7f, 0xa3, 0x16, 0x6e, 0xb2, 0x7f, 0xe5, 0x5c, 0xa9, 0x9d, + 0x42, 0x25, 0xfa, 0xc2, 0x39, 0xe3, 0x2c, 0x18, 0x30, 0xf5, 0xd3, 0x23, 0xc5, 0x30, 0x94, 0x3f, + 0x78, 0xc5, 0xd6, 0x7e, 0x36, 0x80, 0x60, 0xde, 0xc5, 0xd1, 0xbb, 0x8d, 0xdc, 0xe4, 0x31, 0x6c, + 0xbe, 0xbd, 0x62, 0x7c, 0xa6, 0x37, 0xde, 0x80, 0xb9, 0x43, 0x5f, 0xa8, 0xaf, 0xe8, 0x0d, 0x62, + 0xd2, 0x0d, 0x3c, 0xed, 0xe9, 0xc3, 0xfd, 0xe8, 0xac, 0xf6, 0x57, 0x0e, 0x4a, 0x3d, 0x3e, 0x4d, + 0x68, 0xf3, 0x2d, 0xc0, 0xc4, 0xe3, 0xd2, 0x57, 0x98, 0xc6, 0xb0, 0x7f, 0x92, 0x82, 0x7d, 0xee, + 0x9a, 0x30, 0xb4, 0x1b, 0xfb, 0xd3, 0x54, 0xe8, 0xb5, 0x13, 0x9a, 0xf9, 0xe0, 0x09, 0xcd, 0xfe, + 0x87, 0x09, 0x6d, 0x42, 0x29, 0x35, 0xa1, 0xd1, 0x80, 0x6e, 0xbd, 0xbb, 0x8f, 0xd4, 0x8c, 0xc2, + 0x7c, 0x46, 0xab, 0x7f, 0x1a, 0x70, 0x77, 0xa5, 0x45, 0x35, 0x15, 0xa9, 0x47, 0xf2, 0xfd, 0x53, + 0x31, 0x7f, 0x1d, 0x49, 0x0b, 0x6c, 0xac, 0xd2, 0xe5, 0x31, 0xa1, 0xf4, 0x80, 0x94, 0xd2, 0x7d, + 0x2d, 0x32, 0x8e, 0xae, 0x8b, 0x05, 0x5d, 0x90, 0x2e, 0xdc, 0xd7, 0x49, 0x96, 0x5f, 0x49, 0xfd, + 0x52, 0xff, 0x7f, 0x29, 0xd3, 0xe2, 0x23, 0x79, 0x4f, 0xac, 0xd8, 0x44, 0xd5, 0xbd, 0x8d, 0x89, + 0x7f, 0xcf, 0x2b, 0x16, 0xad, 0xee, 0x43, 0x30, 0x5b, 0x6c, 0x34, 0x3a, 0x08, 0xce, 0x43, 0xf5, + 0x3b, 0x11, 0x71, 0xe1, 0xae, 0x37, 0x1c, 0x72, 0x26, 0x44, 0xc4, 0xfa, 0xb2, 0xb6, 0x36, 0xb5, + 0x51, 0x8d, 0x04, 0x0f, 0x43, 0x19, 0x25, 0x44, 0x39, 0x5a, 0x14, 0x35, 0x00, 0x95, 0x4c, 0xe8, + 0x1f, 0x4a, 0xef, 0x5c, 0x37, 0xdb, 0x75, 0xb0, 0xd2, 0xfb, 0x93, 0x00, 0x14, 0x3a, 0x27, 0xf4, + 0xb8, 0x79, 0x64, 0xdf, 0x21, 0x16, 0x98, 0xbd, 0x4e, 0xb3, 0xdb, 0x7b, 0x79, 0xd2, 0xb7, 0x8d, + 0xed, 0x5d, 0xa8, 0x2c, 0xd2, 0x89, 0x14, 0x21, 0x7f, 0xda, 0xe9, 0xb5, 0xfb, 0xf6, 0x1d, 0x15, + 0x76, 0x7a, 0xd0, 0xe9, 0x7f, 0xf9, 0xd8, 0x36, 0x94, 0xf9, 0xf9, 0xeb, 0x7e, 0xbb, 0x67, 0x67, + 0xb6, 0x7f, 0x31, 0x00, 0xe6, 0x58, 0x90, 0x12, 0xac, 0x9d, 0x76, 0x0e, 0x3b, 0x27, 0xdf, 0x75, + 0x74, 0xc8, 0x71, 0xb3, 0xd7, 0x6f, 0x53, 0xdb, 0x50, 0x07, 0xb4, 0xdd, 0x3d, 0x3a, 0x68, 0x35, + 0xed, 0x8c, 0x3a, 0xa0, 0xfb, 0x27, 0x9d, 0xa3, 0xd7, 0x76, 0x16, 0x73, 0x35, 0xfb, 0xad, 0x97, + 0x5a, 0xec, 0x75, 0x9b, 0xb4, 0x6d, 0xe7, 0x88, 0x0d, 0x56, 0xfb, 0xfb, 0x6e, 0x9b, 0x1e, 0x1c, + 0xb7, 0x3b, 0xfd, 0xe6, 0x91, 0x9d, 0x57, 0x31, 0xcf, 0x9b, 0xad, 0xc3, 0xd3, 0xae, 0x5d, 0xd0, + 0xc9, 0x7a, 0xfd, 0x13, 0xda, 0xb6, 0xd7, 0x94, 0xb2, 0x4f, 0x9b, 0x07, 0x9d, 0xf6, 0xbe, 0x6d, + 0x56, 0x33, 0xb6, 0xf1, 0x7c, 0x0f, 0xd6, 0xfd, 0xb0, 0x31, 0xf5, 0x25, 0x13, 0x42, 0xff, 0xdd, + 0xfa, 0xe1, 0x61, 0xa4, 0xf9, 0xe1, 0x8e, 0x96, 0x76, 0x2e, 0xc2, 0x9d, 0xa9, 0xdc, 0xc1, 0xd3, + 0x9d, 0xf8, 0x52, 0xcf, 0x0a, 0xa8, 0x3f, 0xfa, 0x27, 0x00, 0x00, 0xff, 0xff, 0x51, 0xac, 0x2b, + 0xc1, 0xc6, 0x0d, 0x00, 0x00, } diff --git a/go/vt/proto/vtctldata/vtctldata.pb.go b/go/vt/proto/vtctldata/vtctldata.pb.go index 0b7171a412a..8734dc87f02 100644 --- a/go/vt/proto/vtctldata/vtctldata.pb.go +++ b/go/vt/proto/vtctldata/vtctldata.pb.go @@ -111,26 +111,193 @@ func (m *ExecuteVtctlCommandResponse) GetEvent() *logutil.Event { return nil } +// TableMaterializeSttings contains the settings for one table. +type TableMaterializeSettings struct { + TargetTable string `protobuf:"bytes,1,opt,name=target_table,json=targetTable,proto3" json:"target_table,omitempty"` + // source_expression is a select statement. + SourceExpression string `protobuf:"bytes,2,opt,name=source_expression,json=sourceExpression,proto3" json:"source_expression,omitempty"` + // create_ddl contains the DDL to create the target table. + // If empty, the target table must already exist. + // if "copy", the target table DDL is the same as the source table. + CreateDdl string `protobuf:"bytes,3,opt,name=create_ddl,json=createDdl,proto3" json:"create_ddl,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *TableMaterializeSettings) Reset() { *m = TableMaterializeSettings{} } +func (m *TableMaterializeSettings) String() string { return proto.CompactTextString(m) } +func (*TableMaterializeSettings) ProtoMessage() {} +func (*TableMaterializeSettings) Descriptor() ([]byte, []int) { + return fileDescriptor_f41247b323a1ab2e, []int{2} +} + +func (m *TableMaterializeSettings) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_TableMaterializeSettings.Unmarshal(m, b) +} +func (m *TableMaterializeSettings) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_TableMaterializeSettings.Marshal(b, m, deterministic) +} +func (m *TableMaterializeSettings) XXX_Merge(src proto.Message) { + xxx_messageInfo_TableMaterializeSettings.Merge(m, src) +} +func (m *TableMaterializeSettings) XXX_Size() int { + return xxx_messageInfo_TableMaterializeSettings.Size(m) +} +func (m *TableMaterializeSettings) XXX_DiscardUnknown() { + xxx_messageInfo_TableMaterializeSettings.DiscardUnknown(m) +} + +var xxx_messageInfo_TableMaterializeSettings proto.InternalMessageInfo + +func (m *TableMaterializeSettings) GetTargetTable() string { + if m != nil { + return m.TargetTable + } + return "" +} + +func (m *TableMaterializeSettings) GetSourceExpression() string { + if m != nil { + return m.SourceExpression + } + return "" +} + +func (m *TableMaterializeSettings) GetCreateDdl() string { + if m != nil { + return m.CreateDdl + } + return "" +} + +// MaterializeSettings contains the settings for the Materialize command. +type MaterializeSettings struct { + // workflow is the name of the workflow. + Workflow string `protobuf:"bytes,1,opt,name=workflow,proto3" json:"workflow,omitempty"` + SourceKeyspace string `protobuf:"bytes,2,opt,name=source_keyspace,json=sourceKeyspace,proto3" json:"source_keyspace,omitempty"` + TargetKeyspace string `protobuf:"bytes,3,opt,name=target_keyspace,json=targetKeyspace,proto3" json:"target_keyspace,omitempty"` + // stop_after_copy specifies if vreplication should be stopped after copying. + StopAfterCopy bool `protobuf:"varint,4,opt,name=stop_after_copy,json=stopAfterCopy,proto3" json:"stop_after_copy,omitempty"` + TableSettings []*TableMaterializeSettings `protobuf:"bytes,5,rep,name=table_settings,json=tableSettings,proto3" json:"table_settings,omitempty"` + // optional parameters. + Cell string `protobuf:"bytes,6,opt,name=cell,proto3" json:"cell,omitempty"` + TabletTypes string `protobuf:"bytes,7,opt,name=tablet_types,json=tabletTypes,proto3" json:"tablet_types,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MaterializeSettings) Reset() { *m = MaterializeSettings{} } +func (m *MaterializeSettings) String() string { return proto.CompactTextString(m) } +func (*MaterializeSettings) ProtoMessage() {} +func (*MaterializeSettings) Descriptor() ([]byte, []int) { + return fileDescriptor_f41247b323a1ab2e, []int{3} +} + +func (m *MaterializeSettings) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MaterializeSettings.Unmarshal(m, b) +} +func (m *MaterializeSettings) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MaterializeSettings.Marshal(b, m, deterministic) +} +func (m *MaterializeSettings) XXX_Merge(src proto.Message) { + xxx_messageInfo_MaterializeSettings.Merge(m, src) +} +func (m *MaterializeSettings) XXX_Size() int { + return xxx_messageInfo_MaterializeSettings.Size(m) +} +func (m *MaterializeSettings) XXX_DiscardUnknown() { + xxx_messageInfo_MaterializeSettings.DiscardUnknown(m) +} + +var xxx_messageInfo_MaterializeSettings proto.InternalMessageInfo + +func (m *MaterializeSettings) GetWorkflow() string { + if m != nil { + return m.Workflow + } + return "" +} + +func (m *MaterializeSettings) GetSourceKeyspace() string { + if m != nil { + return m.SourceKeyspace + } + return "" +} + +func (m *MaterializeSettings) GetTargetKeyspace() string { + if m != nil { + return m.TargetKeyspace + } + return "" +} + +func (m *MaterializeSettings) GetStopAfterCopy() bool { + if m != nil { + return m.StopAfterCopy + } + return false +} + +func (m *MaterializeSettings) GetTableSettings() []*TableMaterializeSettings { + if m != nil { + return m.TableSettings + } + return nil +} + +func (m *MaterializeSettings) GetCell() string { + if m != nil { + return m.Cell + } + return "" +} + +func (m *MaterializeSettings) GetTabletTypes() string { + if m != nil { + return m.TabletTypes + } + return "" +} + func init() { proto.RegisterType((*ExecuteVtctlCommandRequest)(nil), "vtctldata.ExecuteVtctlCommandRequest") proto.RegisterType((*ExecuteVtctlCommandResponse)(nil), "vtctldata.ExecuteVtctlCommandResponse") + proto.RegisterType((*TableMaterializeSettings)(nil), "vtctldata.TableMaterializeSettings") + proto.RegisterType((*MaterializeSettings)(nil), "vtctldata.MaterializeSettings") } func init() { proto.RegisterFile("vtctldata.proto", fileDescriptor_f41247b323a1ab2e) } var fileDescriptor_f41247b323a1ab2e = []byte{ - // 200 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0xcf, 0xd1, 0x4a, 0x87, 0x30, - 0x14, 0x06, 0x70, 0xd6, 0xbf, 0x82, 0xff, 0x42, 0x83, 0x5d, 0x89, 0xdd, 0x88, 0x54, 0xec, 0xca, - 0x41, 0xbd, 0x41, 0xe2, 0x0b, 0x8c, 0x28, 0xe8, 0x26, 0x96, 0x1e, 0x64, 0xa0, 0x3b, 0xe6, 0xce, - 0x46, 0x8f, 0x1f, 0x3a, 0xf2, 0xaa, 0xbb, 0x8f, 0xdf, 0x37, 0xc6, 0x77, 0xf8, 0x6d, 0xa4, 0x9e, - 0xa6, 0xc1, 0x90, 0x69, 0x96, 0x15, 0x09, 0xc5, 0xf9, 0x80, 0x32, 0x9b, 0x70, 0x0c, 0x64, 0xa7, - 0xd4, 0xd4, 0xef, 0xbc, 0xec, 0x7e, 0xa0, 0x0f, 0x04, 0x6f, 0xdb, 0x93, 0x16, 0xe7, 0xd9, 0xb8, - 0x41, 0xc3, 0x77, 0x00, 0x4f, 0x42, 0xf0, 0x4b, 0xb3, 0x8e, 0xbe, 0x60, 0xd5, 0x49, 0x9e, 0xf5, - 0x9e, 0xc5, 0x03, 0xcf, 0x4d, 0x4f, 0x16, 0xdd, 0x27, 0xd9, 0x19, 0x30, 0x50, 0x71, 0x51, 0x31, - 0x79, 0xd2, 0x59, 0xd2, 0xd7, 0x84, 0x75, 0xcb, 0xef, 0xfe, 0xfd, 0xd8, 0x2f, 0xe8, 0x3c, 0x88, - 0x7b, 0x7e, 0x05, 0x11, 0x1c, 0x15, 0xac, 0x62, 0xf2, 0xe6, 0x29, 0x6f, 0xfe, 0x66, 0x75, 0x9b, - 0xea, 0x54, 0xbe, 0xc8, 0x8f, 0xc7, 0x68, 0x09, 0xbc, 0x6f, 0x2c, 0xaa, 0x94, 0xd4, 0x88, 0x2a, - 0x92, 0xda, 0xd7, 0xab, 0xe3, 0xac, 0xaf, 0xeb, 0x1d, 0x9e, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xd5, 0x57, 0x1c, 0xfb, 0x00, 0x00, 0x00, + // 422 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xd1, 0x6e, 0xd3, 0x30, + 0x14, 0x86, 0x95, 0xb5, 0x1b, 0xeb, 0x29, 0x4d, 0xc1, 0xdc, 0x58, 0x45, 0x48, 0xa1, 0xc0, 0x88, + 0x84, 0xd4, 0x48, 0xe3, 0x09, 0xa0, 0xf4, 0x06, 0xc4, 0x4d, 0xa8, 0x40, 0xe2, 0x26, 0x72, 0x93, + 0xb3, 0xc8, 0x9a, 0x1b, 0x07, 0xfb, 0xa4, 0x5b, 0x79, 0x03, 0x5e, 0x86, 0x67, 0x44, 0xb6, 0xb3, + 0x70, 0xb3, 0xdd, 0x1d, 0x7f, 0xe7, 0xb7, 0xfd, 0x9f, 0x5f, 0x07, 0xe6, 0x07, 0x2a, 0x49, 0x55, + 0x82, 0xc4, 0xaa, 0x35, 0x9a, 0x34, 0x9b, 0x0c, 0x60, 0x31, 0x53, 0xba, 0xee, 0x48, 0xaa, 0xd0, + 0x59, 0xfe, 0x80, 0xc5, 0xe6, 0x16, 0xcb, 0x8e, 0xf0, 0xbb, 0x93, 0xac, 0xf5, 0x7e, 0x2f, 0x9a, + 0x2a, 0xc7, 0x5f, 0x1d, 0x5a, 0x62, 0x0c, 0xc6, 0xc2, 0xd4, 0x96, 0x47, 0xc9, 0x28, 0x9d, 0xe4, + 0xbe, 0x66, 0x6f, 0x20, 0x16, 0x25, 0x49, 0xdd, 0x14, 0x24, 0xf7, 0xa8, 0x3b, 0xe2, 0x27, 0x49, + 0x94, 0x8e, 0xf2, 0x59, 0xa0, 0xdb, 0x00, 0x97, 0x6b, 0x78, 0x7e, 0xef, 0xc3, 0xb6, 0xd5, 0x8d, + 0x45, 0xf6, 0x1a, 0x4e, 0xf1, 0x80, 0x0d, 0xf1, 0x28, 0x89, 0xd2, 0xe9, 0x65, 0xbc, 0xba, 0xb3, + 0xb5, 0x71, 0x34, 0x0f, 0xcd, 0xe5, 0x9f, 0x08, 0xf8, 0x56, 0xec, 0x14, 0x7e, 0x15, 0x84, 0x46, + 0x0a, 0x25, 0x7f, 0xe3, 0x37, 0x24, 0x92, 0x4d, 0x6d, 0xd9, 0x4b, 0x78, 0x4c, 0xc2, 0xd4, 0x48, + 0x05, 0x39, 0x89, 0x7f, 0x69, 0x92, 0x4f, 0x03, 0xf3, 0xb7, 0xd8, 0x3b, 0x78, 0x6a, 0x75, 0x67, + 0x4a, 0x2c, 0xf0, 0xb6, 0x35, 0x68, 0xad, 0xd4, 0x8d, 0xb7, 0x3b, 0xc9, 0x9f, 0x84, 0xc6, 0x66, + 0xe0, 0xec, 0x05, 0x40, 0x69, 0x50, 0x10, 0x16, 0x55, 0xa5, 0xf8, 0xc8, 0xab, 0x26, 0x81, 0x7c, + 0xaa, 0xd4, 0xf2, 0xef, 0x09, 0x3c, 0xbb, 0xcf, 0xc6, 0x02, 0xce, 0x6f, 0xb4, 0xb9, 0xbe, 0x52, + 0xfa, 0xa6, 0xb7, 0x30, 0x9c, 0xd9, 0x5b, 0x98, 0xf7, 0xff, 0x5f, 0xe3, 0xd1, 0xb6, 0xa2, 0xc4, + 0xfe, 0xf7, 0x38, 0xe0, 0x2f, 0x3d, 0x75, 0xc2, 0x7e, 0x96, 0x41, 0x18, 0x0c, 0xc4, 0x01, 0x0f, + 0xc2, 0x0b, 0x98, 0x5b, 0xd2, 0x6d, 0x21, 0xae, 0x08, 0x4d, 0x51, 0xea, 0xf6, 0xc8, 0xc7, 0x49, + 0x94, 0x9e, 0xe7, 0x33, 0x87, 0x3f, 0x38, 0xba, 0xd6, 0xed, 0x91, 0x7d, 0x86, 0xd8, 0xa7, 0x52, + 0xd8, 0xde, 0x27, 0x3f, 0x4d, 0x46, 0xe9, 0xf4, 0xf2, 0xd5, 0xea, 0xff, 0x6e, 0x3c, 0x94, 0x6c, + 0x3e, 0xf3, 0x57, 0x87, 0x09, 0x19, 0x8c, 0x4b, 0x54, 0x8a, 0x9f, 0x79, 0x47, 0xbe, 0x0e, 0xe1, + 0xef, 0x94, 0x0b, 0xff, 0xd8, 0xa2, 0xe5, 0x8f, 0xee, 0xc2, 0x77, 0x6c, 0xeb, 0xd0, 0xc7, 0xf4, + 0xe7, 0xc5, 0x41, 0x12, 0x5a, 0xbb, 0x92, 0x3a, 0x0b, 0x55, 0x56, 0xeb, 0xec, 0x40, 0x99, 0x5f, + 0xbd, 0x6c, 0x30, 0xb2, 0x3b, 0xf3, 0xe0, 0xfd, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x46, 0x37, + 0xd0, 0x53, 0xb8, 0x02, 0x00, 0x00, } diff --git a/go/vt/proto/vtgate/vtgate.pb.go b/go/vt/proto/vtgate/vtgate.pb.go index 48186096d68..61ba91e777b 100644 --- a/go/vt/proto/vtgate/vtgate.pb.go +++ b/go/vt/proto/vtgate/vtgate.pb.go @@ -135,10 +135,14 @@ type Session struct { // pre_sessions contains sessions that have to be committed first. PreSessions []*Session_ShardSession `protobuf:"bytes,9,rep,name=pre_sessions,json=preSessions,proto3" json:"pre_sessions,omitempty"` // post_sessions contains sessions that have to be committed last. - PostSessions []*Session_ShardSession `protobuf:"bytes,10,rep,name=post_sessions,json=postSessions,proto3" json:"post_sessions,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + PostSessions []*Session_ShardSession `protobuf:"bytes,10,rep,name=post_sessions,json=postSessions,proto3" json:"post_sessions,omitempty"` + // last_insert_id keeps track of the last seen insert_id for this session + LastInsertId uint64 `protobuf:"varint,11,opt,name=last_insert_id,json=lastInsertId,proto3" json:"last_insert_id,omitempty"` + // found_rows keeps track of how many rows the last query returned + FoundRows uint64 `protobuf:"varint,11,opt,name=found_rows,json=foundRows,proto3" json:"found_rows,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *Session) Reset() { *m = Session{} } @@ -236,6 +240,13 @@ func (m *Session) GetPostSessions() []*Session_ShardSession { return nil } +func (m *Session) GetLastInsertId() uint64 { + if m != nil { + return m.LastInsertId + } + return 0 +} + type Session_ShardSession struct { Target *query.Target `protobuf:"bytes,1,opt,name=target,proto3" json:"target,omitempty"` TransactionId int64 `protobuf:"varint,2,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` @@ -3686,133 +3697,135 @@ func init() { func init() { proto.RegisterFile("vtgate.proto", fileDescriptor_aab96496ceaf1ebb) } var fileDescriptor_aab96496ceaf1ebb = []byte{ - // 2041 bytes of a gzipped FileDescriptorProto + // 2067 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x5a, 0xcd, 0x8f, 0x23, 0x47, - 0x15, 0x4f, 0x77, 0xfb, 0xf3, 0xf9, 0x73, 0x6b, 0xbc, 0x1b, 0xc7, 0x19, 0x76, 0x26, 0x1d, 0x46, - 0xeb, 0x6c, 0x56, 0x1e, 0xe2, 0x40, 0x40, 0x28, 0x28, 0xcc, 0x78, 0x27, 0x2b, 0x2b, 0x3b, 0x1f, - 0x94, 0xbd, 0xb3, 0x80, 0x88, 0x5a, 0x3d, 0x76, 0xe1, 0x6d, 0xc6, 0xee, 0x76, 0xba, 0xca, 0x5e, - 0x86, 0x03, 0xca, 0x7f, 0x10, 0x71, 0x40, 0x42, 0x11, 0x12, 0x42, 0x42, 0xe2, 0xc4, 0x15, 0x09, - 0xb8, 0x70, 0x43, 0xe2, 0x82, 0x38, 0x71, 0x44, 0xe2, 0x1f, 0x40, 0xe2, 0x2f, 0x40, 0x5d, 0x55, - 0xfd, 0xe1, 0x9e, 0x2f, 0x8f, 0x67, 0x67, 0xe5, 0xbd, 0x58, 0x5d, 0xf5, 0x5e, 0x55, 0xbd, 0xf7, - 0x7b, 0xbf, 0x7a, 0xf5, 0xba, 0xdc, 0x90, 0x9f, 0xb2, 0x81, 0xc9, 0x48, 0x63, 0xec, 0x3a, 0xcc, - 0x41, 0x29, 0xd1, 0xaa, 0x95, 0x8f, 0x2c, 0x7b, 0xe8, 0x0c, 0xfa, 0x26, 0x33, 0x85, 0xa4, 0x96, - 0xfb, 0x6c, 0x42, 0xdc, 0x13, 0xd9, 0x28, 0x32, 0x67, 0xec, 0x44, 0x85, 0x53, 0xe6, 0x8e, 0x7b, - 0xa2, 0xa1, 0xff, 0x3b, 0x01, 0xe9, 0x0e, 0xa1, 0xd4, 0x72, 0x6c, 0xb4, 0x01, 0x45, 0xcb, 0x36, - 0x98, 0x6b, 0xda, 0xd4, 0xec, 0x31, 0xcb, 0xb1, 0xab, 0xca, 0xba, 0x52, 0xcf, 0xe0, 0x82, 0x65, - 0x77, 0xc3, 0x4e, 0xd4, 0x82, 0x22, 0x7d, 0x66, 0xba, 0x7d, 0x83, 0x8a, 0x71, 0xb4, 0xaa, 0xae, - 0x6b, 0xf5, 0x5c, 0x73, 0xb5, 0x21, 0xad, 0x93, 0xf3, 0x35, 0x3a, 0x9e, 0x96, 0x6c, 0xe0, 0x02, - 0x8d, 0xb4, 0x28, 0x7a, 0x13, 0xb2, 0xd4, 0xb2, 0x07, 0x43, 0x62, 0xf4, 0x8f, 0xaa, 0x1a, 0x5f, - 0x26, 0x23, 0x3a, 0x1e, 0x1e, 0xa1, 0xbb, 0x00, 0xe6, 0x84, 0x39, 0x3d, 0x67, 0x34, 0xb2, 0x58, - 0x35, 0xc1, 0xa5, 0x91, 0x1e, 0xf4, 0x36, 0x14, 0x98, 0xe9, 0x0e, 0x08, 0x33, 0x28, 0x73, 0x2d, - 0x7b, 0x50, 0x4d, 0xae, 0x2b, 0xf5, 0x2c, 0xce, 0x8b, 0xce, 0x0e, 0xef, 0x43, 0x9b, 0x90, 0x76, - 0xc6, 0x8c, 0xdb, 0x97, 0x5a, 0x57, 0xea, 0xb9, 0xe6, 0xed, 0x86, 0x40, 0x65, 0xe7, 0xa7, 0xa4, - 0x37, 0x61, 0x64, 0x5f, 0x08, 0xb1, 0xaf, 0x85, 0xb6, 0xa1, 0x1c, 0xf1, 0xdd, 0x18, 0x39, 0x7d, - 0x52, 0x4d, 0xaf, 0x2b, 0xf5, 0x62, 0xf3, 0x75, 0xdf, 0xb3, 0x08, 0x0c, 0xbb, 0x4e, 0x9f, 0xe0, - 0x12, 0x9b, 0xed, 0x40, 0x9b, 0x90, 0x79, 0x6e, 0xba, 0xb6, 0x65, 0x0f, 0x68, 0x35, 0xc3, 0x51, - 0x59, 0x91, 0xab, 0x7e, 0xcf, 0xfb, 0x7d, 0x2a, 0x64, 0x38, 0x50, 0x42, 0x1f, 0x41, 0x7e, 0xec, - 0x92, 0x10, 0xca, 0xec, 0x1c, 0x50, 0xe6, 0xc6, 0x2e, 0x09, 0x80, 0xdc, 0x82, 0xc2, 0xd8, 0xa1, - 0x2c, 0x9c, 0x01, 0xe6, 0x98, 0x21, 0xef, 0x0d, 0xf1, 0xa7, 0xa8, 0xfd, 0x08, 0xf2, 0x51, 0x29, - 0xda, 0x80, 0x94, 0x40, 0x92, 0xc7, 0x3f, 0xd7, 0x2c, 0x48, 0x17, 0xba, 0xbc, 0x13, 0x4b, 0xa1, - 0x47, 0x97, 0x28, 0x5e, 0x56, 0xbf, 0xaa, 0xae, 0x2b, 0x75, 0x0d, 0x17, 0x22, 0xbd, 0xed, 0xbe, - 0xfe, 0x0f, 0x15, 0x8a, 0x12, 0x72, 0x4c, 0x3e, 0x9b, 0x10, 0xca, 0xd0, 0x03, 0xc8, 0xf6, 0xcc, - 0xe1, 0x90, 0xb8, 0xde, 0x20, 0xb1, 0x46, 0xa9, 0x21, 0x58, 0xd9, 0xe2, 0xfd, 0xed, 0x87, 0x38, - 0x23, 0x34, 0xda, 0x7d, 0xf4, 0x0e, 0xa4, 0xa5, 0x73, 0x7c, 0x01, 0xa1, 0x1b, 0xf5, 0x0d, 0xfb, - 0x72, 0x74, 0x0f, 0x92, 0xdc, 0x54, 0xce, 0xa8, 0x5c, 0xf3, 0x96, 0x34, 0x7c, 0xdb, 0x99, 0xd8, - 0x7d, 0x1e, 0x00, 0x2c, 0xe4, 0xe8, 0x1b, 0x90, 0x63, 0xe6, 0xd1, 0x90, 0x30, 0x83, 0x9d, 0x8c, - 0x09, 0xa7, 0x58, 0xb1, 0x59, 0x69, 0x04, 0x3b, 0xa5, 0xcb, 0x85, 0xdd, 0x93, 0x31, 0xc1, 0xc0, - 0x82, 0x67, 0xf4, 0x00, 0x90, 0xed, 0x30, 0x23, 0xb6, 0x4b, 0x92, 0x9c, 0xa0, 0x65, 0xdb, 0x61, - 0xed, 0x99, 0x8d, 0xb2, 0x01, 0xc5, 0x63, 0x72, 0x42, 0xc7, 0x66, 0x8f, 0x18, 0x9c, 0xfd, 0x9c, - 0x88, 0x59, 0x5c, 0xf0, 0x7b, 0x39, 0xea, 0x51, 0xa2, 0xa6, 0xe7, 0x21, 0xaa, 0xfe, 0x85, 0x02, - 0xa5, 0x00, 0x51, 0x3a, 0x76, 0x6c, 0x4a, 0xd0, 0x06, 0x24, 0x89, 0xeb, 0x3a, 0x6e, 0x0c, 0x4e, - 0x7c, 0xd0, 0xda, 0xf1, 0xba, 0xb1, 0x90, 0x5e, 0x05, 0xcb, 0xfb, 0x90, 0x72, 0x09, 0x9d, 0x0c, - 0x99, 0x04, 0x13, 0x45, 0x89, 0x8c, 0xb9, 0x04, 0x4b, 0x0d, 0xfd, 0x3f, 0x2a, 0x54, 0xa4, 0x45, - 0xdc, 0x27, 0xba, 0x3c, 0x91, 0xae, 0x41, 0xc6, 0x87, 0x9b, 0x87, 0x39, 0x8b, 0x83, 0x36, 0xba, - 0x03, 0x29, 0x1e, 0x17, 0x5a, 0x4d, 0xae, 0x6b, 0xf5, 0x2c, 0x96, 0xad, 0x38, 0x3b, 0x52, 0xd7, - 0x62, 0x47, 0xfa, 0x1c, 0x76, 0x44, 0xc2, 0x9e, 0x99, 0x2b, 0xec, 0xbf, 0x54, 0xe0, 0x76, 0x0c, - 0xe4, 0xa5, 0x08, 0xfe, 0xff, 0x54, 0x78, 0x43, 0xda, 0xf5, 0x89, 0x44, 0xb6, 0xfd, 0xaa, 0x30, - 0xe0, 0x2d, 0xc8, 0x07, 0x5b, 0xd4, 0x92, 0x3c, 0xc8, 0xe3, 0xdc, 0x71, 0xe8, 0xc7, 0x92, 0x92, - 0xe1, 0x4b, 0x05, 0x6a, 0x67, 0x81, 0xbe, 0x14, 0x8c, 0xf8, 0x5c, 0x83, 0xd7, 0x43, 0xe3, 0xb0, - 0x69, 0x0f, 0xc8, 0x2b, 0xc2, 0x87, 0xf7, 0x00, 0x8e, 0xc9, 0x89, 0xe1, 0x72, 0x93, 0x39, 0x1b, - 0x3c, 0x4f, 0x83, 0x58, 0xfb, 0xde, 0xe0, 0xec, 0xb1, 0xef, 0xd7, 0x92, 0xf2, 0xe3, 0x57, 0x0a, - 0x54, 0x4f, 0x87, 0x60, 0x29, 0xd8, 0xf1, 0xa7, 0x44, 0xc0, 0x8e, 0x1d, 0x9b, 0x59, 0xec, 0xe4, - 0x95, 0xc9, 0x16, 0x0f, 0x00, 0x11, 0x6e, 0xb1, 0xd1, 0x73, 0x86, 0x93, 0x91, 0x6d, 0xd8, 0xe6, - 0x88, 0xc8, 0xe2, 0xb3, 0x2c, 0x24, 0x2d, 0x2e, 0xd8, 0x33, 0x47, 0x04, 0x7d, 0x1f, 0x56, 0xa4, - 0xf6, 0x4c, 0x8a, 0x49, 0x71, 0x52, 0xd5, 0x7d, 0x4b, 0xcf, 0x41, 0xa2, 0xe1, 0x77, 0xe0, 0x5b, - 0x62, 0x92, 0x4f, 0xce, 0x4f, 0x49, 0xe9, 0x6b, 0x51, 0x2e, 0x73, 0x39, 0xe5, 0xb2, 0xf3, 0x50, - 0xae, 0x76, 0x04, 0x19, 0xdf, 0x68, 0xb4, 0x06, 0x09, 0x6e, 0x9a, 0xc2, 0x4d, 0xcb, 0xf9, 0x05, - 0xa4, 0x67, 0x11, 0x17, 0xa0, 0x0a, 0x24, 0xa7, 0xe6, 0x70, 0x42, 0x78, 0xe0, 0xf2, 0x58, 0x34, - 0xd0, 0x1a, 0xe4, 0x22, 0x58, 0xf1, 0x58, 0xe5, 0x31, 0x84, 0xd9, 0x38, 0x4a, 0xeb, 0x08, 0x62, - 0x4b, 0x41, 0xeb, 0x7f, 0xaa, 0xb0, 0x22, 0x4d, 0xdb, 0x36, 0x59, 0xef, 0xd9, 0x8d, 0x53, 0xfa, - 0x5d, 0x48, 0x7b, 0xd6, 0x58, 0x84, 0x56, 0x35, 0xce, 0xa9, 0x33, 0x48, 0xed, 0x6b, 0x2c, 0x5a, - 0xf0, 0x6e, 0x40, 0xd1, 0xa4, 0x67, 0x14, 0xbb, 0x05, 0x93, 0xbe, 0x8c, 0x4a, 0xf7, 0x4b, 0x25, - 0xa8, 0x2b, 0x25, 0xa6, 0x37, 0x16, 0xea, 0xaf, 0x41, 0x5a, 0x04, 0xd2, 0x47, 0xf3, 0x8e, 0xb4, - 0x4d, 0x84, 0xf9, 0xa9, 0xc5, 0x9e, 0x89, 0xa9, 0x7d, 0x35, 0xdd, 0x86, 0x12, 0x47, 0x9a, 0xfb, - 0xc6, 0xe1, 0x0e, 0xb3, 0x8c, 0x72, 0x85, 0x2c, 0xa3, 0x9e, 0x5b, 0x95, 0x6a, 0xd1, 0xaa, 0x54, - 0xff, 0x63, 0x58, 0x67, 0x71, 0x30, 0x5e, 0x52, 0xa5, 0xfd, 0x5e, 0x9c, 0x66, 0xc1, 0xdb, 0x70, - 0xcc, 0xfb, 0x97, 0x45, 0xb6, 0xab, 0xbe, 0xd8, 0xeb, 0xbf, 0x0e, 0x6b, 0xa5, 0x19, 0xe0, 0x6e, - 0x8c, 0x4b, 0x0f, 0xe2, 0x5c, 0x3a, 0x2b, 0x6f, 0x04, 0x3c, 0xfa, 0x39, 0x54, 0x38, 0x92, 0x61, - 0x86, 0x7f, 0x81, 0x64, 0x8a, 0x17, 0xb8, 0xda, 0xa9, 0x02, 0x57, 0xff, 0xab, 0x0a, 0x77, 0xa3, - 0xf0, 0xbc, 0xcc, 0x22, 0xfe, 0x83, 0x38, 0xb9, 0x56, 0x67, 0xc8, 0x15, 0x83, 0x64, 0x69, 0x19, - 0xf6, 0x5b, 0x05, 0xd6, 0xce, 0x85, 0x70, 0x49, 0x68, 0xf6, 0x7b, 0x15, 0x2a, 0x1d, 0xe6, 0x12, - 0x73, 0x74, 0xad, 0xdb, 0x98, 0x80, 0x95, 0xea, 0xd5, 0xae, 0x58, 0xb4, 0xf9, 0x43, 0x14, 0x3b, - 0x4a, 0x12, 0x97, 0x1c, 0x25, 0xc9, 0xb9, 0x6e, 0xf7, 0x22, 0xb8, 0xa6, 0x2e, 0xc6, 0x55, 0x6f, - 0xc1, 0xed, 0x18, 0x50, 0x32, 0x84, 0x61, 0x39, 0xa0, 0x5c, 0x5a, 0x0e, 0x7c, 0xa1, 0x42, 0x6d, - 0x66, 0x96, 0xeb, 0xa4, 0xeb, 0xb9, 0x41, 0x8f, 0xa6, 0x02, 0xed, 0xdc, 0x73, 0x25, 0x71, 0xd1, - 0x6d, 0x47, 0x72, 0xce, 0x40, 0x5d, 0x79, 0x93, 0xb4, 0xe1, 0xcd, 0x33, 0x01, 0x59, 0x00, 0xdc, - 0xdf, 0xa8, 0xb0, 0x36, 0x33, 0xd7, 0xb5, 0x73, 0xd6, 0x0b, 0x41, 0x38, 0x9e, 0x6c, 0x13, 0x97, - 0xde, 0x26, 0xdc, 0x18, 0xd8, 0x7b, 0xb0, 0x7e, 0x3e, 0x40, 0x0b, 0x20, 0xfe, 0x07, 0x15, 0xbe, - 0x12, 0x9f, 0xf0, 0x3a, 0x2f, 0xf6, 0x2f, 0x04, 0xef, 0xd9, 0xb7, 0xf5, 0xc4, 0x02, 0x6f, 0xeb, - 0x37, 0x86, 0xff, 0x63, 0xb8, 0x7b, 0x1e, 0x5c, 0x0b, 0xa0, 0xff, 0x03, 0xc8, 0x6f, 0x93, 0x81, - 0x65, 0x2f, 0x86, 0xf5, 0xcc, 0x7f, 0x2d, 0xea, 0xec, 0x7f, 0x2d, 0xfa, 0xb7, 0xa1, 0x20, 0xa7, - 0x96, 0x76, 0x45, 0x12, 0xa5, 0x72, 0x49, 0xa2, 0xfc, 0x5c, 0x81, 0x42, 0x8b, 0xff, 0x25, 0x73, - 0xe3, 0x85, 0xc2, 0x1d, 0x48, 0x99, 0xcc, 0x19, 0x59, 0x3d, 0xf9, 0x67, 0x91, 0x6c, 0xe9, 0x65, - 0x28, 0xfa, 0x16, 0x08, 0xfb, 0xf5, 0x9f, 0x40, 0x09, 0x3b, 0xc3, 0xe1, 0x91, 0xd9, 0x3b, 0xbe, - 0x69, 0xab, 0x74, 0x04, 0xe5, 0x70, 0x2d, 0xb9, 0xfe, 0xa7, 0xf0, 0x06, 0x26, 0xd4, 0x19, 0x4e, - 0x49, 0xa4, 0xa4, 0x58, 0xcc, 0x12, 0x04, 0x89, 0x3e, 0x93, 0xff, 0xab, 0x64, 0x31, 0x7f, 0xd6, - 0xff, 0xa2, 0x40, 0x65, 0x97, 0x50, 0x6a, 0x0e, 0x88, 0x20, 0xd8, 0x62, 0x53, 0x5f, 0x54, 0x33, - 0x56, 0x20, 0x29, 0x4e, 0x5e, 0xb1, 0xdf, 0x44, 0x03, 0x6d, 0x42, 0x36, 0xd8, 0x6c, 0xfc, 0x4c, - 0x3e, 0x7b, 0xaf, 0x65, 0xfc, 0xbd, 0xe6, 0x59, 0x1f, 0xb9, 0x1f, 0xe1, 0xcf, 0xfa, 0x2f, 0x14, - 0xb8, 0x25, 0xad, 0xdf, 0x5a, 0x34, 0x3e, 0x17, 0x99, 0xee, 0xaf, 0xa9, 0x85, 0x6b, 0xa2, 0xbb, - 0xa0, 0xf9, 0xc9, 0x38, 0xd7, 0xcc, 0xcb, 0x5d, 0x76, 0x68, 0x0e, 0x27, 0x04, 0x7b, 0x02, 0x7d, - 0x17, 0xf2, 0xed, 0x48, 0xa5, 0x89, 0x56, 0x41, 0x0d, 0xcc, 0x98, 0x55, 0x57, 0xad, 0x7e, 0xfc, - 0x8a, 0x42, 0x3d, 0x75, 0x45, 0xf1, 0x67, 0x05, 0x56, 0x43, 0x17, 0xaf, 0x7d, 0x30, 0x5d, 0xd5, - 0xdb, 0x0f, 0xa1, 0x64, 0xf5, 0x8d, 0x53, 0xc7, 0x50, 0xae, 0x59, 0xf1, 0x59, 0x1c, 0x75, 0x16, - 0x17, 0xac, 0x48, 0x8b, 0xea, 0xab, 0x50, 0x3b, 0x8b, 0xbc, 0x92, 0xda, 0xff, 0x55, 0xe1, 0x56, - 0x67, 0x3c, 0xb4, 0x98, 0xcc, 0x51, 0x2f, 0xda, 0x9f, 0xb9, 0x2f, 0xe9, 0xde, 0x82, 0x3c, 0xf5, - 0xec, 0x90, 0xf7, 0x70, 0xb2, 0xa0, 0xc9, 0xf1, 0x3e, 0x71, 0x03, 0xe7, 0xc5, 0xc9, 0x57, 0x99, - 0xd8, 0x8c, 0x93, 0x50, 0xc3, 0x20, 0x35, 0x26, 0x36, 0x43, 0x5f, 0x87, 0xd7, 0xed, 0xc9, 0xc8, - 0x70, 0x9d, 0xe7, 0xd4, 0x18, 0x13, 0xd7, 0xe0, 0x33, 0x1b, 0x63, 0xd3, 0x65, 0x3c, 0xc5, 0x6b, - 0x78, 0xc5, 0x9e, 0x8c, 0xb0, 0xf3, 0x9c, 0x1e, 0x10, 0x97, 0x2f, 0x7e, 0x60, 0xba, 0x0c, 0x7d, - 0x17, 0xb2, 0xe6, 0x70, 0xe0, 0xb8, 0x16, 0x7b, 0x36, 0x92, 0x17, 0x6f, 0xba, 0x34, 0xf3, 0x14, - 0x32, 0x8d, 0x2d, 0x5f, 0x13, 0x87, 0x83, 0xd0, 0xbb, 0x80, 0x26, 0x94, 0x18, 0xc2, 0x38, 0xb1, - 0xe8, 0xb4, 0x29, 0x6f, 0xe1, 0x4a, 0x13, 0x4a, 0xc2, 0x69, 0x0e, 0x9b, 0xfa, 0xdf, 0x34, 0x40, - 0xd1, 0x79, 0x65, 0x8e, 0xfe, 0x26, 0xa4, 0xf8, 0x78, 0x5a, 0x55, 0x78, 0x6c, 0xd7, 0x82, 0x0c, - 0x75, 0x4a, 0xb7, 0xe1, 0x99, 0x8d, 0xa5, 0x7a, 0xed, 0x53, 0xc8, 0xfb, 0x3b, 0x95, 0xbb, 0x13, - 0x8d, 0x86, 0x72, 0xe1, 0xe9, 0xaa, 0xce, 0x71, 0xba, 0xd6, 0x3e, 0x82, 0x2c, 0xaf, 0xea, 0x2e, - 0x9d, 0x3b, 0xac, 0x45, 0xd5, 0x68, 0x2d, 0x5a, 0xfb, 0x97, 0x02, 0x09, 0x3e, 0x78, 0xee, 0x97, - 0xdf, 0x5d, 0xfe, 0xbe, 0x20, 0xac, 0x14, 0xd1, 0x13, 0x49, 0xfb, 0xde, 0x05, 0x90, 0x44, 0x21, - 0xc0, 0xf9, 0xe3, 0x28, 0x20, 0x2d, 0x00, 0xf1, 0x71, 0x03, 0x9f, 0x4a, 0xf0, 0xf0, 0xab, 0x17, - 0x4c, 0x15, 0xb8, 0x8b, 0xb3, 0x34, 0xf0, 0x1c, 0x41, 0x82, 0x5a, 0x3f, 0x13, 0x59, 0x52, 0xc3, - 0xfc, 0x59, 0x7f, 0x1f, 0x6e, 0x3f, 0x22, 0xac, 0xe3, 0x4e, 0xfd, 0xed, 0xe6, 0x6f, 0x9f, 0x0b, - 0x60, 0xd2, 0x31, 0xdc, 0x89, 0x0f, 0x92, 0x0c, 0xf8, 0x16, 0xe4, 0xa9, 0x3b, 0x35, 0x66, 0x46, - 0x7a, 0x55, 0x49, 0x10, 0x9e, 0xe8, 0xa0, 0x1c, 0x0d, 0x1b, 0xfa, 0xdf, 0x15, 0x28, 0x1e, 0x5e, - 0xe7, 0xe8, 0x88, 0x95, 0x50, 0xea, 0x9c, 0x25, 0xd4, 0x3d, 0x48, 0x4e, 0x07, 0x4c, 0xde, 0xea, - 0x7a, 0x11, 0x8d, 0x7c, 0xb5, 0x72, 0xf8, 0x88, 0x59, 0x7d, 0x2c, 0xe4, 0x5e, 0x61, 0xf4, 0x63, - 0x6b, 0xc8, 0x88, 0x1b, 0x9c, 0x32, 0x11, 0xcd, 0x8f, 0xb9, 0x04, 0x4b, 0x0d, 0xfd, 0x3b, 0x50, - 0x0a, 0x7c, 0x09, 0xeb, 0x2a, 0x32, 0x25, 0x76, 0xb0, 0x37, 0x66, 0x86, 0x1f, 0xee, 0x78, 0x22, - 0x2c, 0x35, 0xf4, 0xdf, 0xa9, 0xb0, 0xf2, 0x64, 0xdc, 0x37, 0xd9, 0xb2, 0x9f, 0xa5, 0x0b, 0x96, - 0xad, 0xab, 0x90, 0x65, 0xd6, 0x88, 0x50, 0x66, 0x8e, 0xc6, 0x32, 0xab, 0x85, 0x1d, 0x5e, 0x44, - 0x38, 0x0e, 0xf2, 0x32, 0xd6, 0xdf, 0x63, 0x1c, 0xa2, 0xae, 0x73, 0x4c, 0x6c, 0x2c, 0xe4, 0xfa, - 0x31, 0x54, 0x66, 0x51, 0x92, 0x50, 0xd7, 0xfd, 0x09, 0x66, 0x2b, 0x58, 0x59, 0xf8, 0x72, 0xa4, - 0x85, 0x02, 0x7a, 0x07, 0xca, 0x5e, 0x29, 0x3b, 0x22, 0x46, 0x68, 0x8f, 0xf8, 0x5a, 0xa4, 0x24, - 0xfa, 0xbb, 0x7e, 0xf7, 0xfd, 0x87, 0x50, 0x8a, 0x7d, 0x66, 0x83, 0x4a, 0x90, 0x7b, 0xb2, 0xd7, - 0x39, 0xd8, 0x69, 0xb5, 0x3f, 0x6e, 0xef, 0x3c, 0x2c, 0xbf, 0x86, 0x00, 0x52, 0x9d, 0xf6, 0xde, - 0xa3, 0xc7, 0x3b, 0x65, 0x05, 0x65, 0x21, 0xb9, 0xfb, 0xe4, 0x71, 0xb7, 0x5d, 0x56, 0xbd, 0xc7, - 0xee, 0xd3, 0xfd, 0x83, 0x56, 0x59, 0xbb, 0xff, 0x21, 0xe4, 0x44, 0x5d, 0xb8, 0xef, 0xf6, 0x89, - 0xeb, 0x0d, 0xd8, 0xdb, 0xc7, 0xbb, 0x5b, 0x8f, 0xcb, 0xaf, 0xa1, 0x34, 0x68, 0x07, 0xd8, 0x1b, - 0x99, 0x81, 0xc4, 0xc1, 0x7e, 0xa7, 0x5b, 0x56, 0x51, 0x11, 0x60, 0xeb, 0x49, 0x77, 0xbf, 0xb5, - 0xbf, 0xbb, 0xdb, 0xee, 0x96, 0xb5, 0xed, 0x0f, 0xa0, 0x64, 0x39, 0x8d, 0xa9, 0xc5, 0x08, 0xa5, - 0xe2, 0x43, 0xa9, 0x1f, 0xbe, 0x2d, 0x5b, 0x96, 0xb3, 0x29, 0x9e, 0x36, 0x07, 0xce, 0xe6, 0x94, - 0x6d, 0x72, 0xe9, 0xa6, 0x48, 0x10, 0x47, 0x29, 0xde, 0x7a, 0xff, 0xff, 0x01, 0x00, 0x00, 0xff, - 0xff, 0x4b, 0xc0, 0xed, 0xac, 0xa8, 0x25, 0x00, 0x00, + 0x15, 0x4f, 0x77, 0xfb, 0xf3, 0xf9, 0x73, 0x6b, 0xbc, 0xbb, 0x8e, 0x33, 0xec, 0x38, 0x9d, 0x8c, + 0xd6, 0xd9, 0xac, 0x3c, 0xc4, 0x81, 0x80, 0x50, 0x50, 0x98, 0xf1, 0x4e, 0x56, 0x56, 0x76, 0x3e, + 0x28, 0x7b, 0x67, 0x01, 0x11, 0xb5, 0x7a, 0xec, 0xc2, 0xdb, 0x8c, 0xdd, 0xed, 0x74, 0x95, 0xbd, + 0x0c, 0x07, 0x94, 0x0b, 0xe7, 0x88, 0x03, 0x12, 0x8a, 0x90, 0x10, 0x12, 0x12, 0x27, 0xae, 0x48, + 0xc0, 0x85, 0x1b, 0x12, 0x17, 0xc4, 0x89, 0x3b, 0xff, 0x00, 0x12, 0x7f, 0x41, 0xd4, 0x55, 0xd5, + 0x1f, 0xf6, 0x7c, 0x79, 0x3c, 0x3b, 0x23, 0xef, 0xc5, 0xea, 0xaa, 0xf7, 0xea, 0xd5, 0xab, 0xdf, + 0xfb, 0xd5, 0xab, 0xd7, 0xe5, 0x86, 0xec, 0x84, 0xf5, 0x4d, 0x46, 0xea, 0x23, 0xd7, 0x61, 0x0e, + 0x4a, 0x88, 0x56, 0xa5, 0x78, 0x68, 0xd9, 0x03, 0xa7, 0xdf, 0x33, 0x99, 0x29, 0x24, 0x95, 0xcc, + 0x67, 0x63, 0xe2, 0x1e, 0xcb, 0x46, 0x9e, 0x39, 0x23, 0x27, 0x2a, 0x9c, 0x30, 0x77, 0xd4, 0x15, + 0x0d, 0xfd, 0x97, 0x71, 0x48, 0xb6, 0x09, 0xa5, 0x96, 0x63, 0xa3, 0x75, 0xc8, 0x5b, 0xb6, 0xc1, + 0x5c, 0xd3, 0xa6, 0x66, 0x97, 0x59, 0x8e, 0x5d, 0x56, 0xaa, 0x4a, 0x2d, 0x85, 0x73, 0x96, 0xdd, + 0x09, 0x3b, 0x51, 0x13, 0xf2, 0xf4, 0xb9, 0xe9, 0xf6, 0x0c, 0x2a, 0xc6, 0xd1, 0xb2, 0x5a, 0xd5, + 0x6a, 0x99, 0xc6, 0x6a, 0x5d, 0x7a, 0x27, 0xed, 0xd5, 0xdb, 0x9e, 0x96, 0x6c, 0xe0, 0x1c, 0x8d, + 0xb4, 0x28, 0x7a, 0x03, 0xd2, 0xd4, 0xb2, 0xfb, 0x03, 0x62, 0xf4, 0x0e, 0xcb, 0x1a, 0x9f, 0x26, + 0x25, 0x3a, 0x1e, 0x1d, 0xa2, 0x7b, 0x00, 0xe6, 0x98, 0x39, 0x5d, 0x67, 0x38, 0xb4, 0x58, 0x39, + 0xc6, 0xa5, 0x91, 0x1e, 0xf4, 0x16, 0xe4, 0x98, 0xe9, 0xf6, 0x09, 0x33, 0x28, 0x73, 0x2d, 0xbb, + 0x5f, 0x8e, 0x57, 0x95, 0x5a, 0x1a, 0x67, 0x45, 0x67, 0x9b, 0xf7, 0xa1, 0x0d, 0x48, 0x3a, 0x23, + 0xc6, 0xfd, 0x4b, 0x54, 0x95, 0x5a, 0xa6, 0x71, 0xbb, 0x2e, 0x50, 0xd9, 0xfe, 0x19, 0xe9, 0x8e, + 0x19, 0xd9, 0x13, 0x42, 0xec, 0x6b, 0xa1, 0x2d, 0x28, 0x46, 0xd6, 0x6e, 0x0c, 0x9d, 0x1e, 0x29, + 0x27, 0xab, 0x4a, 0x2d, 0xdf, 0xb8, 0xeb, 0xaf, 0x2c, 0x02, 0xc3, 0x8e, 0xd3, 0x23, 0xb8, 0xc0, + 0xa6, 0x3b, 0xd0, 0x06, 0xa4, 0x5e, 0x98, 0xae, 0x6d, 0xd9, 0x7d, 0x5a, 0x4e, 0x71, 0x54, 0x56, + 0xe4, 0xac, 0xdf, 0xf7, 0x7e, 0x9f, 0x09, 0x19, 0x0e, 0x94, 0xd0, 0x47, 0x90, 0x1d, 0xb9, 0x24, + 0x84, 0x32, 0x3d, 0x07, 0x94, 0x99, 0x91, 0x4b, 0x02, 0x20, 0x37, 0x21, 0x37, 0x72, 0x28, 0x0b, + 0x2d, 0xc0, 0x1c, 0x16, 0xb2, 0xde, 0x90, 0xc0, 0xc4, 0xdb, 0x90, 0x1f, 0x98, 0x94, 0x19, 0x96, + 0x4d, 0x89, 0xcb, 0x0c, 0xab, 0x57, 0xce, 0x54, 0x95, 0x5a, 0x0c, 0x67, 0xbd, 0xde, 0x16, 0xef, + 0x6c, 0xf5, 0x2a, 0x3f, 0x86, 0x6c, 0xd4, 0x06, 0x5a, 0x87, 0x84, 0xc0, 0x9b, 0xb3, 0x24, 0xd3, + 0xc8, 0xc9, 0x85, 0x76, 0x78, 0x27, 0x96, 0x42, 0x8f, 0x54, 0x51, 0x54, 0xad, 0x5e, 0x59, 0xad, + 0x2a, 0x35, 0x0d, 0xe7, 0x22, 0xbd, 0xad, 0x9e, 0xfe, 0x2f, 0x15, 0xf2, 0x32, 0x30, 0x98, 0x7c, + 0x36, 0x26, 0x94, 0xa1, 0x87, 0x90, 0xee, 0x9a, 0x83, 0x01, 0x71, 0xbd, 0x41, 0x62, 0x8e, 0x42, + 0x5d, 0x70, 0xb7, 0xc9, 0xfb, 0x5b, 0x8f, 0x70, 0x4a, 0x68, 0xb4, 0x7a, 0xe8, 0x1d, 0x48, 0x4a, + 0x08, 0xf8, 0x04, 0x42, 0x37, 0x8a, 0x00, 0xf6, 0xe5, 0xe8, 0x3e, 0xc4, 0xb9, 0xab, 0x9c, 0x77, + 0x99, 0xc6, 0x2d, 0xe9, 0xf8, 0x96, 0x33, 0xb6, 0x7b, 0x3c, 0x4c, 0x58, 0xc8, 0xd1, 0x37, 0x21, + 0xc3, 0xcc, 0xc3, 0x01, 0x61, 0x06, 0x3b, 0x1e, 0x11, 0x4e, 0xc4, 0x7c, 0xa3, 0x54, 0x0f, 0xf6, + 0x53, 0x87, 0x0b, 0x3b, 0xc7, 0x23, 0x82, 0x81, 0x05, 0xcf, 0xe8, 0x21, 0x20, 0xdb, 0xf1, 0xe0, + 0x9c, 0xda, 0x4b, 0x71, 0x4e, 0xe3, 0xa2, 0xed, 0xb0, 0xd6, 0xd4, 0x76, 0x5a, 0x87, 0xfc, 0x11, + 0x39, 0xa6, 0x23, 0xb3, 0x4b, 0x0c, 0xbe, 0x47, 0x38, 0x5d, 0xd3, 0x38, 0xe7, 0xf7, 0x72, 0xd4, + 0xa3, 0x74, 0x4e, 0xce, 0x43, 0x67, 0xfd, 0x0b, 0x05, 0x0a, 0x01, 0xa2, 0x74, 0xe4, 0xd8, 0x94, + 0xa0, 0x75, 0x88, 0x13, 0xd7, 0x75, 0xdc, 0x19, 0x38, 0xf1, 0x7e, 0x73, 0xdb, 0xeb, 0xc6, 0x42, + 0x7a, 0x19, 0x2c, 0x1f, 0x40, 0xc2, 0x25, 0x74, 0x3c, 0x60, 0x12, 0x4c, 0x14, 0xa5, 0x3b, 0xe6, + 0x12, 0x2c, 0x35, 0xf4, 0xff, 0xaa, 0x50, 0x92, 0x1e, 0xf1, 0x35, 0xd1, 0xe5, 0x89, 0x74, 0x05, + 0x52, 0x3e, 0xdc, 0x3c, 0xcc, 0x69, 0x1c, 0xb4, 0xd1, 0x1d, 0x48, 0xf0, 0xb8, 0xd0, 0x72, 0xbc, + 0xaa, 0xd5, 0xd2, 0x58, 0xb6, 0x66, 0xd9, 0x91, 0xb8, 0x12, 0x3b, 0x92, 0x67, 0xb0, 0x23, 0x12, + 0xf6, 0xd4, 0x5c, 0x61, 0xff, 0xb5, 0x02, 0xb7, 0x67, 0x40, 0x5e, 0x8a, 0xe0, 0xff, 0x5f, 0x85, + 0xd7, 0xa5, 0x5f, 0x9f, 0x48, 0x64, 0x5b, 0xaf, 0x0a, 0x03, 0xde, 0x84, 0x6c, 0xb0, 0x45, 0x2d, + 0xc9, 0x83, 0x2c, 0xce, 0x1c, 0x85, 0xeb, 0x58, 0x52, 0x32, 0x7c, 0xa9, 0x40, 0xe5, 0x34, 0xd0, + 0x97, 0x82, 0x11, 0x9f, 0x6b, 0x70, 0x37, 0x74, 0x0e, 0x9b, 0x76, 0x9f, 0xbc, 0x22, 0x7c, 0x78, + 0x0f, 0xe0, 0x88, 0x1c, 0x1b, 0x2e, 0x77, 0x99, 0xb3, 0xc1, 0x5b, 0x69, 0x10, 0x6b, 0x7f, 0x35, + 0x38, 0x7d, 0xe4, 0xaf, 0x6b, 0x49, 0xf9, 0xf1, 0x1b, 0x05, 0xca, 0x27, 0x43, 0xb0, 0x14, 0xec, + 0xf8, 0x4b, 0x2c, 0x60, 0xc7, 0xb6, 0xcd, 0x2c, 0x76, 0xfc, 0xca, 0x64, 0x8b, 0x87, 0x80, 0x08, + 0xf7, 0xd8, 0xe8, 0x3a, 0x83, 0xf1, 0xd0, 0x36, 0x6c, 0x73, 0x48, 0x64, 0x89, 0x5a, 0x14, 0x92, + 0x26, 0x17, 0xec, 0x9a, 0x43, 0x82, 0x7e, 0x00, 0x2b, 0x52, 0x7b, 0x2a, 0xc5, 0x24, 0x38, 0xa9, + 0x6a, 0xbe, 0xa7, 0x67, 0x20, 0x51, 0xf7, 0x3b, 0xf0, 0x2d, 0x61, 0xe4, 0x93, 0xb3, 0x53, 0x52, + 0xf2, 0x4a, 0x94, 0x4b, 0x5d, 0x4c, 0xb9, 0xf4, 0x3c, 0x94, 0xab, 0x1c, 0x42, 0xca, 0x77, 0x1a, + 0xad, 0x41, 0x8c, 0xbb, 0xa6, 0x70, 0xd7, 0x32, 0x7e, 0x01, 0xe9, 0x79, 0xc4, 0x05, 0xa8, 0x04, + 0xf1, 0x89, 0x39, 0x18, 0x13, 0x1e, 0xb8, 0x2c, 0x16, 0x0d, 0xb4, 0x06, 0x99, 0x08, 0x56, 0x3c, + 0x56, 0x59, 0x0c, 0x61, 0x36, 0x8e, 0xd2, 0x3a, 0x82, 0xd8, 0x52, 0xd0, 0xfa, 0xdf, 0x2a, 0xac, + 0x48, 0xd7, 0xb6, 0x4c, 0xd6, 0x7d, 0x7e, 0xed, 0x94, 0x7e, 0x17, 0x92, 0x9e, 0x37, 0x16, 0xa1, + 0x65, 0x8d, 0x73, 0xea, 0x14, 0x52, 0xfb, 0x1a, 0x8b, 0x16, 0xbc, 0xeb, 0x90, 0x37, 0xe9, 0x29, + 0xc5, 0x6e, 0xce, 0xa4, 0x37, 0x51, 0xe9, 0x7e, 0xa9, 0x04, 0x75, 0xa5, 0xc4, 0xf4, 0xda, 0x42, + 0xfd, 0x75, 0x48, 0x8a, 0x40, 0xfa, 0x68, 0xde, 0x91, 0xbe, 0x89, 0x30, 0x3f, 0xb3, 0xd8, 0x73, + 0x61, 0xda, 0x57, 0xd3, 0x6d, 0x28, 0x70, 0xa4, 0xf9, 0xda, 0x38, 0xdc, 0x61, 0x96, 0x51, 0x2e, + 0x91, 0x65, 0xd4, 0x33, 0xab, 0x52, 0x2d, 0x5a, 0x95, 0xea, 0x7f, 0x0e, 0xeb, 0x2c, 0x0e, 0xc6, + 0x0d, 0x55, 0xda, 0xef, 0xcd, 0xd2, 0x2c, 0x78, 0x67, 0x9e, 0x59, 0xfd, 0x4d, 0x91, 0xed, 0xb2, + 0xaf, 0xff, 0xfa, 0x6f, 0xc3, 0x5a, 0x69, 0x0a, 0xb8, 0x6b, 0xe3, 0xd2, 0xc3, 0x59, 0x2e, 0x9d, + 0x96, 0x37, 0x02, 0x1e, 0xfd, 0x02, 0x4a, 0x1c, 0xc9, 0x30, 0xc3, 0xbf, 0x44, 0x32, 0xcd, 0x16, + 0xb8, 0xda, 0x89, 0x02, 0x57, 0xff, 0xbb, 0x0a, 0xf7, 0xa2, 0xf0, 0xdc, 0x64, 0x11, 0xff, 0xc1, + 0x2c, 0xb9, 0x56, 0xa7, 0xc8, 0x35, 0x03, 0xc9, 0xd2, 0x32, 0xec, 0xf7, 0x0a, 0xac, 0x9d, 0x09, + 0xe1, 0x92, 0xd0, 0xec, 0x8f, 0x2a, 0x94, 0xda, 0xcc, 0x25, 0xe6, 0xf0, 0x4a, 0xb7, 0x31, 0x01, + 0x2b, 0xd5, 0xcb, 0x5d, 0xb1, 0x68, 0xf3, 0x87, 0x68, 0xe6, 0x28, 0x89, 0x5d, 0x70, 0x94, 0xc4, + 0xe7, 0xba, 0x03, 0x8c, 0xe0, 0x9a, 0x38, 0x1f, 0x57, 0xbd, 0x09, 0xb7, 0x67, 0x80, 0x92, 0x21, + 0x0c, 0xcb, 0x01, 0xe5, 0xc2, 0x72, 0xe0, 0x0b, 0x15, 0x2a, 0x53, 0x56, 0xae, 0x92, 0xae, 0xe7, + 0x06, 0x3d, 0x9a, 0x0a, 0xb4, 0x33, 0xcf, 0x95, 0xd8, 0x79, 0xb7, 0x1d, 0xf1, 0x39, 0x03, 0x75, + 0xe9, 0x4d, 0xd2, 0x82, 0x37, 0x4e, 0x05, 0x64, 0x01, 0x70, 0x7f, 0xa7, 0xc2, 0xda, 0x94, 0xad, + 0x2b, 0xe7, 0xac, 0x97, 0x82, 0xf0, 0x6c, 0xb2, 0x8d, 0x5d, 0x78, 0x9b, 0x70, 0x6d, 0x60, 0xef, + 0x42, 0xf5, 0x6c, 0x80, 0x16, 0x40, 0xfc, 0x4f, 0x2a, 0x7c, 0x6d, 0xd6, 0xe0, 0x55, 0x5e, 0xec, + 0x5f, 0x0a, 0xde, 0xd3, 0x6f, 0xeb, 0xb1, 0x05, 0xde, 0xd6, 0xaf, 0x0d, 0xff, 0x27, 0x70, 0xef, + 0x2c, 0xb8, 0x16, 0x40, 0xff, 0x87, 0x90, 0xdd, 0x22, 0x7d, 0xcb, 0x5e, 0x0c, 0xeb, 0xa9, 0x7f, + 0x64, 0xd4, 0xe9, 0x7f, 0x64, 0xf4, 0xef, 0x40, 0x4e, 0x9a, 0x96, 0x7e, 0x45, 0x12, 0xa5, 0x72, + 0x41, 0xa2, 0xfc, 0x5c, 0x81, 0x5c, 0x93, 0xff, 0x71, 0x73, 0xed, 0x85, 0xc2, 0x1d, 0x48, 0x98, + 0xcc, 0x19, 0x5a, 0x5d, 0xf9, 0x97, 0x92, 0x6c, 0xe9, 0x45, 0xc8, 0xfb, 0x1e, 0x08, 0xff, 0xf5, + 0x9f, 0x42, 0x01, 0x3b, 0x83, 0xc1, 0xa1, 0xd9, 0x3d, 0xba, 0x6e, 0xaf, 0x74, 0x04, 0xc5, 0x70, + 0x2e, 0x39, 0xff, 0xa7, 0xf0, 0x3a, 0x26, 0xd4, 0x19, 0x4c, 0x48, 0xa4, 0xa4, 0x58, 0xcc, 0x13, + 0x04, 0xb1, 0x1e, 0x93, 0xff, 0xab, 0xa4, 0x31, 0x7f, 0xd6, 0xff, 0xa6, 0x40, 0x69, 0x87, 0x50, + 0x6a, 0xf6, 0x89, 0x20, 0xd8, 0x62, 0xa6, 0xcf, 0xab, 0x19, 0x4b, 0x10, 0x17, 0x27, 0xaf, 0xd8, + 0x6f, 0xa2, 0x81, 0x36, 0x20, 0x1d, 0x6c, 0x36, 0x7e, 0x26, 0x9f, 0xbe, 0xd7, 0x52, 0xfe, 0x5e, + 0xf3, 0xbc, 0x8f, 0xdc, 0x8f, 0xf0, 0x67, 0xfd, 0x57, 0x0a, 0xdc, 0x92, 0xde, 0x6f, 0x2e, 0x1a, + 0x9f, 0xf3, 0x5c, 0xf7, 0xe7, 0xd4, 0xc2, 0x39, 0xd1, 0x3d, 0xd0, 0xfc, 0x64, 0x9c, 0x69, 0x64, + 0xe5, 0x2e, 0x3b, 0x30, 0x07, 0x63, 0x82, 0x3d, 0x81, 0xbe, 0x03, 0xd9, 0x56, 0xa4, 0xd2, 0x44, + 0xab, 0xa0, 0x06, 0x6e, 0x4c, 0xab, 0xab, 0x56, 0x6f, 0xf6, 0x8a, 0x42, 0x3d, 0x71, 0x45, 0xf1, + 0x57, 0x05, 0x56, 0xc3, 0x25, 0x5e, 0xf9, 0x60, 0xba, 0xec, 0x6a, 0x3f, 0x84, 0x82, 0xd5, 0x33, + 0x4e, 0x1c, 0x43, 0x99, 0x46, 0xc9, 0x67, 0x71, 0x74, 0xb1, 0x38, 0x67, 0x45, 0x5a, 0x54, 0x5f, + 0x85, 0xca, 0x69, 0xe4, 0x95, 0xd4, 0xfe, 0x9f, 0x0a, 0xb7, 0xda, 0xa3, 0x81, 0xc5, 0x64, 0x8e, + 0x7a, 0xd9, 0xeb, 0x99, 0xfb, 0x92, 0xee, 0x4d, 0xc8, 0x52, 0xcf, 0x0f, 0x79, 0x0f, 0x27, 0x0b, + 0x9a, 0x0c, 0xef, 0x13, 0x37, 0x70, 0x5e, 0x9c, 0x7c, 0x95, 0xb1, 0xcd, 0x38, 0x09, 0x35, 0x0c, + 0x52, 0x63, 0x6c, 0x33, 0xf4, 0x0d, 0xb8, 0x6b, 0x8f, 0x87, 0x86, 0xeb, 0xbc, 0xa0, 0xc6, 0x88, + 0xb8, 0x06, 0xb7, 0x6c, 0x8c, 0x4c, 0x97, 0xf1, 0x14, 0xaf, 0xe1, 0x15, 0x7b, 0x3c, 0xc4, 0xce, + 0x0b, 0xba, 0x4f, 0x5c, 0x3e, 0xf9, 0xbe, 0xe9, 0x32, 0xf4, 0x3d, 0x48, 0x9b, 0x83, 0xbe, 0xe3, + 0x5a, 0xec, 0xf9, 0x50, 0x5e, 0xbc, 0xe9, 0xd2, 0xcd, 0x13, 0xc8, 0xd4, 0x37, 0x7d, 0x4d, 0x1c, + 0x0e, 0x42, 0xef, 0x02, 0x1a, 0x53, 0x62, 0x08, 0xe7, 0xc4, 0xa4, 0x93, 0x86, 0xbc, 0x85, 0x2b, + 0x8c, 0x29, 0x09, 0xcd, 0x1c, 0x34, 0xf4, 0x7f, 0x68, 0x80, 0xa2, 0x76, 0x65, 0x8e, 0xfe, 0x16, + 0x24, 0xf8, 0x78, 0x5a, 0x56, 0x78, 0x6c, 0xd7, 0x82, 0x0c, 0x75, 0x42, 0xb7, 0xee, 0xb9, 0x8d, + 0xa5, 0x7a, 0xe5, 0x53, 0xc8, 0xfa, 0x3b, 0x95, 0x2f, 0x27, 0x1a, 0x0d, 0xe5, 0xdc, 0xd3, 0x55, + 0x9d, 0xe3, 0x74, 0xad, 0x7c, 0x04, 0x69, 0x5e, 0xd5, 0x5d, 0x68, 0x3b, 0xac, 0x45, 0xd5, 0x68, + 0x2d, 0x5a, 0xf9, 0x8f, 0x02, 0x31, 0x3e, 0x78, 0xee, 0x97, 0xdf, 0x1d, 0xfe, 0xbe, 0x20, 0xbc, + 0x14, 0xd1, 0x13, 0x49, 0xfb, 0xfe, 0x39, 0x90, 0x44, 0x21, 0xc0, 0xd9, 0xa3, 0x28, 0x20, 0x4d, + 0x00, 0xf1, 0x09, 0x04, 0x37, 0x25, 0x78, 0xf8, 0xf6, 0x39, 0xa6, 0x82, 0xe5, 0xe2, 0x34, 0x0d, + 0x56, 0x8e, 0x20, 0x46, 0xad, 0x9f, 0x8b, 0x2c, 0xa9, 0x61, 0xfe, 0xac, 0xbf, 0x0f, 0xb7, 0x1f, + 0x13, 0xd6, 0x76, 0x27, 0xfe, 0x76, 0xf3, 0xb7, 0xcf, 0x39, 0x30, 0xe9, 0x18, 0xee, 0xcc, 0x0e, + 0x92, 0x0c, 0xf8, 0x36, 0x64, 0xa9, 0x3b, 0x31, 0xa6, 0x46, 0x7a, 0x55, 0x49, 0x10, 0x9e, 0xe8, + 0xa0, 0x0c, 0x0d, 0x1b, 0xfa, 0x3f, 0x15, 0xc8, 0x1f, 0x5c, 0xe5, 0xe8, 0x98, 0x29, 0xa1, 0xd4, + 0x39, 0x4b, 0xa8, 0xfb, 0x10, 0x9f, 0xf4, 0x99, 0xbc, 0xd5, 0xf5, 0x22, 0x1a, 0xf9, 0xb6, 0xe5, + 0xe0, 0x31, 0xb3, 0x7a, 0x58, 0xc8, 0xbd, 0xc2, 0xe8, 0x27, 0xd6, 0x80, 0x11, 0x37, 0x38, 0x65, + 0x22, 0x9a, 0x1f, 0x73, 0x09, 0x96, 0x1a, 0xfa, 0x77, 0xa1, 0x10, 0xac, 0x25, 0xac, 0xab, 0xc8, + 0x84, 0xd8, 0xc1, 0xde, 0x98, 0x1a, 0x7e, 0xb0, 0xed, 0x89, 0xb0, 0xd4, 0xd0, 0xff, 0xa0, 0xc2, + 0xca, 0xd3, 0x51, 0xcf, 0x64, 0xcb, 0x7e, 0x96, 0x2e, 0x58, 0xb6, 0xae, 0x42, 0x9a, 0x59, 0x43, + 0x42, 0x99, 0x39, 0x1c, 0xc9, 0xac, 0x16, 0x76, 0x78, 0x11, 0xe1, 0x38, 0xc8, 0xcb, 0x58, 0x7f, + 0x8f, 0x71, 0x88, 0x3a, 0xce, 0x11, 0xb1, 0xb1, 0x90, 0xeb, 0x47, 0x50, 0x9a, 0x46, 0x49, 0x42, + 0x5d, 0xf3, 0x0d, 0x4c, 0x57, 0xb0, 0xb2, 0xf0, 0xe5, 0x48, 0x0b, 0x05, 0xf4, 0x0e, 0x14, 0xbd, + 0x52, 0x76, 0x48, 0x8c, 0xd0, 0x1f, 0xf1, 0xb5, 0x48, 0x41, 0xf4, 0x77, 0xfc, 0xee, 0x07, 0x8f, + 0xa0, 0x30, 0xf3, 0x31, 0x0e, 0x2a, 0x40, 0xe6, 0xe9, 0x6e, 0x7b, 0x7f, 0xbb, 0xd9, 0xfa, 0xb8, + 0xb5, 0xfd, 0xa8, 0xf8, 0x1a, 0x02, 0x48, 0xb4, 0x5b, 0xbb, 0x8f, 0x9f, 0x6c, 0x17, 0x15, 0x94, + 0x86, 0xf8, 0xce, 0xd3, 0x27, 0x9d, 0x56, 0x51, 0xf5, 0x1e, 0x3b, 0xcf, 0xf6, 0xf6, 0x9b, 0x45, + 0xed, 0xc1, 0x87, 0x90, 0x11, 0x75, 0xe1, 0x9e, 0xdb, 0x23, 0xae, 0x37, 0x60, 0x77, 0x0f, 0xef, + 0x6c, 0x3e, 0x29, 0xbe, 0x86, 0x92, 0xa0, 0xed, 0x63, 0x6f, 0x64, 0x0a, 0x62, 0xfb, 0x7b, 0xed, + 0x4e, 0x51, 0x45, 0x79, 0x80, 0xcd, 0xa7, 0x9d, 0xbd, 0xe6, 0xde, 0xce, 0x4e, 0xab, 0x53, 0xd4, + 0xb6, 0x3e, 0x80, 0x82, 0xe5, 0xd4, 0x27, 0x16, 0x23, 0x94, 0x8a, 0xcf, 0xa9, 0x7e, 0xf4, 0x96, + 0x6c, 0x59, 0xce, 0x86, 0x78, 0xda, 0xe8, 0x3b, 0x1b, 0x13, 0xb6, 0xc1, 0xa5, 0x1b, 0x22, 0x41, + 0x1c, 0x26, 0x78, 0xeb, 0xfd, 0xaf, 0x02, 0x00, 0x00, 0xff, 0xff, 0x4b, 0x03, 0xdd, 0xba, 0xce, + 0x25, 0x00, 0x00, } diff --git a/go/vt/proto/vttime/time.pb.go b/go/vt/proto/vttime/vttime.pb.go similarity index 87% rename from go/vt/proto/vttime/time.pb.go rename to go/vt/proto/vttime/vttime.pb.go index 449cd23197b..95c6f63de33 100644 --- a/go/vt/proto/vttime/time.pb.go +++ b/go/vt/proto/vttime/vttime.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: time.proto +// source: vttime.proto package vttime @@ -35,7 +35,7 @@ func (m *Time) Reset() { *m = Time{} } func (m *Time) String() string { return proto.CompactTextString(m) } func (*Time) ProtoMessage() {} func (*Time) Descriptor() ([]byte, []int) { - return fileDescriptor_49a92d779a28c7fd, []int{0} + return fileDescriptor_bbeb0d3434911dee, []int{0} } func (m *Time) XXX_Unmarshal(b []byte) error { @@ -74,16 +74,16 @@ func init() { proto.RegisterType((*Time)(nil), "vttime.Time") } -func init() { proto.RegisterFile("time.proto", fileDescriptor_49a92d779a28c7fd) } +func init() { proto.RegisterFile("vttime.proto", fileDescriptor_bbeb0d3434911dee) } -var fileDescriptor_49a92d779a28c7fd = []byte{ +var fileDescriptor_bbeb0d3434911dee = []byte{ // 120 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2a, 0xc9, 0xcc, 0x4d, - 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2b, 0x2b, 0x01, 0xf1, 0x94, 0x9c, 0xb8, 0x58, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0x2b, 0x29, 0xc9, + 0xcc, 0x4d, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0xf0, 0x94, 0x9c, 0xb8, 0x58, 0x42, 0x32, 0x73, 0x53, 0x85, 0x24, 0xb8, 0xd8, 0x8b, 0x53, 0x93, 0xf3, 0xf3, 0x52, 0x8a, 0x25, 0x18, 0x15, 0x18, 0x35, 0x98, 0x83, 0x60, 0x5c, 0x21, 0x05, 0x2e, 0xee, 0xbc, 0xc4, 0xbc, 0x7c, 0x98, 0x2c, 0x93, 0x02, 0xa3, 0x06, 0x6b, 0x10, 0xb2, 0x90, 0x93, 0x6a, 0x94, 0x72, 0x59, 0x66, 0x49, 0x6a, 0x71, 0xb1, 0x5e, 0x66, 0xbe, 0x3e, 0x84, 0xa5, 0x9f, 0x9e, 0xaf, 0x5f, 0x56, 0xa2, 0x0f, 0xb6, 0x4b, 0x1f, 0x62, 0x55, 0x12, 0x1b, 0x98, 0x67, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, - 0xb4, 0x42, 0xf5, 0xf7, 0x87, 0x00, 0x00, 0x00, + 0x35, 0x46, 0xf4, 0x16, 0x89, 0x00, 0x00, 0x00, } diff --git a/go/vt/schemamanager/tablet_executor.go b/go/vt/schemamanager/tablet_executor.go index 865ce3cede8..652686398a1 100644 --- a/go/vt/schemamanager/tablet_executor.go +++ b/go/vt/schemamanager/tablet_executor.go @@ -101,7 +101,9 @@ func (exec *TabletExecutor) Validate(ctx context.Context, sqls []string) error { return fmt.Errorf("executor is closed") } - parsedDDLs, err := exec.parseDDLs(sqls) + // We ignore DATABASE-level DDLs here because detectBigSchemaChanges doesn't + // look at them anyway. + parsedDDLs, _, err := exec.parseDDLs(sqls) if err != nil { return err } @@ -114,23 +116,26 @@ func (exec *TabletExecutor) Validate(ctx context.Context, sqls []string) error { return err } -func (exec *TabletExecutor) parseDDLs(sqls []string) ([]*sqlparser.DDL, error) { - parsedDDLs := make([]*sqlparser.DDL, 0, len(sqls)) +func (exec *TabletExecutor) parseDDLs(sqls []string) ([]*sqlparser.DDL, []*sqlparser.DBDDL, error) { + parsedDDLs := make([]*sqlparser.DDL, 0) + parsedDBDDLs := make([]*sqlparser.DBDDL, 0) for _, sql := range sqls { stat, err := sqlparser.Parse(sql) if err != nil { - return nil, fmt.Errorf("failed to parse sql: %s, got error: %v", sql, err) + return nil, nil, fmt.Errorf("failed to parse sql: %s, got error: %v", sql, err) } - ddl, ok := stat.(*sqlparser.DDL) - if !ok { + switch ddl := stat.(type) { + case *sqlparser.DDL: + parsedDDLs = append(parsedDDLs, ddl) + case *sqlparser.DBDDL: + parsedDBDDLs = append(parsedDBDDLs, ddl) + default: if len(exec.tablets) != 1 { - return nil, fmt.Errorf("non-ddl statements can only be executed for single shard keyspaces: %s", sql) + return nil, nil, fmt.Errorf("non-ddl statements can only be executed for single shard keyspaces: %s", sql) } - continue } - parsedDDLs = append(parsedDDLs, ddl) } - return parsedDDLs, nil + return parsedDDLs, parsedDBDDLs, nil } // a schema change that satisfies any following condition is considered diff --git a/go/vt/schemamanager/tablet_executor_test.go b/go/vt/schemamanager/tablet_executor_test.go index 579f4bd794c..890a4c5bfb9 100644 --- a/go/vt/schemamanager/tablet_executor_test.go +++ b/go/vt/schemamanager/tablet_executor_test.go @@ -108,6 +108,8 @@ func TestTabletExecutorValidate(t *testing.T) { sqls := []string{ "ALTER TABLE test_table ADD COLUMN new_id bigint(20)", "CREATE TABLE test_table_02 (pk int)", + "ALTER DATABASE db_name DEFAULT CHARACTER SET = utf8mb4", + "ALTER SCHEMA db_name CHARACTER SET = utf8mb4", } if err := executor.Validate(ctx, sqls); err == nil { diff --git a/go/vt/servenv/buildinfo.go b/go/vt/servenv/buildinfo.go index 97834a794d8..cab58cf2555 100644 --- a/go/vt/servenv/buildinfo.go +++ b/go/vt/servenv/buildinfo.go @@ -96,4 +96,14 @@ func init() { stats.NewString("GoOS").Set(AppVersion.goOS) stats.NewString("GoArch").Set(AppVersion.goArch) + buildLabels := []string{"BuildHost", "BuildUser", "BuildTimestamp", "BuildGitRev", "BuildGitBranch", "BuildNumber"} + buildValues := []string{ + AppVersion.buildHost, + AppVersion.buildUser, + fmt.Sprintf("%v", AppVersion.buildTime), + AppVersion.buildGitRev, + AppVersion.buildGitBranch, + fmt.Sprintf("%v", AppVersion.jenkinsBuildNumber), + } + stats.NewGaugesWithMultiLabels("BuildInformation", "build information exposed via label", buildLabels).Set(buildValues, 1) } diff --git a/go/vt/servenv/grpc_server_auth_mtls.go b/go/vt/servenv/grpc_server_auth_mtls.go new file mode 100644 index 00000000000..817bc5bd0a9 --- /dev/null +++ b/go/vt/servenv/grpc_server_auth_mtls.go @@ -0,0 +1,77 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package servenv + +import ( + "flag" + "strings" + + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/peer" + + "golang.org/x/net/context" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "vitess.io/vitess/go/vt/log" +) + +var ( + // ClientCertSubstrings list of substrings of at least one of the client certificate names to use during authorization + ClientCertSubstrings = flag.String("grpc_auth_mtls_allowed_substrings", "", "List of substrings of at least one of the client certificate names (separated by colon).") + // MtlsAuthPlugin implements AuthPlugin interface + _ Authenticator = (*MtlsAuthPlugin)(nil) +) + +// MtlsAuthPlugin implements static username/password authentication for grpc. It contains an array of username/passwords +// that will be authorized to connect to the grpc server. +type MtlsAuthPlugin struct { + clientCertSubstrings []string +} + +// Authenticate implements Authenticator interface. This method will be used inside a middleware in grpc_server to authenticate +// incoming requests. +func (ma *MtlsAuthPlugin) Authenticate(ctx context.Context, fullMethod string) (context.Context, error) { + p, ok := peer.FromContext(ctx) + if !ok { + return nil, status.Errorf(codes.Unauthenticated, "no peer connection info") + } + tlsInfo, ok := p.AuthInfo.(credentials.TLSInfo) + if !ok { + return nil, status.Errorf(codes.Unauthenticated, "not connected via TLS") + } + for _, substring := range ma.clientCertSubstrings { + for _, cert := range tlsInfo.State.PeerCertificates { + if strings.Contains(cert.Subject.String(), substring) { + return ctx, nil + } + } + } + return nil, status.Errorf(codes.Unauthenticated, "client certificate not authorized") +} + +func mtlsAuthPluginInitializer() (Authenticator, error) { + mtlsAuthPlugin := &MtlsAuthPlugin{ + clientCertSubstrings: strings.Split(*ClientCertSubstrings, ":"), + } + log.Infof("mtls auth plugin have initialized successfully with allowed client cert name substrings of %v", *ClientCertSubstrings) + return mtlsAuthPlugin, nil +} + +func init() { + RegisterAuthPlugin("mtls", mtlsAuthPluginInitializer) +} diff --git a/go/vt/servenv/status.go b/go/vt/servenv/status.go index f391bf470a6..c9fdbfb3fd3 100644 --- a/go/vt/servenv/status.go +++ b/go/vt/servenv/status.go @@ -104,6 +104,7 @@ Started: {{.StartTime}}
Running on {{.Hostname}}
View
variables, debugging profiles, + scatter query statistics, ` diff --git a/go/vt/sqlparser/analyzer.go b/go/vt/sqlparser/analyzer.go index 534903e9a71..3d78e3e993d 100644 --- a/go/vt/sqlparser/analyzer.go +++ b/go/vt/sqlparser/analyzer.go @@ -52,6 +52,7 @@ const ( StmtOther StmtUnknown StmtComment + StmtPriv ) // Preview analyzes the beginning of the query using a simpler and faster @@ -110,6 +111,8 @@ func Preview(sql string) StatementType { return StmtUse case "analyze", "describe", "desc", "explain", "repair", "optimize": return StmtOther + case "grant", "revoke": + return StmtPriv } return StmtUnknown } @@ -144,6 +147,8 @@ func (s StatementType) String() string { return "USE" case StmtOther: return "OTHER" + case StmtPriv: + return "PRIV" default: return "UNKNOWN" } @@ -175,6 +180,31 @@ func SplitAndExpression(filters []Expr, node Expr) []Expr { return append(filters, node) } +// TableFromStatement returns the qualified table name for the query. +// This works only for select statements. +func TableFromStatement(sql string) (TableName, error) { + stmt, err := Parse(sql) + if err != nil { + return TableName{}, err + } + sel, ok := stmt.(*Select) + if !ok { + return TableName{}, fmt.Errorf("unrecognized statement: %s", sql) + } + if len(sel.From) != 1 { + return TableName{}, fmt.Errorf("table expression is complex") + } + aliased, ok := sel.From[0].(*AliasedTableExpr) + if !ok { + return TableName{}, fmt.Errorf("table expression is complex") + } + tableName, ok := aliased.Expr.(TableName) + if !ok { + return TableName{}, fmt.Errorf("table expression is complex") + } + return tableName, nil +} + // GetTableName returns the table name from the SimpleTableExpr // only if it's a simple expression. Otherwise, it returns "". func GetTableName(node SimpleTableExpr) TableIdent { diff --git a/go/vt/sqlparser/analyzer_test.go b/go/vt/sqlparser/analyzer_test.go index 8ecc3ce0dba..062a3e3b66b 100644 --- a/go/vt/sqlparser/analyzer_test.go +++ b/go/vt/sqlparser/analyzer_test.go @@ -50,6 +50,9 @@ func TestPreview(t *testing.T) { {"begin ...", StmtUnknown}, {"begin /* ... */", StmtBegin}, {"begin /* ... *//*test*/", StmtBegin}, + {"begin;", StmtBegin}, + {"begin ;", StmtBegin}, + {"begin; /*...*/", StmtBegin}, {"start transaction", StmtBegin}, {"commit", StmtCommit}, {"commit /*...*/", StmtCommit}, @@ -68,6 +71,8 @@ func TestPreview(t *testing.T) { {"explain", StmtOther}, {"repair", StmtOther}, {"optimize", StmtOther}, + {"grant", StmtPriv}, + {"revoke", StmtPriv}, {"truncate", StmtDDL}, {"unknown", StmtUnknown}, @@ -157,6 +162,49 @@ func TestSplitAndExpression(t *testing.T) { } } +func TestTableFromStatement(t *testing.T) { + testcases := []struct { + in, out string + }{{ + in: "select * from t", + out: "t", + }, { + in: "select * from t.t", + out: "t.t", + }, { + in: "select * from t1, t2", + out: "table expression is complex", + }, { + in: "select * from (t)", + out: "table expression is complex", + }, { + in: "select * from t1 join t2", + out: "table expression is complex", + }, { + in: "select * from (select * from t) as tt", + out: "table expression is complex", + }, { + in: "update t set a=1", + out: "unrecognized statement: update t set a=1", + }, { + in: "bad query", + out: "syntax error at position 4 near 'bad'", + }} + + for _, tc := range testcases { + name, err := TableFromStatement(tc.in) + var got string + if err != nil { + got = err.Error() + } else { + got = String(name) + } + if got != tc.out { + t.Errorf("TableFromStatement('%s'): %s, want %s", tc.in, got, tc.out) + } + } +} + func TestGetTableName(t *testing.T) { testcases := []struct { in, out string @@ -519,6 +567,14 @@ func TestExtractSetValues(t *testing.T) { sql: "set session sql_safe_updates = 0", out: map[SetKey]interface{}{{Key: "sql_safe_updates", Scope: ImplicitStr}: int64(0)}, scope: SessionStr, + }, { + sql: "set session transaction_read_only = 0", + out: map[SetKey]interface{}{{Key: "transaction_read_only", Scope: ImplicitStr}: int64(0)}, + scope: SessionStr, + }, { + sql: "set session transaction_read_only = 1", + out: map[SetKey]interface{}{{Key: "transaction_read_only", Scope: ImplicitStr}: int64(1)}, + scope: SessionStr, }, { sql: "set session sql_safe_updates = 1", out: map[SetKey]interface{}{{Key: "sql_safe_updates", Scope: ImplicitStr}: int64(1)}, diff --git a/go/vt/sqlparser/ast.go b/go/vt/sqlparser/ast.go index cb74aff4f2a..f99edf0495d 100644 --- a/go/vt/sqlparser/ast.go +++ b/go/vt/sqlparser/ast.go @@ -17,470 +17,813 @@ limitations under the License. package sqlparser import ( - "encoding/hex" - "encoding/json" - "errors" "fmt" - "io" "strings" - "sync" "vitess.io/vitess/go/sqltypes" - "vitess.io/vitess/go/vt/log" - "vitess.io/vitess/go/vt/vterrors" - - querypb "vitess.io/vitess/go/vt/proto/query" - vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" ) -// parserPool is a pool for parser objects. -var parserPool = sync.Pool{} - -// zeroParser is a zero-initialized parser to help reinitialize the parser for pooling. -var zeroParser = *(yyNewParser().(*yyParserImpl)) - -// yyParsePooled is a wrapper around yyParse that pools the parser objects. There isn't a -// particularly good reason to use yyParse directly, since it immediately discards its parser. What -// would be ideal down the line is to actually pool the stacks themselves rather than the parser -// objects, as per https://github.com/cznic/goyacc/blob/master/main.go. However, absent an upstream -// change to goyacc, this is the next best option. -// -// N.B: Parser pooling means that you CANNOT take references directly to parse stack variables (e.g. -// $$ = &$4) in sql.y rules. You must instead add an intermediate reference like so: -// showCollationFilterOpt := $4 -// $$ = &Show{Type: string($2), ShowCollationFilterOpt: &showCollationFilterOpt} -func yyParsePooled(yylex yyLexer) int { - // Being very particular about using the base type and not an interface type b/c we depend on - // the implementation to know how to reinitialize the parser. - var parser *yyParserImpl - - i := parserPool.Get() - if i != nil { - parser = i.(*yyParserImpl) - } else { - parser = yyNewParser().(*yyParserImpl) - } - - defer func() { - *parser = zeroParser - parserPool.Put(parser) - }() - return parser.Parse(yylex) -} - -// Instructions for creating new types: If a type -// needs to satisfy an interface, declare that function -// along with that interface. This will help users -// identify the list of types to which they can assert -// those interfaces. -// If the member of a type has a string with a predefined -// list of values, declare those values as const following -// the type. -// For interfaces that define dummy functions to consolidate -// a set of types, define the function as iTypeName. -// This will help avoid name collisions. - -// Parse parses the SQL in full and returns a Statement, which -// is the AST representation of the query. If a DDL statement -// is partially parsed but still contains a syntax error, the -// error is ignored and the DDL is returned anyway. -func Parse(sql string) (Statement, error) { - tokenizer := NewStringTokenizer(sql) - if yyParsePooled(tokenizer) != 0 { - if tokenizer.partialDDL != nil { - if typ, val := tokenizer.Scan(); typ != 0 { - return nil, fmt.Errorf("extra characters encountered after end of DDL: '%s'", string(val)) - } - log.Warningf("ignoring error parsing DDL '%s': %v", sql, tokenizer.LastError) - tokenizer.ParseTree = tokenizer.partialDDL - return tokenizer.ParseTree, nil - } - return nil, vterrors.New(vtrpcpb.Code_INVALID_ARGUMENT, tokenizer.LastError.Error()) - } - if tokenizer.ParseTree == nil { - return nil, ErrEmpty - } - return tokenizer.ParseTree, nil +/* +This is the Vitess AST. This file should only contain pure struct declarations, +or methods used to mark a struct as implementing an interface. All other methods +related to these structs live in ast_funcs.go +*/ + +// SQLNode defines the interface for all nodes +// generated by the parser. +type SQLNode interface { + Format(buf *TrackedBuffer) } -// ParseStrictDDL is the same as Parse except it errors on -// partially parsed DDL statements. -func ParseStrictDDL(sql string) (Statement, error) { - tokenizer := NewStringTokenizer(sql) - if yyParsePooled(tokenizer) != 0 { - return nil, tokenizer.LastError - } - if tokenizer.ParseTree == nil { - return nil, ErrEmpty - } - return tokenizer.ParseTree, nil +// Statements +type ( + // Statement represents a statement. + Statement interface { + iStatement() + SQLNode + } + + // SelectStatement any SELECT statement. + SelectStatement interface { + iSelectStatement() + iStatement() + iInsertRows() + AddOrder(*Order) + SetLimit(*Limit) + SQLNode + } + + // Select represents a SELECT statement. + Select struct { + Cache string + Comments Comments + Distinct string + Hints string + SelectExprs SelectExprs + From TableExprs + Where *Where + GroupBy GroupBy + Having *Where + OrderBy OrderBy + Limit *Limit + Lock string + } + + // Union represents a UNION statement. + Union struct { + Type string + Left, Right SelectStatement + OrderBy OrderBy + Limit *Limit + Lock string + } + + // Stream represents a SELECT statement. + Stream struct { + Comments Comments + SelectExpr SelectExpr + Table TableName + } + + // Insert represents an INSERT or REPLACE statement. + // Per the MySQL docs, http://dev.mysql.com/doc/refman/5.7/en/replace.html + // Replace is the counterpart to `INSERT IGNORE`, and works exactly like a + // normal INSERT except if the row exists. In that case it first deletes + // the row and re-inserts with new values. For that reason we keep it as an Insert struct. + // Replaces are currently disallowed in sharded schemas because + // of the implications the deletion part may have on vindexes. + // If you add fields here, consider adding them to calls to validateUnshardedRoute. + Insert struct { + Action string + Comments Comments + Ignore string + Table TableName + Partitions Partitions + Columns Columns + Rows InsertRows + OnDup OnDup + } + + // Update represents an UPDATE statement. + // If you add fields here, consider adding them to calls to validateUnshardedRoute. + Update struct { + Comments Comments + Ignore string + TableExprs TableExprs + Exprs UpdateExprs + Where *Where + OrderBy OrderBy + Limit *Limit + } + + // Delete represents a DELETE statement. + // If you add fields here, consider adding them to calls to validateUnshardedRoute. + Delete struct { + Comments Comments + Targets TableNames + TableExprs TableExprs + Partitions Partitions + Where *Where + OrderBy OrderBy + Limit *Limit + } + + // Set represents a SET statement. + Set struct { + Comments Comments + Exprs SetExprs + Scope string + } + + // DBDDL represents a CREATE, DROP, or ALTER database statement. + DBDDL struct { + Action string + DBName string + IfExists bool + Collate string + Charset string + } + + // DDL represents a CREATE, ALTER, DROP, RENAME, TRUNCATE or ANALYZE statement. + DDL struct { + Action string + + // FromTables is set if Action is RenameStr or DropStr. + FromTables TableNames + + // ToTables is set if Action is RenameStr. + ToTables TableNames + + // Table is set if Action is other than RenameStr or DropStr. + Table TableName + + // The following fields are set if a DDL was fully analyzed. + IfExists bool + TableSpec *TableSpec + OptLike *OptLike + PartitionSpec *PartitionSpec + + // VindexSpec is set for CreateVindexStr, DropVindexStr, AddColVindexStr, DropColVindexStr. + VindexSpec *VindexSpec + + // VindexCols is set for AddColVindexStr. + VindexCols []ColIdent + + // AutoIncSpec is set for AddAutoIncStr. + AutoIncSpec *AutoIncSpec + } + + // ParenSelect is a parenthesized SELECT statement. + ParenSelect struct { + Select SelectStatement + } + + // Show represents a show statement. + Show struct { + Type string + OnTable TableName + Table TableName + ShowTablesOpt *ShowTablesOpt + Scope string + ShowCollationFilterOpt *Expr // TODO: this should not be a pointer + } + + // Use represents a use statement. + Use struct { + DBName TableIdent + } + + // Begin represents a Begin statement. + Begin struct{} + + // Commit represents a Commit statement. + Commit struct{} + + // Rollback represents a Rollback statement. + Rollback struct{} + + // OtherRead represents a DESCRIBE, or EXPLAIN statement. + // It should be used only as an indicator. It does not contain + // the full AST for the statement. + OtherRead struct{} + + // OtherAdmin represents a misc statement that relies on ADMIN privileges, + // such as REPAIR, OPTIMIZE, or TRUNCATE statement. + // It should be used only as an indicator. It does not contain + // the full AST for the statement. + OtherAdmin struct{} +) + +func (*Union) iStatement() {} +func (*Select) iStatement() {} +func (*Stream) iStatement() {} +func (*Insert) iStatement() {} +func (*Update) iStatement() {} +func (*Delete) iStatement() {} +func (*Set) iStatement() {} +func (*DBDDL) iStatement() {} +func (*DDL) iStatement() {} +func (*Show) iStatement() {} +func (*Use) iStatement() {} +func (*Begin) iStatement() {} +func (*Commit) iStatement() {} +func (*Rollback) iStatement() {} +func (*OtherRead) iStatement() {} +func (*OtherAdmin) iStatement() {} +func (*Select) iSelectStatement() {} +func (*Union) iSelectStatement() {} +func (*ParenSelect) iSelectStatement() {} + +// ParenSelect can actually not be a top level statement, +// but we have to allow it because it's a requirement +// of SelectStatement. +func (*ParenSelect) iStatement() {} + +// InsertRows represents the rows for an INSERT statement. +type InsertRows interface { + iInsertRows() + SQLNode } -// ParseTokenizer is a raw interface to parse from the given tokenizer. -// This does not used pooled parsers, and should not be used in general. -func ParseTokenizer(tokenizer *Tokenizer) int { - return yyParse(tokenizer) +func (*Select) iInsertRows() {} +func (*Union) iInsertRows() {} +func (Values) iInsertRows() {} +func (*ParenSelect) iInsertRows() {} + +// OptLike works for create table xxx like xxx +type OptLike struct { + LikeTable TableName } -// ParseNext parses a single SQL statement from the tokenizer -// returning a Statement which is the AST representation of the query. -// The tokenizer will always read up to the end of the statement, allowing for -// the next call to ParseNext to parse any subsequent SQL statements. When -// there are no more statements to parse, a error of io.EOF is returned. -func ParseNext(tokenizer *Tokenizer) (Statement, error) { - return parseNext(tokenizer, false) +// PartitionSpec describe partition actions (for alter and create) +type PartitionSpec struct { + Action string + Name ColIdent + Definitions []*PartitionDefinition } -// ParseNextStrictDDL is the same as ParseNext except it errors on -// partially parsed DDL statements. -func ParseNextStrictDDL(tokenizer *Tokenizer) (Statement, error) { - return parseNext(tokenizer, true) +// PartitionDefinition describes a very minimal partition definition +type PartitionDefinition struct { + Name ColIdent + Limit Expr + Maxvalue bool } -func parseNext(tokenizer *Tokenizer, strict bool) (Statement, error) { - if tokenizer.lastChar == ';' { - tokenizer.next() - tokenizer.skipBlank() - } - if tokenizer.lastChar == eofChar { - return nil, io.EOF - } +// TableSpec describes the structure of a table from a CREATE TABLE statement +type TableSpec struct { + Columns []*ColumnDefinition + Indexes []*IndexDefinition + Constraints []*ConstraintDefinition + Options string +} - tokenizer.reset() - tokenizer.multi = true - if yyParsePooled(tokenizer) != 0 { - if tokenizer.partialDDL != nil && !strict { - tokenizer.ParseTree = tokenizer.partialDDL - return tokenizer.ParseTree, nil - } - return nil, tokenizer.LastError - } - if tokenizer.ParseTree == nil { - return ParseNext(tokenizer) - } - return tokenizer.ParseTree, nil +// ColumnDefinition describes a column in a CREATE TABLE statement +type ColumnDefinition struct { + Name ColIdent + // TODO: Should this not be a reference? + Type ColumnType } -// ErrEmpty is a sentinel error returned when parsing empty statements. -var ErrEmpty = errors.New("empty statement") +// ColumnType represents a sql type in a CREATE TABLE statement +// All optional fields are nil if not specified +type ColumnType struct { + // The base type string + Type string -// SplitStatement returns the first sql statement up to either a ; or EOF -// and the remainder from the given buffer -func SplitStatement(blob string) (string, string, error) { - tokenizer := NewStringTokenizer(blob) - tkn := 0 - for { - tkn, _ = tokenizer.Scan() - if tkn == 0 || tkn == ';' || tkn == eofChar { - break - } - } - if tokenizer.LastError != nil { - return "", "", tokenizer.LastError - } - if tkn == ';' { - return blob[:tokenizer.Position-2], blob[tokenizer.Position-1:], nil - } - return blob, "", nil -} + // Generic field options. + NotNull BoolVal + Autoincrement BoolVal + Default Expr + OnUpdate Expr + Comment *SQLVal -// SplitStatementToPieces split raw sql statement that may have multi sql pieces to sql pieces -// returns the sql pieces blob contains; or error if sql cannot be parsed -func SplitStatementToPieces(blob string) (pieces []string, err error) { - pieces = make([]string, 0, 16) - tokenizer := NewStringTokenizer(blob) + // Numeric field options + Length *SQLVal + Unsigned BoolVal + Zerofill BoolVal + Scale *SQLVal - tkn := 0 - var stmt string - stmtBegin := 0 - for { - tkn, _ = tokenizer.Scan() - if tkn == ';' { - stmt = blob[stmtBegin : tokenizer.Position-2] - pieces = append(pieces, stmt) - stmtBegin = tokenizer.Position - 1 + // Text field options + Charset string + Collate string - } else if tkn == 0 || tkn == eofChar { - blobTail := tokenizer.Position - 2 + // Enum values + EnumValues []string - if stmtBegin < blobTail { - stmt = blob[stmtBegin : blobTail+1] - pieces = append(pieces, stmt) - } - break - } - } + // Key specification + KeyOpt ColumnKeyOption +} - err = tokenizer.LastError - return +// IndexDefinition describes an index in a CREATE TABLE statement +type IndexDefinition struct { + Info *IndexInfo + Columns []*IndexColumn + Options []*IndexOption } -// SQLNode defines the interface for all nodes -// generated by the parser. -type SQLNode interface { - Format(buf *TrackedBuffer) - // walkSubtree calls visit on all underlying nodes - // of the subtree, but not the current one. Walking - // must be interrupted if visit returns an error. - walkSubtree(visit Visit) error -} - -// Visit defines the signature of a function that -// can be used to visit all nodes of a parse tree. -type Visit func(node SQLNode) (kontinue bool, err error) - -// Walk calls visit on every node. -// If visit returns true, the underlying nodes -// are also visited. If it returns an error, walking -// is interrupted, and the error is returned. -func Walk(visit Visit, nodes ...SQLNode) error { - for _, node := range nodes { - if node == nil { - continue - } - kontinue, err := visit(node) - if err != nil { - return err - } - if kontinue { - err = node.walkSubtree(visit) - if err != nil { - return err - } - } - } - return nil +// IndexInfo describes the name and type of an index in a CREATE TABLE statement +type IndexInfo struct { + Type string + Name ColIdent + Primary bool + Spatial bool + Unique bool } -// String returns a string representation of an SQLNode. -func String(node SQLNode) string { - if node == nil { - return "" - } +// VindexSpec defines a vindex for a CREATE VINDEX or DROP VINDEX statement +type VindexSpec struct { + Name ColIdent + Type ColIdent + Params []VindexParam +} - buf := NewTrackedBuffer(nil) - buf.Myprintf("%v", node) - return buf.String() +// AutoIncSpec defines and autoincrement value for a ADD AUTO_INCREMENT statement +type AutoIncSpec struct { + Column ColIdent + Sequence TableName } -// Append appends the SQLNode to the buffer. -func Append(buf *strings.Builder, node SQLNode) { - tbuf := &TrackedBuffer{ - Builder: buf, - } - node.Format(tbuf) +// VindexParam defines a key/value parameter for a CREATE VINDEX statement +type VindexParam struct { + Key ColIdent + Val string } -// Statement represents a statement. -type Statement interface { - iStatement() - SQLNode +// ConstraintDefinition describes a constraint in a CREATE TABLE statement +type ConstraintDefinition struct { + Name string + Details ConstraintInfo } -func (*Union) iStatement() {} -func (*Select) iStatement() {} -func (*Stream) iStatement() {} -func (*Insert) iStatement() {} -func (*Update) iStatement() {} -func (*Delete) iStatement() {} -func (*Set) iStatement() {} -func (*DBDDL) iStatement() {} -func (*DDL) iStatement() {} -func (*Show) iStatement() {} -func (*Use) iStatement() {} -func (*Begin) iStatement() {} -func (*Commit) iStatement() {} -func (*Rollback) iStatement() {} -func (*OtherRead) iStatement() {} -func (*OtherAdmin) iStatement() {} +type ( + // ConstraintInfo details a constraint in a CREATE TABLE statement + ConstraintInfo interface { + SQLNode + iConstraintInfo() + } -// ParenSelect can actually not be a top level statement, -// but we have to allow it because it's a requirement -// of SelectStatement. -func (*ParenSelect) iStatement() {} + // ForeignKeyDefinition describes a foreign key in a CREATE TABLE statement + ForeignKeyDefinition struct { + Source Columns + ReferencedTable TableName + ReferencedColumns Columns + OnDelete ReferenceAction + OnUpdate ReferenceAction + } +) -// SelectStatement any SELECT statement. -type SelectStatement interface { - iSelectStatement() - iStatement() - iInsertRows() - AddOrder(*Order) - SetLimit(*Limit) - SQLNode +// ShowFilter is show tables filter +type ShowFilter struct { + Like string + Filter Expr } -func (*Select) iSelectStatement() {} -func (*Union) iSelectStatement() {} -func (*ParenSelect) iSelectStatement() {} +// Comments represents a list of comments. +type Comments [][]byte -// Select represents a SELECT statement. -type Select struct { - Cache string - Comments Comments - Distinct string - Hints string - SelectExprs SelectExprs - From TableExprs - Where *Where - GroupBy GroupBy - Having *Where - OrderBy OrderBy - Limit *Limit - Lock string -} - -// Select.Distinct -const ( - DistinctStr = "distinct " - StraightJoinHint = "straight_join " +// SelectExprs represents SELECT expressions. +type SelectExprs []SelectExpr + +type ( + // SelectExpr represents a SELECT expression. + SelectExpr interface { + iSelectExpr() + SQLNode + } + + // StarExpr defines a '*' or 'table.*' expression. + StarExpr struct { + TableName TableName + } + + // AliasedExpr defines an aliased SELECT expression. + AliasedExpr struct { + Expr Expr + As ColIdent + } + + // Nextval defines the NEXT VALUE expression. + Nextval struct { + Expr Expr + } ) -// Select.Lock -const ( - ForUpdateStr = " for update" - ShareModeStr = " lock in share mode" +func (*StarExpr) iSelectExpr() {} +func (*AliasedExpr) iSelectExpr() {} +func (Nextval) iSelectExpr() {} + +// Columns represents an insert column list. +type Columns []ColIdent + +// Partitions is a type alias for Columns so we can handle printing efficiently +type Partitions Columns + +// TableExprs represents a list of table expressions. +type TableExprs []TableExpr + +type ( + // TableExpr represents a table expression. + TableExpr interface { + iTableExpr() + SQLNode + } + + // AliasedTableExpr represents a table expression + // coupled with an optional alias or index hint. + // If As is empty, no alias was used. + AliasedTableExpr struct { + Expr SimpleTableExpr + Partitions Partitions + As TableIdent + Hints *IndexHints + } + + // JoinTableExpr represents a TableExpr that's a JOIN operation. + JoinTableExpr struct { + LeftExpr TableExpr + Join string + RightExpr TableExpr + Condition JoinCondition + } + + // ParenTableExpr represents a parenthesized list of TableExpr. + ParenTableExpr struct { + Exprs TableExprs + } ) -// Select.Cache -const ( - SQLCacheStr = "sql_cache " - SQLNoCacheStr = "sql_no_cache " +func (*AliasedTableExpr) iTableExpr() {} +func (*ParenTableExpr) iTableExpr() {} +func (*JoinTableExpr) iTableExpr() {} + +type ( + // SimpleTableExpr represents a simple table expression. + SimpleTableExpr interface { + iSimpleTableExpr() + SQLNode + } + + // TableName represents a table name. + // Qualifier, if specified, represents a database or keyspace. + // TableName is a value struct whose fields are case sensitive. + // This means two TableName vars can be compared for equality + // and a TableName can also be used as key in a map. + TableName struct { + Name, Qualifier TableIdent + } + + // Subquery represents a subquery. + Subquery struct { + Select SelectStatement + } ) -// AddOrder adds an order by element -func (node *Select) AddOrder(order *Order) { - node.OrderBy = append(node.OrderBy, order) +func (TableName) iSimpleTableExpr() {} +func (*Subquery) iSimpleTableExpr() {} + +// TableNames is a list of TableName. +type TableNames []TableName + +// JoinCondition represents the join conditions (either a ON or USING clause) +// of a JoinTableExpr. +type JoinCondition struct { + On Expr + Using Columns } -// SetLimit sets the limit clause -func (node *Select) SetLimit(limit *Limit) { - node.Limit = limit +// IndexHints represents a list of index hints. +type IndexHints struct { + Type string + Indexes []ColIdent } -// Format formats the node. -func (node *Select) Format(buf *TrackedBuffer) { - buf.Myprintf("select %v%s%s%s%v from %v%v%v%v%v%v%s", - node.Comments, node.Cache, node.Distinct, node.Hints, node.SelectExprs, - node.From, node.Where, - node.GroupBy, node.Having, node.OrderBy, - node.Limit, node.Lock) +// Where represents a WHERE or HAVING clause. +type Where struct { + Type string + Expr Expr } -func (node *Select) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Comments, - node.SelectExprs, - node.From, - node.Where, - node.GroupBy, - node.Having, - node.OrderBy, - node.Limit, - ) -} - -// AddWhere adds the boolean expression to the -// WHERE clause as an AND condition. If the expression -// is an OR clause, it parenthesizes it. Currently, -// the OR operator is the only one that's lower precedence -// than AND. -func (node *Select) AddWhere(expr Expr) { - if _, ok := expr.(*OrExpr); ok { - expr = &ParenExpr{Expr: expr} - } - if node.Where == nil { - node.Where = &Where{ - Type: WhereStr, - Expr: expr, - } - return +// *********** Expressions +type ( + // Expr represents an expression. + Expr interface { + iExpr() + SQLNode } - node.Where.Expr = &AndExpr{ - Left: node.Where.Expr, - Right: expr, + + // AndExpr represents an AND expression. + AndExpr struct { + Left, Right Expr } -} -// AddHaving adds the boolean expression to the -// HAVING clause as an AND condition. If the expression -// is an OR clause, it parenthesizes it. Currently, -// the OR operator is the only one that's lower precedence -// than AND. -func (node *Select) AddHaving(expr Expr) { - if _, ok := expr.(*OrExpr); ok { - expr = &ParenExpr{Expr: expr} + // OrExpr represents an OR expression. + OrExpr struct { + Left, Right Expr } - if node.Having == nil { - node.Having = &Where{ - Type: HavingStr, - Expr: expr, - } - return + + // NotExpr represents a NOT expression. + NotExpr struct { + Expr Expr } - node.Having.Expr = &AndExpr{ - Left: node.Having.Expr, - Right: expr, + + // ParenExpr represents a parenthesized boolean expression. + ParenExpr struct { + Expr Expr + } + + // ComparisonExpr represents a two-value comparison expression. + ComparisonExpr struct { + Operator string + Left, Right Expr + Escape Expr + } + + // RangeCond represents a BETWEEN or a NOT BETWEEN expression. + RangeCond struct { + Operator string + Left Expr + From, To Expr + } + + // IsExpr represents an IS ... or an IS NOT ... expression. + IsExpr struct { + Operator string + Expr Expr + } + + // ExistsExpr represents an EXISTS expression. + ExistsExpr struct { + Subquery *Subquery + } + + // SQLVal represents a single value. + SQLVal struct { + Type ValType + Val []byte + } + + // NullVal represents a NULL value. + NullVal struct{} + + // BoolVal is true or false. + BoolVal bool + + // ColName represents a column name. + ColName struct { + // Metadata is not populated by the parser. + // It's a placeholder for analyzers to store + // additional data, typically info about which + // table or column this node references. + Metadata interface{} + Name ColIdent + Qualifier TableName } + + // ColTuple represents a list of column values. + // It can be ValTuple, Subquery, ListArg. + ColTuple interface { + iColTuple() + Expr + } + + // ListArg represents a named list argument. + ListArg []byte + + // ValTuple represents a tuple of actual values. + ValTuple Exprs + + // BinaryExpr represents a binary value expression. + BinaryExpr struct { + Operator string + Left, Right Expr + } + + // UnaryExpr represents a unary value expression. + UnaryExpr struct { + Operator string + Expr Expr + } + + // IntervalExpr represents a date-time INTERVAL expression. + IntervalExpr struct { + Expr Expr + Unit string + } + + // TimestampFuncExpr represents the function and arguments for TIMESTAMP{ADD,DIFF} functions. + TimestampFuncExpr struct { + Name string + Expr1 Expr + Expr2 Expr + Unit string + } + + // CollateExpr represents dynamic collate operator. + CollateExpr struct { + Expr Expr + Charset string + } + + // FuncExpr represents a function call. + FuncExpr struct { + Qualifier TableIdent + Name ColIdent + Distinct bool + Exprs SelectExprs + } + + // GroupConcatExpr represents a call to GROUP_CONCAT + GroupConcatExpr struct { + Distinct string + Exprs SelectExprs + OrderBy OrderBy + Separator string + Limit *Limit + } + + // ValuesFuncExpr represents a function call. + ValuesFuncExpr struct { + Name *ColName + } + + // SubstrExpr represents a call to SubstrExpr(column, value_expression) or SubstrExpr(column, value_expression,value_expression) + // also supported syntax SubstrExpr(column from value_expression for value_expression). + // Additionally to column names, SubstrExpr is also supported for string values, e.g.: + // SubstrExpr('static string value', value_expression, value_expression) + // In this case StrVal will be set instead of Name. + SubstrExpr struct { + Name *ColName + StrVal *SQLVal + From Expr + To Expr + } + + // ConvertExpr represents a call to CONVERT(expr, type) + // or it's equivalent CAST(expr AS type). Both are rewritten to the former. + ConvertExpr struct { + Expr Expr + Type *ConvertType + } + + // ConvertUsingExpr represents a call to CONVERT(expr USING charset). + ConvertUsingExpr struct { + Expr Expr + Type string + } + + // MatchExpr represents a call to the MATCH function + MatchExpr struct { + Columns SelectExprs + Expr Expr + Option string + } + + // CaseExpr represents a CASE expression. + CaseExpr struct { + Expr Expr + Whens []*When + Else Expr + } + + // Default represents a DEFAULT expression. + Default struct { + ColName string + } + + // When represents a WHEN sub-expression. + When struct { + Cond Expr + Val Expr + } + + // CurTimeFuncExpr represents the function and arguments for CURRENT DATE/TIME functions + // supported functions are documented in the grammar + CurTimeFuncExpr struct { + Name ColIdent + Fsp Expr // fractional seconds precision, integer from 0 to 6 + } +) + +// iExpr ensures that only expressions nodes can be assigned to a Expr +func (*AndExpr) iExpr() {} +func (*OrExpr) iExpr() {} +func (*NotExpr) iExpr() {} +func (*ParenExpr) iExpr() {} +func (*ComparisonExpr) iExpr() {} +func (*RangeCond) iExpr() {} +func (*IsExpr) iExpr() {} +func (*ExistsExpr) iExpr() {} +func (*SQLVal) iExpr() {} +func (*NullVal) iExpr() {} +func (BoolVal) iExpr() {} +func (*ColName) iExpr() {} +func (ValTuple) iExpr() {} +func (*Subquery) iExpr() {} +func (ListArg) iExpr() {} +func (*BinaryExpr) iExpr() {} +func (*UnaryExpr) iExpr() {} +func (*IntervalExpr) iExpr() {} +func (*CollateExpr) iExpr() {} +func (*FuncExpr) iExpr() {} +func (*TimestampFuncExpr) iExpr() {} +func (*CurTimeFuncExpr) iExpr() {} +func (*CaseExpr) iExpr() {} +func (*ValuesFuncExpr) iExpr() {} +func (*ConvertExpr) iExpr() {} +func (*SubstrExpr) iExpr() {} +func (*ConvertUsingExpr) iExpr() {} +func (*MatchExpr) iExpr() {} +func (*GroupConcatExpr) iExpr() {} +func (*Default) iExpr() {} + +// Exprs represents a list of value expressions. +// It's not a valid expression because it's not parenthesized. +type Exprs []Expr + +func (ValTuple) iColTuple() {} +func (*Subquery) iColTuple() {} +func (ListArg) iColTuple() {} + +// ConvertType represents the type in call to CONVERT(expr, type) +type ConvertType struct { + Type string + Length *SQLVal + Scale *SQLVal + Operator string + Charset string } -// ParenSelect is a parenthesized SELECT statement. -type ParenSelect struct { - Select SelectStatement +// GroupBy represents a GROUP BY clause. +type GroupBy []Expr + +// OrderBy represents an ORDER By clause. +type OrderBy []*Order + +// Order represents an ordering expression. +type Order struct { + Expr Expr + Direction string } -// AddOrder adds an order by element -func (node *ParenSelect) AddOrder(order *Order) { - panic("unreachable") +// Limit represents a LIMIT clause. +type Limit struct { + Offset, Rowcount Expr } -// SetLimit sets the limit clause -func (node *ParenSelect) SetLimit(limit *Limit) { - panic("unreachable") +// Values represents a VALUES clause. +type Values []ValTuple + +// UpdateExprs represents a list of update expressions. +type UpdateExprs []*UpdateExpr + +// UpdateExpr represents an update expression. +type UpdateExpr struct { + Name *ColName + Expr Expr } -// Format formats the node. -func (node *ParenSelect) Format(buf *TrackedBuffer) { - buf.Myprintf("(%v)", node.Select) +// SetExprs represents a list of set expressions. +type SetExprs []*SetExpr + +// SetExpr represents a set expression. +type SetExpr struct { + Name ColIdent + Expr Expr } -func (node *ParenSelect) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Select, - ) +// OnDup represents an ON DUPLICATE KEY clause. +type OnDup UpdateExprs + +// ColIdent is a case insensitive SQL identifier. It will be escaped with +// backquotes if necessary. +type ColIdent struct { + // This artifact prevents this struct from being compared + // with itself. It consumes no space as long as it's not the + // last field in the struct. + _ [0]struct{ _ []byte } + val, lowered string } -// Union represents a UNION statement. -type Union struct { - Type string - Left, Right SelectStatement - OrderBy OrderBy - Limit *Limit - Lock string +// TableIdent is a case sensitive SQL identifier. It will be escaped with +// backquotes if necessary. +type TableIdent struct { + v string } -// Union.Type -const ( - UnionStr = "union" - UnionAllStr = "union all" - UnionDistinctStr = "union distinct" -) +// Here follow all the Format implementations for AST nodes -// AddOrder adds an order by element -func (node *Union) AddOrder(order *Order) { - node.OrderBy = append(node.OrderBy, order) +// Format formats the node. +func (node *Select) Format(buf *TrackedBuffer) { + buf.Myprintf("select %v%s%s%s%v from %v%v%v%v%v%v%s", + node.Comments, node.Cache, node.Distinct, node.Hints, node.SelectExprs, + node.From, node.Where, + node.GroupBy, node.Having, node.OrderBy, + node.Limit, node.Lock) } -// SetLimit sets the limit clause -func (node *Union) SetLimit(limit *Limit) { - node.Limit = limit +// Format formats the node. +func (node *ParenSelect) Format(buf *TrackedBuffer) { + buf.Myprintf("(%v)", node.Select) } // Format formats the node. @@ -489,67 +832,12 @@ func (node *Union) Format(buf *TrackedBuffer) { node.OrderBy, node.Limit, node.Lock) } -func (node *Union) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Left, - node.Right, - ) -} - -// Stream represents a SELECT statement. -type Stream struct { - Comments Comments - SelectExpr SelectExpr - Table TableName -} - // Format formats the node. func (node *Stream) Format(buf *TrackedBuffer) { buf.Myprintf("stream %v%v from %v", node.Comments, node.SelectExpr, node.Table) } -func (node *Stream) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Comments, - node.SelectExpr, - node.Table, - ) -} - -// Insert represents an INSERT or REPLACE statement. -// Per the MySQL docs, http://dev.mysql.com/doc/refman/5.7/en/replace.html -// Replace is the counterpart to `INSERT IGNORE`, and works exactly like a -// normal INSERT except if the row exists. In that case it first deletes -// the row and re-inserts with new values. For that reason we keep it as an Insert struct. -// Replaces are currently disallowed in sharded schemas because -// of the implications the deletion part may have on vindexes. -// If you add fields here, consider adding them to calls to validateUnshardedRoute. -type Insert struct { - Action string - Comments Comments - Ignore string - Table TableName - Partitions Partitions - Columns Columns - Rows InsertRows - OnDup OnDup -} - -// DDL strings. -const ( - InsertStr = "insert" - ReplaceStr = "replace" -) - // Format formats the node. func (node *Insert) Format(buf *TrackedBuffer) { buf.Myprintf("%s %v%sinto %v%v%v %v%v", @@ -558,43 +846,6 @@ func (node *Insert) Format(buf *TrackedBuffer) { node.Table, node.Partitions, node.Columns, node.Rows, node.OnDup) } -func (node *Insert) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Comments, - node.Table, - node.Columns, - node.Rows, - node.OnDup, - ) -} - -// InsertRows represents the rows for an INSERT statement. -type InsertRows interface { - iInsertRows() - SQLNode -} - -func (*Select) iInsertRows() {} -func (*Union) iInsertRows() {} -func (Values) iInsertRows() {} -func (*ParenSelect) iInsertRows() {} - -// Update represents an UPDATE statement. -// If you add fields here, consider adding them to calls to validateUnshardedRoute. -type Update struct { - Comments Comments - Ignore string - TableExprs TableExprs - Exprs UpdateExprs - Where *Where - OrderBy OrderBy - Limit *Limit -} - // Format formats the node. func (node *Update) Format(buf *TrackedBuffer) { buf.Myprintf("update %v%s%v set %v%v%v%v", @@ -602,33 +853,6 @@ func (node *Update) Format(buf *TrackedBuffer) { node.Exprs, node.Where, node.OrderBy, node.Limit) } -func (node *Update) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Comments, - node.TableExprs, - node.Exprs, - node.Where, - node.OrderBy, - node.Limit, - ) -} - -// Delete represents a DELETE statement. -// If you add fields here, consider adding them to calls to validateUnshardedRoute. -type Delete struct { - Comments Comments - Targets TableNames - TableExprs TableExprs - Partitions Partitions - Where *Where - OrderBy OrderBy - Limit *Limit -} - // Format formats the node. func (node *Delete) Format(buf *TrackedBuffer) { buf.Myprintf("delete %v", node.Comments) @@ -638,36 +862,6 @@ func (node *Delete) Format(buf *TrackedBuffer) { buf.Myprintf("from %v%v%v%v%v", node.TableExprs, node.Partitions, node.Where, node.OrderBy, node.Limit) } -func (node *Delete) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Comments, - node.Targets, - node.TableExprs, - node.Where, - node.OrderBy, - node.Limit, - ) -} - -// Set represents a SET statement. -type Set struct { - Comments Comments - Exprs SetExprs - Scope string -} - -// Set.Scope or Show.Scope -const ( - SessionStr = "session" - GlobalStr = "global" - VitessMetadataStr = "vitess_metadata" - ImplicitStr = "" -) - // Format formats the node. func (node *Set) Format(buf *TrackedBuffer) { if node.Scope == "" { @@ -677,30 +871,10 @@ func (node *Set) Format(buf *TrackedBuffer) { } } -func (node *Set) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Comments, - node.Exprs, - ) -} - -// DBDDL represents a CREATE, DROP database statement. -type DBDDL struct { - Action string - DBName string - IfExists bool - Collate string - Charset string -} - // Format formats the node. func (node *DBDDL) Format(buf *TrackedBuffer) { switch node.Action { - case CreateStr: + case CreateStr, AlterStr: buf.WriteString(fmt.Sprintf("%s database %s", node.Action, node.DBName)) case DropStr: exists := "" @@ -711,61 +885,6 @@ func (node *DBDDL) Format(buf *TrackedBuffer) { } } -// walkSubtree walks the nodes of the subtree. -func (node *DBDDL) walkSubtree(visit Visit) error { - return nil -} - -// DDL represents a CREATE, ALTER, DROP, RENAME, TRUNCATE or ANALYZE statement. -type DDL struct { - Action string - - // FromTables is set if Action is RenameStr or DropStr. - FromTables TableNames - - // ToTables is set if Action is RenameStr. - ToTables TableNames - - // Table is set if Action is other than RenameStr or DropStr. - Table TableName - - // The following fields are set if a DDL was fully analyzed. - IfExists bool - TableSpec *TableSpec - OptLike *OptLike - PartitionSpec *PartitionSpec - - // VindexSpec is set for CreateVindexStr, DropVindexStr, AddColVindexStr, DropColVindexStr. - VindexSpec *VindexSpec - - // VindexCols is set for AddColVindexStr. - VindexCols []ColIdent - - // AutoIncSpec is set for AddAutoIncStr. - AutoIncSpec *AutoIncSpec -} - -// DDL strings. -const ( - CreateStr = "create" - AlterStr = "alter" - DropStr = "drop" - RenameStr = "rename" - TruncateStr = "truncate" - FlushStr = "flush" - CreateVindexStr = "create vindex" - DropVindexStr = "drop vindex" - AddVschemaTableStr = "add vschema table" - DropVschemaTableStr = "drop vschema table" - AddColVindexStr = "on table add vindex" - DropColVindexStr = "on table drop vindex" - AddSequenceStr = "add sequence" - AddAutoIncStr = "add auto_increment" - - // Vindex DDL param to specify the owner of a vindex - VindexOwnerStr = "owner" -) - // Format formats the node. func (node *DDL) Format(buf *TrackedBuffer) { switch node.Action { @@ -817,48 +936,15 @@ func (node *DDL) Format(buf *TrackedBuffer) { if node.VindexSpec.Type.String() != "" { buf.Myprintf(" %v", node.VindexSpec) } - case DropColVindexStr: - buf.Myprintf("alter vschema on %v drop vindex %v", node.Table, node.VindexSpec.Name) - case AddSequenceStr: - buf.Myprintf("alter vschema add sequence %v", node.Table) - case AddAutoIncStr: - buf.Myprintf("alter vschema on %v add auto_increment %v", node.Table, node.AutoIncSpec) - default: - buf.Myprintf("%s table %v", node.Action, node.Table) - } -} - -func (node *DDL) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - for _, t := range node.AffectedTables() { - if err := Walk(visit, t); err != nil { - return err - } - } - return nil -} - -// AffectedTables returns the list table names affected by the DDL. -func (node *DDL) AffectedTables() TableNames { - if node.Action == RenameStr || node.Action == DropStr { - list := make(TableNames, 0, len(node.FromTables)+len(node.ToTables)) - list = append(list, node.FromTables...) - list = append(list, node.ToTables...) - return list + case DropColVindexStr: + buf.Myprintf("alter vschema on %v drop vindex %v", node.Table, node.VindexSpec.Name) + case AddSequenceStr: + buf.Myprintf("alter vschema add sequence %v", node.Table) + case AddAutoIncStr: + buf.Myprintf("alter vschema on %v add auto_increment %v", node.Table, node.AutoIncSpec) + default: + buf.Myprintf("%s table %v", node.Action, node.Table) } - return TableNames{node.Table} -} - -// Partition strings -const ( - ReorganizeStr = "reorganize partition" -) - -// OptLike works for create table xxx like xxx -type OptLike struct { - LikeTable TableName } // Format formats the node. @@ -866,20 +952,6 @@ func (node *OptLike) Format(buf *TrackedBuffer) { buf.Myprintf("like %v", node.LikeTable) } -func (node *OptLike) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk(visit, node.LikeTable) -} - -// PartitionSpec describe partition actions (for alter and create) -type PartitionSpec struct { - Action string - Name ColIdent - Definitions []*PartitionDefinition -} - // Format formats the node. func (node *PartitionSpec) Format(buf *TrackedBuffer) { switch node.Action { @@ -896,28 +968,6 @@ func (node *PartitionSpec) Format(buf *TrackedBuffer) { } } -func (node *PartitionSpec) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - if err := Walk(visit, node.Name); err != nil { - return err - } - for _, def := range node.Definitions { - if err := Walk(visit, def); err != nil { - return err - } - } - return nil -} - -// PartitionDefinition describes a very minimal partition definition -type PartitionDefinition struct { - Name ColIdent - Limit Expr - Maxvalue bool -} - // Format formats the node func (node *PartitionDefinition) Format(buf *TrackedBuffer) { if !node.Maxvalue { @@ -927,25 +977,6 @@ func (node *PartitionDefinition) Format(buf *TrackedBuffer) { } } -func (node *PartitionDefinition) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Name, - node.Limit, - ) -} - -// TableSpec describes the structure of a table from a CREATE TABLE statement -type TableSpec struct { - Columns []*ColumnDefinition - Indexes []*IndexDefinition - Constraints []*ConstraintDefinition - Options string -} - // Format formats the node. func (ts *TableSpec) Format(buf *TrackedBuffer) { buf.Myprintf("(\n") @@ -966,99 +997,11 @@ func (ts *TableSpec) Format(buf *TrackedBuffer) { buf.Myprintf("\n)%s", strings.Replace(ts.Options, ", ", ",\n ", -1)) } -// AddColumn appends the given column to the list in the spec -func (ts *TableSpec) AddColumn(cd *ColumnDefinition) { - ts.Columns = append(ts.Columns, cd) -} - -// AddIndex appends the given index to the list in the spec -func (ts *TableSpec) AddIndex(id *IndexDefinition) { - ts.Indexes = append(ts.Indexes, id) -} - -// AddConstraint appends the given index to the list in the spec -func (ts *TableSpec) AddConstraint(cd *ConstraintDefinition) { - ts.Constraints = append(ts.Constraints, cd) -} - -func (ts *TableSpec) walkSubtree(visit Visit) error { - if ts == nil { - return nil - } - - for _, n := range ts.Columns { - if err := Walk(visit, n); err != nil { - return err - } - } - - for _, n := range ts.Indexes { - if err := Walk(visit, n); err != nil { - return err - } - } - - for _, n := range ts.Constraints { - if err := Walk(visit, n); err != nil { - return err - } - } - - return nil -} - -// ColumnDefinition describes a column in a CREATE TABLE statement -type ColumnDefinition struct { - Name ColIdent - Type ColumnType -} - // Format formats the node. func (col *ColumnDefinition) Format(buf *TrackedBuffer) { buf.Myprintf("%v %v", col.Name, &col.Type) } -func (col *ColumnDefinition) walkSubtree(visit Visit) error { - if col == nil { - return nil - } - return Walk( - visit, - col.Name, - &col.Type, - ) -} - -// ColumnType represents a sql type in a CREATE TABLE statement -// All optional fields are nil if not specified -type ColumnType struct { - // The base type string - Type string - - // Generic field options. - NotNull BoolVal - Autoincrement BoolVal - Default Expr - OnUpdate Expr - Comment *SQLVal - - // Numeric field options - Length *SQLVal - Unsigned BoolVal - Zerofill BoolVal - Scale *SQLVal - - // Text field options - Charset string - Collate string - - // Enum values - EnumValues []string - - // Key specification - KeyOpt ColumnKeyOption -} - // Format returns a canonical string representation of the type and all relevant options func (ct *ColumnType) Format(buf *TrackedBuffer) { buf.Myprintf("%s", ct.Type) @@ -1123,141 +1066,6 @@ func (ct *ColumnType) Format(buf *TrackedBuffer) { } } -// DescribeType returns the abbreviated type information as required for -// describe table -func (ct *ColumnType) DescribeType() string { - buf := NewTrackedBuffer(nil) - buf.Myprintf("%s", ct.Type) - if ct.Length != nil && ct.Scale != nil { - buf.Myprintf("(%v,%v)", ct.Length, ct.Scale) - } else if ct.Length != nil { - buf.Myprintf("(%v)", ct.Length) - } - - opts := make([]string, 0, 16) - if ct.Unsigned { - opts = append(opts, keywordStrings[UNSIGNED]) - } - if ct.Zerofill { - opts = append(opts, keywordStrings[ZEROFILL]) - } - if len(opts) != 0 { - buf.Myprintf(" %s", strings.Join(opts, " ")) - } - return buf.String() -} - -// SQLType returns the sqltypes type code for the given column -func (ct *ColumnType) SQLType() querypb.Type { - switch ct.Type { - case keywordStrings[TINYINT]: - if ct.Unsigned { - return sqltypes.Uint8 - } - return sqltypes.Int8 - case keywordStrings[SMALLINT]: - if ct.Unsigned { - return sqltypes.Uint16 - } - return sqltypes.Int16 - case keywordStrings[MEDIUMINT]: - if ct.Unsigned { - return sqltypes.Uint24 - } - return sqltypes.Int24 - case keywordStrings[INT]: - fallthrough - case keywordStrings[INTEGER]: - if ct.Unsigned { - return sqltypes.Uint32 - } - return sqltypes.Int32 - case keywordStrings[BIGINT]: - if ct.Unsigned { - return sqltypes.Uint64 - } - return sqltypes.Int64 - case keywordStrings[BOOL], keywordStrings[BOOLEAN]: - return sqltypes.Uint8 - case keywordStrings[TEXT]: - return sqltypes.Text - case keywordStrings[TINYTEXT]: - return sqltypes.Text - case keywordStrings[MEDIUMTEXT]: - return sqltypes.Text - case keywordStrings[LONGTEXT]: - return sqltypes.Text - case keywordStrings[BLOB]: - return sqltypes.Blob - case keywordStrings[TINYBLOB]: - return sqltypes.Blob - case keywordStrings[MEDIUMBLOB]: - return sqltypes.Blob - case keywordStrings[LONGBLOB]: - return sqltypes.Blob - case keywordStrings[CHAR]: - return sqltypes.Char - case keywordStrings[VARCHAR]: - return sqltypes.VarChar - case keywordStrings[BINARY]: - return sqltypes.Binary - case keywordStrings[VARBINARY]: - return sqltypes.VarBinary - case keywordStrings[DATE]: - return sqltypes.Date - case keywordStrings[TIME]: - return sqltypes.Time - case keywordStrings[DATETIME]: - return sqltypes.Datetime - case keywordStrings[TIMESTAMP]: - return sqltypes.Timestamp - case keywordStrings[YEAR]: - return sqltypes.Year - case keywordStrings[FLOAT_TYPE]: - return sqltypes.Float32 - case keywordStrings[DOUBLE]: - return sqltypes.Float64 - case keywordStrings[DECIMAL]: - return sqltypes.Decimal - case keywordStrings[BIT]: - return sqltypes.Bit - case keywordStrings[ENUM]: - return sqltypes.Enum - case keywordStrings[SET]: - return sqltypes.Set - case keywordStrings[JSON]: - return sqltypes.TypeJSON - case keywordStrings[GEOMETRY]: - return sqltypes.Geometry - case keywordStrings[POINT]: - return sqltypes.Geometry - case keywordStrings[LINESTRING]: - return sqltypes.Geometry - case keywordStrings[POLYGON]: - return sqltypes.Geometry - case keywordStrings[GEOMETRYCOLLECTION]: - return sqltypes.Geometry - case keywordStrings[MULTIPOINT]: - return sqltypes.Geometry - case keywordStrings[MULTILINESTRING]: - return sqltypes.Geometry - case keywordStrings[MULTIPOLYGON]: - return sqltypes.Geometry - } - panic("unimplemented type " + ct.Type) -} - -func (ct *ColumnType) walkSubtree(visit Visit) error { - return nil -} - -// IndexDefinition describes an index in a CREATE TABLE statement -type IndexDefinition struct { - Info *IndexInfo - Columns []*IndexColumn - Options []*IndexOption -} - // Format formats the node. func (idx *IndexDefinition) Format(buf *TrackedBuffer) { buf.Myprintf("%v (", idx.Info) @@ -1283,29 +1091,6 @@ func (idx *IndexDefinition) Format(buf *TrackedBuffer) { } } -func (idx *IndexDefinition) walkSubtree(visit Visit) error { - if idx == nil { - return nil - } - - for _, n := range idx.Columns { - if err := Walk(visit, n.Column); err != nil { - return err - } - } - - return nil -} - -// IndexInfo describes the name and type of an index in a CREATE TABLE statement -type IndexInfo struct { - Type string - Name ColIdent - Primary bool - Spatial bool - Unique bool -} - // Format formats the node. func (ii *IndexInfo) Format(buf *TrackedBuffer) { if ii.Primary { @@ -1318,82 +1103,12 @@ func (ii *IndexInfo) Format(buf *TrackedBuffer) { } } -func (ii *IndexInfo) walkSubtree(visit Visit) error { - return Walk(visit, ii.Name) -} - -// IndexColumn describes a column in an index definition with optional length -type IndexColumn struct { - Column ColIdent - Length *SQLVal -} - -// LengthScaleOption is used for types that have an optional length -// and scale -type LengthScaleOption struct { - Length *SQLVal - Scale *SQLVal -} - -// IndexOption is used for trailing options for indexes: COMMENT, KEY_BLOCK_SIZE, USING -type IndexOption struct { - Name string - Value *SQLVal - Using string -} - -// ColumnKeyOption indicates whether or not the given column is defined as an -// index element and contains the type of the option -type ColumnKeyOption int - -const ( - colKeyNone ColumnKeyOption = iota - colKeyPrimary - colKeySpatialKey - colKeyUnique - colKeyUniqueKey - colKey -) - -// VindexSpec defines a vindex for a CREATE VINDEX or DROP VINDEX statement -type VindexSpec struct { - Name ColIdent - Type ColIdent - Params []VindexParam -} - -// AutoIncSpec defines and autoincrement value for a ADD AUTO_INCREMENT statement -type AutoIncSpec struct { - Column ColIdent - Sequence TableName -} - // Format formats the node. func (node *AutoIncSpec) Format(buf *TrackedBuffer) { buf.Myprintf("%v ", node.Column) buf.Myprintf("using %v", node.Sequence) } -func (node *AutoIncSpec) walkSubtree(visit Visit) error { - err := Walk(visit, node.Sequence, node.Column) - return err -} - -// ParseParams parses the vindex parameter list, pulling out the special-case -// "owner" parameter -func (node *VindexSpec) ParseParams() (string, map[string]string) { - var owner string - params := map[string]string{} - for _, p := range node.Params { - if p.Key.Lowered() == VindexOwnerStr { - owner = p.Val - } else { - params[p.Key.String()] = p.Val - } - } - return owner, params -} - // Format formats the node. The "CREATE VINDEX" preamble was formatted in // the containing DDL node Format, so this just prints the type, any // parameters, and optionally the owner @@ -1412,54 +1127,11 @@ func (node *VindexSpec) Format(buf *TrackedBuffer) { } } -func (node *VindexSpec) walkSubtree(visit Visit) error { - err := Walk(visit, - node.Name, - ) - - if err != nil { - return err - } - - for _, p := range node.Params { - err := Walk(visit, p) - - if err != nil { - return err - } - } - return nil -} - -// VindexParam defines a key/value parameter for a CREATE VINDEX statement -type VindexParam struct { - Key ColIdent - Val string -} - // Format formats the node. func (node VindexParam) Format(buf *TrackedBuffer) { buf.Myprintf("%s=%s", node.Key.String(), node.Val) } -func (node VindexParam) walkSubtree(visit Visit) error { - return Walk(visit, - node.Key, - ) -} - -// ConstraintDefinition describes a constraint in a CREATE TABLE statement -type ConstraintDefinition struct { - Name string - Details ConstraintInfo -} - -// ConstraintInfo details a constraint in a CREATE TABLE statement -type ConstraintInfo interface { - SQLNode - constraintInfo() -} - // Format formats the node. func (c *ConstraintDefinition) Format(buf *TrackedBuffer) { if c.Name != "" { @@ -1468,28 +1140,6 @@ func (c *ConstraintDefinition) Format(buf *TrackedBuffer) { c.Details.Format(buf) } -func (c *ConstraintDefinition) walkSubtree(visit Visit) error { - return Walk(visit, c.Details) -} - -// ReferenceAction indicates the action takes by a referential constraint e.g. -// the `CASCADE` in a `FOREIGN KEY .. ON DELETE CASCADE` table definition. -type ReferenceAction int - -// These map to the SQL-defined reference actions. -// See https://dev.mysql.com/doc/refman/8.0/en/create-table-foreign-keys.html#foreign-keys-referential-actions -const ( - // DefaultAction indicates no action was explicitly specified. - DefaultAction ReferenceAction = iota - Restrict - Cascade - NoAction - SetNull - SetDefault -) - -func (a ReferenceAction) walkSubtree(visit Visit) error { return nil } - // Format formats the node. func (a ReferenceAction) Format(buf *TrackedBuffer) { switch a { @@ -1506,17 +1156,6 @@ func (a ReferenceAction) Format(buf *TrackedBuffer) { } } -// ForeignKeyDefinition describes a foreign key in a CREATE TABLE statement -type ForeignKeyDefinition struct { - Source Columns - ReferencedTable TableName - ReferencedColumns Columns - OnDelete ReferenceAction - OnUpdate ReferenceAction -} - -var _ ConstraintInfo = &ForeignKeyDefinition{} - // Format formats the node. func (f *ForeignKeyDefinition) Format(buf *TrackedBuffer) { buf.Myprintf("foreign key %v references %v %v", f.Source, f.ReferencedTable, f.ReferencedColumns) @@ -1528,28 +1167,6 @@ func (f *ForeignKeyDefinition) Format(buf *TrackedBuffer) { } } -func (f *ForeignKeyDefinition) constraintInfo() {} - -func (f *ForeignKeyDefinition) walkSubtree(visit Visit) error { - if err := Walk(visit, f.Source); err != nil { - return err - } - if err := Walk(visit, f.ReferencedTable); err != nil { - return err - } - return Walk(visit, f.ReferencedColumns) -} - -// Show represents a show statement. -type Show struct { - Type string - OnTable TableName - Table TableName - ShowTablesOpt *ShowTablesOpt - Scope string - ShowCollationFilterOpt *Expr -} - // Format formats the node. func (node *Show) Format(buf *TrackedBuffer) { if (node.Type == "tables" || node.Type == "columns" || node.Type == "fields") && node.ShowTablesOpt != nil { @@ -1567,45 +1184,20 @@ func (node *Show) Format(buf *TrackedBuffer) { if node.Scope == "" { buf.Myprintf("show %s", node.Type) } else { - buf.Myprintf("show %s %s", node.Scope, node.Type) - } - if node.HasOnTable() { - buf.Myprintf(" on %v", node.OnTable) - } - if node.Type == "collation" && node.ShowCollationFilterOpt != nil { - buf.Myprintf(" where %v", *node.ShowCollationFilterOpt) - } - if node.HasTable() { - buf.Myprintf(" %v", node.Table) - } -} - -// HasOnTable returns true if the show statement has an "on" clause -func (node *Show) HasOnTable() bool { - return node.OnTable.Name.v != "" -} - -// HasTable returns true if the show statement has a parsed table name. -// Not all show statements parse table names. -func (node *Show) HasTable() bool { - return node.Table.Name.v != "" -} - -func (node *Show) walkSubtree(visit Visit) error { - return nil -} - -// ShowTablesOpt is show tables option -type ShowTablesOpt struct { - Full string - DbName string - Filter *ShowFilter -} - -// ShowFilter is show tables filter -type ShowFilter struct { - Like string - Filter Expr + buf.Myprintf("show %s %s", node.Scope, node.Type) + } + if node.HasOnTable() { + buf.Myprintf(" on %v", node.OnTable) + } + if node.Type == "collation" && node.ShowCollationFilterOpt != nil { + buf.Myprintf(" where %v", *node.ShowCollationFilterOpt) + } + if node.Type == "charset" && node.ShowTablesOpt != nil { + buf.Myprintf("%v", node.ShowTablesOpt.Filter) + } + if node.HasTable() { + buf.Myprintf(" %v", node.Table) + } } // Format formats the node. @@ -1620,15 +1212,6 @@ func (node *ShowFilter) Format(buf *TrackedBuffer) { } } -func (node *ShowFilter) walkSubtree(visit Visit) error { - return nil -} - -// Use represents a use statement. -type Use struct { - DBName TableIdent -} - // Format formats the node. func (node *Use) Format(buf *TrackedBuffer) { if node.DBName.v != "" { @@ -1638,78 +1221,31 @@ func (node *Use) Format(buf *TrackedBuffer) { } } -func (node *Use) walkSubtree(visit Visit) error { - return Walk(visit, node.DBName) -} - -// Begin represents a Begin statement. -type Begin struct{} - -// Format formats the node. -func (node *Begin) Format(buf *TrackedBuffer) { - buf.WriteString("begin") -} - -func (node *Begin) walkSubtree(visit Visit) error { - return nil -} - -// Commit represents a Commit statement. -type Commit struct{} - // Format formats the node. func (node *Commit) Format(buf *TrackedBuffer) { buf.WriteString("commit") } -func (node *Commit) walkSubtree(visit Visit) error { - return nil +// Format formats the node. +func (node *Begin) Format(buf *TrackedBuffer) { + buf.WriteString("begin") } -// Rollback represents a Rollback statement. -type Rollback struct{} - // Format formats the node. func (node *Rollback) Format(buf *TrackedBuffer) { buf.WriteString("rollback") } -func (node *Rollback) walkSubtree(visit Visit) error { - return nil -} - -// OtherRead represents a DESCRIBE, or EXPLAIN statement. -// It should be used only as an indicator. It does not contain -// the full AST for the statement. -type OtherRead struct{} - // Format formats the node. func (node *OtherRead) Format(buf *TrackedBuffer) { buf.WriteString("otherread") } -func (node *OtherRead) walkSubtree(visit Visit) error { - return nil -} - -// OtherAdmin represents a misc statement that relies on ADMIN privileges, -// such as REPAIR, OPTIMIZE, or TRUNCATE statement. -// It should be used only as an indicator. It does not contain -// the full AST for the statement. -type OtherAdmin struct{} - // Format formats the node. func (node *OtherAdmin) Format(buf *TrackedBuffer) { buf.WriteString("otheradmin") } -func (node *OtherAdmin) walkSubtree(visit Visit) error { - return nil -} - -// Comments represents a list of comments. -type Comments [][]byte - // Format formats the node. func (node Comments) Format(buf *TrackedBuffer) { for _, c := range node { @@ -1717,13 +1253,6 @@ func (node Comments) Format(buf *TrackedBuffer) { } } -func (node Comments) walkSubtree(visit Visit) error { - return nil -} - -// SelectExprs represents SELECT expressions. -type SelectExprs []SelectExpr - // Format formats the node. func (node SelectExprs) Format(buf *TrackedBuffer) { var prefix string @@ -1733,30 +1262,6 @@ func (node SelectExprs) Format(buf *TrackedBuffer) { } } -func (node SelectExprs) walkSubtree(visit Visit) error { - for _, n := range node { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - -// SelectExpr represents a SELECT expression. -type SelectExpr interface { - iSelectExpr() - SQLNode -} - -func (*StarExpr) iSelectExpr() {} -func (*AliasedExpr) iSelectExpr() {} -func (Nextval) iSelectExpr() {} - -// StarExpr defines a '*' or 'table.*' expression. -type StarExpr struct { - TableName TableName -} - // Format formats the node. func (node *StarExpr) Format(buf *TrackedBuffer) { if !node.TableName.IsEmpty() { @@ -1765,22 +1270,6 @@ func (node *StarExpr) Format(buf *TrackedBuffer) { buf.Myprintf("*") } -func (node *StarExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.TableName, - ) -} - -// AliasedExpr defines an aliased SELECT expression. -type AliasedExpr struct { - Expr Expr - As ColIdent -} - // Format formats the node. func (node *AliasedExpr) Format(buf *TrackedBuffer) { buf.Myprintf("%v", node.Expr) @@ -1789,34 +1278,11 @@ func (node *AliasedExpr) Format(buf *TrackedBuffer) { } } -func (node *AliasedExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - node.As, - ) -} - -// Nextval defines the NEXT VALUE expression. -type Nextval struct { - Expr Expr -} - // Format formats the node. func (node Nextval) Format(buf *TrackedBuffer) { buf.Myprintf("next %v values", node.Expr) } -func (node Nextval) walkSubtree(visit Visit) error { - return Walk(visit, node.Expr) -} - -// Columns represents an insert column list. -type Columns []ColIdent - // Format formats the node. func (node Columns) Format(buf *TrackedBuffer) { if node == nil { @@ -1830,29 +1296,6 @@ func (node Columns) Format(buf *TrackedBuffer) { buf.WriteString(")") } -func (node Columns) walkSubtree(visit Visit) error { - for _, n := range node { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - -// FindColumn finds a column in the column list, returning -// the index if it exists or -1 otherwise -func (node Columns) FindColumn(col ColIdent) int { - for i, colName := range node { - if colName.Equal(col) { - return i - } - } - return -1 -} - -// Partitions is a type alias for Columns so we can handle printing efficiently -type Partitions Columns - // Format formats the node func (node Partitions) Format(buf *TrackedBuffer) { if node == nil { @@ -1866,18 +1309,6 @@ func (node Partitions) Format(buf *TrackedBuffer) { buf.WriteString(")") } -func (node Partitions) walkSubtree(visit Visit) error { - for _, n := range node { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - -// TableExprs represents a list of table expressions. -type TableExprs []TableExpr - // Format formats the node. func (node TableExprs) Format(buf *TrackedBuffer) { var prefix string @@ -1887,35 +1318,6 @@ func (node TableExprs) Format(buf *TrackedBuffer) { } } -func (node TableExprs) walkSubtree(visit Visit) error { - for _, n := range node { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - -// TableExpr represents a table expression. -type TableExpr interface { - iTableExpr() - SQLNode -} - -func (*AliasedTableExpr) iTableExpr() {} -func (*ParenTableExpr) iTableExpr() {} -func (*JoinTableExpr) iTableExpr() {} - -// AliasedTableExpr represents a table expression -// coupled with an optional alias or index hint. -// If As is empty, no alias was used. -type AliasedTableExpr struct { - Expr SimpleTableExpr - Partitions Partitions - As TableIdent - Hints *IndexHints -} - // Format formats the node. func (node *AliasedTableExpr) Format(buf *TrackedBuffer) { buf.Myprintf("%v%v", node.Expr, node.Partitions) @@ -1928,37 +1330,6 @@ func (node *AliasedTableExpr) Format(buf *TrackedBuffer) { } } -func (node *AliasedTableExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - node.As, - node.Hints, - ) -} - -// RemoveHints returns a new AliasedTableExpr with the hints removed. -func (node *AliasedTableExpr) RemoveHints() *AliasedTableExpr { - noHints := *node - noHints.Hints = nil - return &noHints -} - -// SimpleTableExpr represents a simple table expression. -type SimpleTableExpr interface { - iSimpleTableExpr() - SQLNode -} - -func (TableName) iSimpleTableExpr() {} -func (*Subquery) iSimpleTableExpr() {} - -// TableNames is a list of TableName. -type TableNames []TableName - // Format formats the node. func (node TableNames) Format(buf *TrackedBuffer) { var prefix string @@ -1968,24 +1339,6 @@ func (node TableNames) Format(buf *TrackedBuffer) { } } -func (node TableNames) walkSubtree(visit Visit) error { - for _, n := range node { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - -// TableName represents a table name. -// Qualifier, if specified, represents a database or keyspace. -// TableName is a value struct whose fields are case sensitive. -// This means two TableName vars can be compared for equality -// and a TableName can also be used as key in a map. -type TableName struct { - Name, Qualifier TableIdent -} - // Format formats the node. func (node TableName) Format(buf *TrackedBuffer) { if node.IsEmpty() { @@ -1997,259 +1350,48 @@ func (node TableName) Format(buf *TrackedBuffer) { buf.Myprintf("%v", node.Name) } -func (node TableName) walkSubtree(visit Visit) error { - return Walk( - visit, - node.Name, - node.Qualifier, - ) -} - -// IsEmpty returns true if TableName is nil or empty. -func (node TableName) IsEmpty() bool { - // If Name is empty, Qualifier is also empty. - return node.Name.IsEmpty() -} - -// ToViewName returns a TableName acceptable for use as a VIEW. VIEW names are -// always lowercase, so ToViewName lowercasese the name. Databases are case-sensitive -// so Qualifier is left untouched. -func (node TableName) ToViewName() TableName { - return TableName{ - Qualifier: node.Qualifier, - Name: NewTableIdent(strings.ToLower(node.Name.v)), - } -} - -// ParenTableExpr represents a parenthesized list of TableExpr. -type ParenTableExpr struct { - Exprs TableExprs -} - // Format formats the node. func (node *ParenTableExpr) Format(buf *TrackedBuffer) { buf.Myprintf("(%v)", node.Exprs) } -func (node *ParenTableExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Exprs, - ) -} - -// JoinCondition represents the join conditions (either a ON or USING clause) -// of a JoinTableExpr. -type JoinCondition struct { - On Expr - Using Columns -} - // Format formats the node. func (node JoinCondition) Format(buf *TrackedBuffer) { if node.On != nil { buf.Myprintf(" on %v", node.On) } if node.Using != nil { - buf.Myprintf(" using %v", node.Using) - } -} - -func (node JoinCondition) walkSubtree(visit Visit) error { - return Walk( - visit, - node.On, - node.Using, - ) -} - -// JoinTableExpr represents a TableExpr that's a JOIN operation. -type JoinTableExpr struct { - LeftExpr TableExpr - Join string - RightExpr TableExpr - Condition JoinCondition -} - -// JoinTableExpr.Join -const ( - JoinStr = "join" - StraightJoinStr = "straight_join" - LeftJoinStr = "left join" - RightJoinStr = "right join" - NaturalJoinStr = "natural join" - NaturalLeftJoinStr = "natural left join" - NaturalRightJoinStr = "natural right join" -) - -// Format formats the node. -func (node *JoinTableExpr) Format(buf *TrackedBuffer) { - buf.Myprintf("%v %s %v%v", node.LeftExpr, node.Join, node.RightExpr, node.Condition) -} - -func (node *JoinTableExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.LeftExpr, - node.RightExpr, - node.Condition, - ) -} - -// IndexHints represents a list of index hints. -type IndexHints struct { - Type string - Indexes []ColIdent -} - -// Index hints. -const ( - UseStr = "use " - IgnoreStr = "ignore " - ForceStr = "force " -) - -// Format formats the node. -func (node *IndexHints) Format(buf *TrackedBuffer) { - buf.Myprintf(" %sindex ", node.Type) - prefix := "(" - for _, n := range node.Indexes { - buf.Myprintf("%s%v", prefix, n) - prefix = ", " - } - buf.Myprintf(")") -} - -func (node *IndexHints) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - for _, n := range node.Indexes { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - -// Where represents a WHERE or HAVING clause. -type Where struct { - Type string - Expr Expr -} - -// Where.Type -const ( - WhereStr = "where" - HavingStr = "having" -) - -// NewWhere creates a WHERE or HAVING clause out -// of a Expr. If the expression is nil, it returns nil. -func NewWhere(typ string, expr Expr) *Where { - if expr == nil { - return nil - } - return &Where{Type: typ, Expr: expr} -} - -// Format formats the node. -func (node *Where) Format(buf *TrackedBuffer) { - if node == nil || node.Expr == nil { - return - } - buf.Myprintf(" %s %v", node.Type, node.Expr) -} - -func (node *Where) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - ) -} - -// Expr represents an expression. -type Expr interface { - iExpr() - // replace replaces any subexpression that matches - // from with to. The implementation can use the - // replaceExprs convenience function. - replace(from, to Expr) bool - SQLNode -} - -func (*AndExpr) iExpr() {} -func (*OrExpr) iExpr() {} -func (*NotExpr) iExpr() {} -func (*ParenExpr) iExpr() {} -func (*ComparisonExpr) iExpr() {} -func (*RangeCond) iExpr() {} -func (*IsExpr) iExpr() {} -func (*ExistsExpr) iExpr() {} -func (*SQLVal) iExpr() {} -func (*NullVal) iExpr() {} -func (BoolVal) iExpr() {} -func (*ColName) iExpr() {} -func (ValTuple) iExpr() {} -func (*Subquery) iExpr() {} -func (ListArg) iExpr() {} -func (*BinaryExpr) iExpr() {} -func (*UnaryExpr) iExpr() {} -func (*IntervalExpr) iExpr() {} -func (*CollateExpr) iExpr() {} -func (*FuncExpr) iExpr() {} -func (*TimestampFuncExpr) iExpr() {} -func (*CurTimeFuncExpr) iExpr() {} -func (*CaseExpr) iExpr() {} -func (*ValuesFuncExpr) iExpr() {} -func (*ConvertExpr) iExpr() {} -func (*SubstrExpr) iExpr() {} -func (*ConvertUsingExpr) iExpr() {} -func (*MatchExpr) iExpr() {} -func (*GroupConcatExpr) iExpr() {} -func (*Default) iExpr() {} - -// ReplaceExpr finds the from expression from root -// and replaces it with to. If from matches root, -// then to is returned. -func ReplaceExpr(root, from, to Expr) Expr { - if root == from { - return to + buf.Myprintf(" using %v", node.Using) } - root.replace(from, to) - return root } -// replaceExprs is a convenience function used by implementors -// of the replace method. -func replaceExprs(from, to Expr, exprs ...*Expr) bool { - for _, expr := range exprs { - if *expr == nil { - continue - } - if *expr == from { - *expr = to - return true - } - if (*expr).replace(from, to) { - return true +// Format formats the node. +func (node *JoinTableExpr) Format(buf *TrackedBuffer) { + buf.Myprintf("%v %s %v%v", node.LeftExpr, node.Join, node.RightExpr, node.Condition) +} + +// Format formats the node. +func (node *IndexHints) Format(buf *TrackedBuffer) { + buf.Myprintf(" %sindex ", node.Type) + if len(node.Indexes) == 0 { + buf.Myprintf("()") + } else { + prefix := "(" + for _, n := range node.Indexes { + buf.Myprintf("%s%v", prefix, n) + prefix = ", " } + buf.Myprintf(")") } - return false } -// Exprs represents a list of value expressions. -// It's not a valid expression because it's not parenthesized. -type Exprs []Expr +// Format formats the node. +func (node *Where) Format(buf *TrackedBuffer) { + if node == nil || node.Expr == nil { + return + } + buf.Myprintf(" %s %v", node.Type, node.Expr) +} // Format formats the node. func (node Exprs) Format(buf *TrackedBuffer) { @@ -2260,139 +1402,26 @@ func (node Exprs) Format(buf *TrackedBuffer) { } } -func (node Exprs) walkSubtree(visit Visit) error { - for _, n := range node { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - -// AndExpr represents an AND expression. -type AndExpr struct { - Left, Right Expr -} - // Format formats the node. func (node *AndExpr) Format(buf *TrackedBuffer) { buf.Myprintf("%v and %v", node.Left, node.Right) } -func (node *AndExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Left, - node.Right, - ) -} - -func (node *AndExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Left, &node.Right) -} - -// OrExpr represents an OR expression. -type OrExpr struct { - Left, Right Expr -} - // Format formats the node. func (node *OrExpr) Format(buf *TrackedBuffer) { buf.Myprintf("%v or %v", node.Left, node.Right) } -func (node *OrExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Left, - node.Right, - ) -} - -func (node *OrExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Left, &node.Right) -} - -// NotExpr represents a NOT expression. -type NotExpr struct { - Expr Expr -} - // Format formats the node. func (node *NotExpr) Format(buf *TrackedBuffer) { buf.Myprintf("not %v", node.Expr) } -func (node *NotExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - ) -} - -func (node *NotExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Expr) -} - -// ParenExpr represents a parenthesized boolean expression. -type ParenExpr struct { - Expr Expr -} - // Format formats the node. func (node *ParenExpr) Format(buf *TrackedBuffer) { buf.Myprintf("(%v)", node.Expr) } -func (node *ParenExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - ) -} - -func (node *ParenExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Expr) -} - -// ComparisonExpr represents a two-value comparison expression. -type ComparisonExpr struct { - Operator string - Left, Right Expr - Escape Expr -} - -// ComparisonExpr.Operator -const ( - EqualStr = "=" - LessThanStr = "<" - GreaterThanStr = ">" - LessEqualStr = "<=" - GreaterEqualStr = ">=" - NotEqualStr = "!=" - NullSafeEqualStr = "<=>" - InStr = "in" - NotInStr = "not in" - LikeStr = "like" - NotLikeStr = "not like" - RegexpStr = "regexp" - NotRegexpStr = "not regexp" - JSONExtractOp = "->" - JSONUnquoteExtractOp = "->>" -) - // Format formats the node. func (node *ComparisonExpr) Format(buf *TrackedBuffer) { buf.Myprintf("%v %s %v", node.Left, node.Operator, node.Right) @@ -2401,218 +1430,21 @@ func (node *ComparisonExpr) Format(buf *TrackedBuffer) { } } -func (node *ComparisonExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Left, - node.Right, - node.Escape, - ) -} - -func (node *ComparisonExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Left, &node.Right, &node.Escape) -} - -// IsImpossible returns true if the comparison in the expression can never evaluate to true. -// Note that this is not currently exhaustive to ALL impossible comparisons. -func (node *ComparisonExpr) IsImpossible() bool { - var left, right *SQLVal - var ok bool - if left, ok = node.Left.(*SQLVal); !ok { - return false - } - if right, ok = node.Right.(*SQLVal); !ok { - return false - } - if node.Operator == NotEqualStr && left.Type == right.Type { - if len(left.Val) != len(right.Val) { - return false - } - - for i := range left.Val { - if left.Val[i] != right.Val[i] { - return false - } - } - return true - } - return false -} - -// RangeCond represents a BETWEEN or a NOT BETWEEN expression. -type RangeCond struct { - Operator string - Left Expr - From, To Expr -} - -// RangeCond.Operator -const ( - BetweenStr = "between" - NotBetweenStr = "not between" -) - // Format formats the node. func (node *RangeCond) Format(buf *TrackedBuffer) { buf.Myprintf("%v %s %v and %v", node.Left, node.Operator, node.From, node.To) } -func (node *RangeCond) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Left, - node.From, - node.To, - ) -} - -func (node *RangeCond) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Left, &node.From, &node.To) -} - -// IsExpr represents an IS ... or an IS NOT ... expression. -type IsExpr struct { - Operator string - Expr Expr -} - -// IsExpr.Operator -const ( - IsNullStr = "is null" - IsNotNullStr = "is not null" - IsTrueStr = "is true" - IsNotTrueStr = "is not true" - IsFalseStr = "is false" - IsNotFalseStr = "is not false" -) - // Format formats the node. func (node *IsExpr) Format(buf *TrackedBuffer) { buf.Myprintf("%v %s", node.Expr, node.Operator) } -func (node *IsExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - ) -} - -func (node *IsExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Expr) -} - -// ExistsExpr represents an EXISTS expression. -type ExistsExpr struct { - Subquery *Subquery -} - // Format formats the node. func (node *ExistsExpr) Format(buf *TrackedBuffer) { buf.Myprintf("exists %v", node.Subquery) } -func (node *ExistsExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Subquery, - ) -} - -func (node *ExistsExpr) replace(from, to Expr) bool { - return false -} - -// ExprFromValue converts the given Value into an Expr or returns an error. -func ExprFromValue(value sqltypes.Value) (Expr, error) { - // The type checks here follow the rules defined in sqltypes/types.go. - switch { - case value.Type() == sqltypes.Null: - return &NullVal{}, nil - case value.IsIntegral(): - return NewIntVal(value.ToBytes()), nil - case value.IsFloat() || value.Type() == sqltypes.Decimal: - return NewFloatVal(value.ToBytes()), nil - case value.IsQuoted(): - return NewStrVal(value.ToBytes()), nil - default: - // We cannot support sqltypes.Expression, or any other invalid type. - return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "cannot convert value %v to AST", value) - } -} - -// ValType specifies the type for SQLVal. -type ValType int - -// These are the possible Valtype values. -// HexNum represents a 0x... value. It cannot -// be treated as a simple value because it can -// be interpreted differently depending on the -// context. -const ( - StrVal = ValType(iota) - IntVal - FloatVal - HexNum - HexVal - ValArg - BitVal -) - -// SQLVal represents a single value. -type SQLVal struct { - Type ValType - Val []byte -} - -// NewStrVal builds a new StrVal. -func NewStrVal(in []byte) *SQLVal { - return &SQLVal{Type: StrVal, Val: in} -} - -// NewIntVal builds a new IntVal. -func NewIntVal(in []byte) *SQLVal { - return &SQLVal{Type: IntVal, Val: in} -} - -// NewFloatVal builds a new FloatVal. -func NewFloatVal(in []byte) *SQLVal { - return &SQLVal{Type: FloatVal, Val: in} -} - -// NewHexNum builds a new HexNum. -func NewHexNum(in []byte) *SQLVal { - return &SQLVal{Type: HexNum, Val: in} -} - -// NewHexVal builds a new HexVal. -func NewHexVal(in []byte) *SQLVal { - return &SQLVal{Type: HexVal, Val: in} -} - -// NewBitVal builds a new BitVal containing a bit literal. -func NewBitVal(in []byte) *SQLVal { - return &SQLVal{Type: BitVal, Val: in} -} - -// NewValArg builds a new ValArg. -func NewValArg(in []byte) *SQLVal { - return &SQLVal{Type: ValArg, Val: in} -} - // Format formats the node. func (node *SQLVal) Format(buf *TrackedBuffer) { switch node.Type { @@ -2631,43 +1463,11 @@ func (node *SQLVal) Format(buf *TrackedBuffer) { } } -func (node *SQLVal) walkSubtree(visit Visit) error { - return nil -} - -func (node *SQLVal) replace(from, to Expr) bool { - return false -} - -// HexDecode decodes the hexval into bytes. -func (node *SQLVal) HexDecode() ([]byte, error) { - dst := make([]byte, hex.DecodedLen(len([]byte(node.Val)))) - _, err := hex.Decode(dst, []byte(node.Val)) - if err != nil { - return nil, err - } - return dst, err -} - -// NullVal represents a NULL value. -type NullVal struct{} - // Format formats the node. func (node *NullVal) Format(buf *TrackedBuffer) { buf.Myprintf("null") } -func (node *NullVal) walkSubtree(visit Visit) error { - return nil -} - -func (node *NullVal) replace(from, to Expr) bool { - return false -} - -// BoolVal is true or false. -type BoolVal bool - // Format formats the node. func (node BoolVal) Format(buf *TrackedBuffer) { if node { @@ -2677,25 +1477,6 @@ func (node BoolVal) Format(buf *TrackedBuffer) { } } -func (node BoolVal) walkSubtree(visit Visit) error { - return nil -} - -func (node BoolVal) replace(from, to Expr) bool { - return false -} - -// ColName represents a column name. -type ColName struct { - // Metadata is not populated by the parser. - // It's a placeholder for analyzers to store - // additional data, typically info about which - // table or column this node references. - Metadata interface{} - Name ColIdent - Qualifier TableName -} - // Format formats the node. func (node *ColName) Format(buf *TrackedBuffer) { if !node.Qualifier.IsEmpty() { @@ -2704,160 +1485,26 @@ func (node *ColName) Format(buf *TrackedBuffer) { buf.Myprintf("%v", node.Name) } -func (node *ColName) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Name, - node.Qualifier, - ) -} - -func (node *ColName) replace(from, to Expr) bool { - return false -} - -// Equal returns true if the column names match. -func (node *ColName) Equal(c *ColName) bool { - // Failsafe: ColName should not be empty. - if node == nil || c == nil { - return false - } - return node.Name.Equal(c.Name) && node.Qualifier == c.Qualifier -} - -// ColTuple represents a list of column values. -// It can be ValTuple, Subquery, ListArg. -type ColTuple interface { - iColTuple() - Expr -} - -func (ValTuple) iColTuple() {} -func (*Subquery) iColTuple() {} -func (ListArg) iColTuple() {} - -// ValTuple represents a tuple of actual values. -type ValTuple Exprs - // Format formats the node. func (node ValTuple) Format(buf *TrackedBuffer) { buf.Myprintf("(%v)", Exprs(node)) } -func (node ValTuple) walkSubtree(visit Visit) error { - return Walk(visit, Exprs(node)) -} - -func (node ValTuple) replace(from, to Expr) bool { - for i := range node { - if replaceExprs(from, to, &node[i]) { - return true - } - } - return false -} - -// Subquery represents a subquery. -type Subquery struct { - Select SelectStatement -} - // Format formats the node. func (node *Subquery) Format(buf *TrackedBuffer) { buf.Myprintf("(%v)", node.Select) } -func (node *Subquery) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Select, - ) -} - -func (node *Subquery) replace(from, to Expr) bool { - return false -} - -// ListArg represents a named list argument. -type ListArg []byte - // Format formats the node. func (node ListArg) Format(buf *TrackedBuffer) { buf.WriteArg(string(node)) } -func (node ListArg) walkSubtree(visit Visit) error { - return nil -} - -func (node ListArg) replace(from, to Expr) bool { - return false -} - -// BinaryExpr represents a binary value expression. -type BinaryExpr struct { - Operator string - Left, Right Expr -} - -// BinaryExpr.Operator -const ( - BitAndStr = "&" - BitOrStr = "|" - BitXorStr = "^" - PlusStr = "+" - MinusStr = "-" - MultStr = "*" - DivStr = "/" - IntDivStr = "div" - ModStr = "%" - ShiftLeftStr = "<<" - ShiftRightStr = ">>" -) - // Format formats the node. func (node *BinaryExpr) Format(buf *TrackedBuffer) { buf.Myprintf("%v %s %v", node.Left, node.Operator, node.Right) } -func (node *BinaryExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Left, - node.Right, - ) -} - -func (node *BinaryExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Left, &node.Right) -} - -// UnaryExpr represents a unary value expression. -type UnaryExpr struct { - Operator string - Expr Expr -} - -// UnaryExpr.Operator -const ( - UPlusStr = "+" - UMinusStr = "-" - TildaStr = "~" - BangStr = "!" - BinaryStr = "binary " - UBinaryStr = "_binary " - Utf8mb4Str = "_utf8mb4 " -) - // Format formats the node. func (node *UnaryExpr) Format(buf *TrackedBuffer) { if _, unary := node.Expr.(*UnaryExpr); unary { @@ -2867,138 +1514,26 @@ func (node *UnaryExpr) Format(buf *TrackedBuffer) { buf.Myprintf("%s%v", node.Operator, node.Expr) } -func (node *UnaryExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - ) -} - -func (node *UnaryExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Expr) -} - -// IntervalExpr represents a date-time INTERVAL expression. -type IntervalExpr struct { - Expr Expr - Unit string -} - // Format formats the node. func (node *IntervalExpr) Format(buf *TrackedBuffer) { buf.Myprintf("interval %v %s", node.Expr, node.Unit) } -func (node *IntervalExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - ) -} - -func (node *IntervalExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Expr) -} - -// TimestampFuncExpr represents the function and arguments for TIMESTAMP{ADD,DIFF} functions. -type TimestampFuncExpr struct { - Name string - Expr1 Expr - Expr2 Expr - Unit string -} - // Format formats the node. func (node *TimestampFuncExpr) Format(buf *TrackedBuffer) { buf.Myprintf("%s(%s, %v, %v)", node.Name, node.Unit, node.Expr1, node.Expr2) } -func (node *TimestampFuncExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr1, - node.Expr2, - ) -} - -func (node *TimestampFuncExpr) replace(from, to Expr) bool { - if replaceExprs(from, to, &node.Expr1) { - return true - } - if replaceExprs(from, to, &node.Expr2) { - return true - } - return false -} - -// CurTimeFuncExpr represents the function and arguments for CURRENT DATE/TIME functions -// supported functions are documented in the grammar -type CurTimeFuncExpr struct { - Name ColIdent - Fsp Expr // fractional seconds precision, integer from 0 to 6 -} - // Format formats the node. func (node *CurTimeFuncExpr) Format(buf *TrackedBuffer) { buf.Myprintf("%s(%v)", node.Name.String(), node.Fsp) } -func (node *CurTimeFuncExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Fsp, - ) -} - -func (node *CurTimeFuncExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Fsp) -} - -// CollateExpr represents dynamic collate operator. -type CollateExpr struct { - Expr Expr - Charset string -} - // Format formats the node. func (node *CollateExpr) Format(buf *TrackedBuffer) { buf.Myprintf("%v collate %s", node.Expr, node.Charset) } -func (node *CollateExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - ) -} - -func (node *CollateExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Expr) -} - -// FuncExpr represents a function call. -type FuncExpr struct { - Qualifier TableIdent - Name ColIdent - Distinct bool - Exprs SelectExprs -} - // Format formats the node. func (node *FuncExpr) Format(buf *TrackedBuffer) { var distinct string @@ -3006,109 +1541,23 @@ func (node *FuncExpr) Format(buf *TrackedBuffer) { distinct = "distinct " } if !node.Qualifier.IsEmpty() { - buf.Myprintf("%v.", node.Qualifier) - } - // Function names should not be back-quoted even - // if they match a reserved word. So, print the - // name as is. - buf.Myprintf("%s(%s%v)", node.Name.String(), distinct, node.Exprs) -} - -func (node *FuncExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Qualifier, - node.Name, - node.Exprs, - ) -} - -func (node *FuncExpr) replace(from, to Expr) bool { - for _, sel := range node.Exprs { - aliased, ok := sel.(*AliasedExpr) - if !ok { - continue - } - if replaceExprs(from, to, &aliased.Expr) { - return true - } - } - return false -} - -// Aggregates is a map of all aggregate functions. -var Aggregates = map[string]bool{ - "avg": true, - "bit_and": true, - "bit_or": true, - "bit_xor": true, - "count": true, - "group_concat": true, - "max": true, - "min": true, - "std": true, - "stddev_pop": true, - "stddev_samp": true, - "stddev": true, - "sum": true, - "var_pop": true, - "var_samp": true, - "variance": true, -} - -// IsAggregate returns true if the function is an aggregate. -func (node *FuncExpr) IsAggregate() bool { - return Aggregates[node.Name.Lowered()] -} - -// GroupConcatExpr represents a call to GROUP_CONCAT -type GroupConcatExpr struct { - Distinct string - Exprs SelectExprs - OrderBy OrderBy - Separator string -} - -// Format formats the node -func (node *GroupConcatExpr) Format(buf *TrackedBuffer) { - buf.Myprintf("group_concat(%s%v%v%s)", node.Distinct, node.Exprs, node.OrderBy, node.Separator) -} - -func (node *GroupConcatExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil + buf.Myprintf("%v.", node.Qualifier) } - return Walk( - visit, - node.Exprs, - node.OrderBy, - ) -} + // Function names should not be back-quoted even + // if they match a reserved word, only if they contain illegal characters + funcName := node.Name.String() -func (node *GroupConcatExpr) replace(from, to Expr) bool { - for _, sel := range node.Exprs { - aliased, ok := sel.(*AliasedExpr) - if !ok { - continue - } - if replaceExprs(from, to, &aliased.Expr) { - return true - } - } - for _, order := range node.OrderBy { - if replaceExprs(from, to, &order.Expr) { - return true - } + if containEscapableChars(funcName) { + writeEscapedString(buf, funcName) + } else { + buf.WriteString(funcName) } - return false + buf.Myprintf("(%s%v)", distinct, node.Exprs) } -// ValuesFuncExpr represents a function call. -type ValuesFuncExpr struct { - Name *ColName +// Format formats the node +func (node *GroupConcatExpr) Format(buf *TrackedBuffer) { + buf.Myprintf("group_concat(%s%v%v%s%v)", node.Distinct, node.Exprs, node.OrderBy, node.Separator, node.Limit) } // Format formats the node. @@ -3116,32 +1565,6 @@ func (node *ValuesFuncExpr) Format(buf *TrackedBuffer) { buf.Myprintf("values(%v)", node.Name) } -func (node *ValuesFuncExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Name, - ) -} - -func (node *ValuesFuncExpr) replace(from, to Expr) bool { - return false -} - -// SubstrExpr represents a call to SubstrExpr(column, value_expression) or SubstrExpr(column, value_expression,value_expression) -// also supported syntax SubstrExpr(column from value_expression for value_expression). -// Additionally to column names, SubstrExpr is also supported for string values, e.g.: -// SubstrExpr('static string value', value_expression, value_expression) -// In this case StrVal will be set instead of Name. -type SubstrExpr struct { - Name *ColName - StrVal *SQLVal - From Expr - To Expr -} - // Format formats the node. func (node *SubstrExpr) Format(buf *TrackedBuffer) { var val interface{} @@ -3158,89 +1581,16 @@ func (node *SubstrExpr) Format(buf *TrackedBuffer) { } } -func (node *SubstrExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.From, &node.To) -} - -func (node *SubstrExpr) walkSubtree(visit Visit) error { - if node == nil || node.Name == nil { - return nil - } - return Walk( - visit, - node.Name, - node.From, - node.To, - ) -} - -// ConvertExpr represents a call to CONVERT(expr, type) -// or it's equivalent CAST(expr AS type). Both are rewritten to the former. -type ConvertExpr struct { - Expr Expr - Type *ConvertType -} - // Format formats the node. func (node *ConvertExpr) Format(buf *TrackedBuffer) { buf.Myprintf("convert(%v, %v)", node.Expr, node.Type) } -func (node *ConvertExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - node.Type, - ) -} - -func (node *ConvertExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Expr) -} - -// ConvertUsingExpr represents a call to CONVERT(expr USING charset). -type ConvertUsingExpr struct { - Expr Expr - Type string -} - // Format formats the node. func (node *ConvertUsingExpr) Format(buf *TrackedBuffer) { buf.Myprintf("convert(%v using %s)", node.Expr, node.Type) } -func (node *ConvertUsingExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - ) -} - -func (node *ConvertUsingExpr) replace(from, to Expr) bool { - return replaceExprs(from, to, &node.Expr) -} - -// ConvertType represents the type in call to CONVERT(expr, type) -type ConvertType struct { - Type string - Length *SQLVal - Scale *SQLVal - Operator string - Charset string -} - -// this string is "character set" and this comment is required -const ( - CharacterSetStr = " character set" - CharsetStr = "charset" -) - // Format formats the node. func (node *ConvertType) Format(buf *TrackedBuffer) { buf.Myprintf("%s", node.Type) @@ -3256,61 +1606,11 @@ func (node *ConvertType) Format(buf *TrackedBuffer) { } } -func (node *ConvertType) walkSubtree(visit Visit) error { - return nil -} - -// MatchExpr represents a call to the MATCH function -type MatchExpr struct { - Columns SelectExprs - Expr Expr - Option string -} - -// MatchExpr.Option -const ( - BooleanModeStr = " in boolean mode" - NaturalLanguageModeStr = " in natural language mode" - NaturalLanguageModeWithQueryExpansionStr = " in natural language mode with query expansion" - QueryExpansionStr = " with query expansion" -) - // Format formats the node func (node *MatchExpr) Format(buf *TrackedBuffer) { buf.Myprintf("match(%v) against (%v%s)", node.Columns, node.Expr, node.Option) } -func (node *MatchExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Columns, - node.Expr, - ) -} - -func (node *MatchExpr) replace(from, to Expr) bool { - for _, sel := range node.Columns { - aliased, ok := sel.(*AliasedExpr) - if !ok { - continue - } - if replaceExprs(from, to, &aliased.Expr) { - return true - } - } - return replaceExprs(from, to, &node.Expr) -} - -// CaseExpr represents a CASE expression. -type CaseExpr struct { - Expr Expr - Whens []*When - Else Expr -} - // Format formats the node. func (node *CaseExpr) Format(buf *TrackedBuffer) { buf.Myprintf("case ") @@ -3326,35 +1626,6 @@ func (node *CaseExpr) Format(buf *TrackedBuffer) { buf.Myprintf("end") } -func (node *CaseExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - if err := Walk(visit, node.Expr); err != nil { - return err - } - for _, n := range node.Whens { - if err := Walk(visit, n); err != nil { - return err - } - } - return Walk(visit, node.Else) -} - -func (node *CaseExpr) replace(from, to Expr) bool { - for _, when := range node.Whens { - if replaceExprs(from, to, &when.Cond, &when.Val) { - return true - } - } - return replaceExprs(from, to, &node.Expr, &node.Else) -} - -// Default represents a DEFAULT expression. -type Default struct { - ColName string -} - // Format formats the node. func (node *Default) Format(buf *TrackedBuffer) { buf.Myprintf("default") @@ -3363,39 +1634,11 @@ func (node *Default) Format(buf *TrackedBuffer) { } } -func (node *Default) walkSubtree(visit Visit) error { - return nil -} - -func (node *Default) replace(from, to Expr) bool { - return false -} - -// When represents a WHEN sub-expression. -type When struct { - Cond Expr - Val Expr -} - // Format formats the node. func (node *When) Format(buf *TrackedBuffer) { buf.Myprintf("when %v then %v", node.Cond, node.Val) } -func (node *When) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Cond, - node.Val, - ) -} - -// GroupBy represents a GROUP BY clause. -type GroupBy []Expr - // Format formats the node. func (node GroupBy) Format(buf *TrackedBuffer) { prefix := " group by " @@ -3405,18 +1648,6 @@ func (node GroupBy) Format(buf *TrackedBuffer) { } } -func (node GroupBy) walkSubtree(visit Visit) error { - for _, n := range node { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - -// OrderBy represents an ORDER By clause. -type OrderBy []*Order - // Format formats the node. func (node OrderBy) Format(buf *TrackedBuffer) { prefix := " order by " @@ -3426,27 +1657,6 @@ func (node OrderBy) Format(buf *TrackedBuffer) { } } -func (node OrderBy) walkSubtree(visit Visit) error { - for _, n := range node { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - -// Order represents an ordering expression. -type Order struct { - Expr Expr - Direction string -} - -// Order.Direction -const ( - AscScr = "asc" - DescScr = "desc" -) - // Format formats the node. func (node *Order) Format(buf *TrackedBuffer) { if node, ok := node.Expr.(*NullVal); ok { @@ -3463,21 +1673,6 @@ func (node *Order) Format(buf *TrackedBuffer) { buf.Myprintf("%v %s", node.Expr, node.Direction) } -func (node *Order) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Expr, - ) -} - -// Limit represents a LIMIT clause. -type Limit struct { - Offset, Rowcount Expr -} - // Format formats the node. func (node *Limit) Format(buf *TrackedBuffer) { if node == nil { @@ -3490,20 +1685,6 @@ func (node *Limit) Format(buf *TrackedBuffer) { buf.Myprintf("%v", node.Rowcount) } -func (node *Limit) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Offset, - node.Rowcount, - ) -} - -// Values represents a VALUES clause. -type Values []ValTuple - // Format formats the node. func (node Values) Format(buf *TrackedBuffer) { prefix := "values " @@ -3513,18 +1694,6 @@ func (node Values) Format(buf *TrackedBuffer) { } } -func (node Values) walkSubtree(visit Visit) error { - for _, n := range node { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - -// UpdateExprs represents a list of update expressions. -type UpdateExprs []*UpdateExpr - // Format formats the node. func (node UpdateExprs) Format(buf *TrackedBuffer) { var prefix string @@ -3534,40 +1703,11 @@ func (node UpdateExprs) Format(buf *TrackedBuffer) { } } -func (node UpdateExprs) walkSubtree(visit Visit) error { - for _, n := range node { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - -// UpdateExpr represents an update expression. -type UpdateExpr struct { - Name *ColName - Expr Expr -} - // Format formats the node. func (node *UpdateExpr) Format(buf *TrackedBuffer) { buf.Myprintf("%v = %v", node.Name, node.Expr) } -func (node *UpdateExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Name, - node.Expr, - ) -} - -// SetExprs represents a list of set expressions. -type SetExprs []*SetExpr - // Format formats the node. func (node SetExprs) Format(buf *TrackedBuffer) { var prefix string @@ -3577,35 +1717,6 @@ func (node SetExprs) Format(buf *TrackedBuffer) { } } -func (node SetExprs) walkSubtree(visit Visit) error { - for _, n := range node { - if err := Walk(visit, n); err != nil { - return err - } - } - return nil -} - -// SetExpr represents a set expression. -type SetExpr struct { - Name ColIdent - Expr Expr -} - -// SetExpr.Expr, for SET TRANSACTION ... or START TRANSACTION -const ( - // TransactionStr is the Name for a SET TRANSACTION statement - TransactionStr = "transaction" - - IsolationLevelReadUncommitted = "isolation level read uncommitted" - IsolationLevelReadCommitted = "isolation level read committed" - IsolationLevelRepeatableRead = "isolation level repeatable read" - IsolationLevelSerializable = "isolation level serializable" - - TxReadOnly = "read only" - TxReadWrite = "read write" -) - // Format formats the node. func (node *SetExpr) Format(buf *TrackedBuffer) { // We don't have to backtick set variable names. @@ -3619,20 +1730,6 @@ func (node *SetExpr) Format(buf *TrackedBuffer) { } } -func (node *SetExpr) walkSubtree(visit Visit) error { - if node == nil { - return nil - } - return Walk( - visit, - node.Name, - node.Expr, - ) -} - -// OnDup represents an ON DUPLICATE KEY clause. -type OnDup UpdateExprs - // Format formats the node. func (node OnDup) Format(buf *TrackedBuffer) { if node == nil { @@ -3641,189 +1738,12 @@ func (node OnDup) Format(buf *TrackedBuffer) { buf.Myprintf(" on duplicate key update %v", UpdateExprs(node)) } -func (node OnDup) walkSubtree(visit Visit) error { - return Walk(visit, UpdateExprs(node)) -} - -// ColIdent is a case insensitive SQL identifier. It will be escaped with -// backquotes if necessary. -type ColIdent struct { - // This artifact prevents this struct from being compared - // with itself. It consumes no space as long as it's not the - // last field in the struct. - _ [0]struct{ _ []byte } - val, lowered string -} - -// NewColIdent makes a new ColIdent. -func NewColIdent(str string) ColIdent { - return ColIdent{ - val: str, - } -} - // Format formats the node. func (node ColIdent) Format(buf *TrackedBuffer) { formatID(buf, node.val, node.Lowered()) } -func (node ColIdent) walkSubtree(visit Visit) error { - return nil -} - -// IsEmpty returns true if the name is empty. -func (node ColIdent) IsEmpty() bool { - return node.val == "" -} - -// String returns the unescaped column name. It must -// not be used for SQL generation. Use sqlparser.String -// instead. The Stringer conformance is for usage -// in templates. -func (node ColIdent) String() string { - return node.val -} - -// CompliantName returns a compliant id name -// that can be used for a bind var. -func (node ColIdent) CompliantName() string { - return compliantName(node.val) -} - -// Lowered returns a lower-cased column name. -// This function should generally be used only for optimizing -// comparisons. -func (node ColIdent) Lowered() string { - if node.val == "" { - return "" - } - if node.lowered == "" { - node.lowered = strings.ToLower(node.val) - } - return node.lowered -} - -// Equal performs a case-insensitive compare. -func (node ColIdent) Equal(in ColIdent) bool { - return node.Lowered() == in.Lowered() -} - -// EqualString performs a case-insensitive compare with str. -func (node ColIdent) EqualString(str string) bool { - return node.Lowered() == strings.ToLower(str) -} - -// MarshalJSON marshals into JSON. -func (node ColIdent) MarshalJSON() ([]byte, error) { - return json.Marshal(node.val) -} - -// UnmarshalJSON unmarshals from JSON. -func (node *ColIdent) UnmarshalJSON(b []byte) error { - var result string - err := json.Unmarshal(b, &result) - if err != nil { - return err - } - node.val = result - return nil -} - -// TableIdent is a case sensitive SQL identifier. It will be escaped with -// backquotes if necessary. -type TableIdent struct { - v string -} - -// NewTableIdent creates a new TableIdent. -func NewTableIdent(str string) TableIdent { - return TableIdent{v: str} -} - // Format formats the node. func (node TableIdent) Format(buf *TrackedBuffer) { formatID(buf, node.v, strings.ToLower(node.v)) } - -func (node TableIdent) walkSubtree(visit Visit) error { - return nil -} - -// IsEmpty returns true if TabIdent is empty. -func (node TableIdent) IsEmpty() bool { - return node.v == "" -} - -// String returns the unescaped table name. It must -// not be used for SQL generation. Use sqlparser.String -// instead. The Stringer conformance is for usage -// in templates. -func (node TableIdent) String() string { - return node.v -} - -// CompliantName returns a compliant id name -// that can be used for a bind var. -func (node TableIdent) CompliantName() string { - return compliantName(node.v) -} - -// MarshalJSON marshals into JSON. -func (node TableIdent) MarshalJSON() ([]byte, error) { - return json.Marshal(node.v) -} - -// UnmarshalJSON unmarshals from JSON. -func (node *TableIdent) UnmarshalJSON(b []byte) error { - var result string - err := json.Unmarshal(b, &result) - if err != nil { - return err - } - node.v = result - return nil -} - -func formatID(buf *TrackedBuffer, original, lowered string) { - isDbSystemVariable := false - if len(original) > 1 && original[:2] == "@@" { - isDbSystemVariable = true - } - - for i, c := range original { - if !isLetter(uint16(c)) && (!isDbSystemVariable || !isCarat(uint16(c))) { - if i == 0 || !isDigit(uint16(c)) { - goto mustEscape - } - } - } - if _, ok := keywords[lowered]; ok { - goto mustEscape - } - buf.Myprintf("%s", original) - return - -mustEscape: - buf.WriteByte('`') - for _, c := range original { - buf.WriteRune(c) - if c == '`' { - buf.WriteByte('`') - } - } - buf.WriteByte('`') -} - -func compliantName(in string) string { - var buf strings.Builder - for i, c := range in { - if !isLetter(uint16(c)) { - if i == 0 || !isDigit(uint16(c)) { - buf.WriteByte('_') - continue - } - } - buf.WriteRune(c) - } - return buf.String() -} diff --git a/go/vt/sqlparser/ast_funcs.go b/go/vt/sqlparser/ast_funcs.go new file mode 100644 index 00000000000..e1b6c07bec0 --- /dev/null +++ b/go/vt/sqlparser/ast_funcs.go @@ -0,0 +1,761 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package sqlparser + +import ( + "encoding/hex" + "encoding/json" + "strings" + + "vitess.io/vitess/go/vt/log" + + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/vt/vterrors" + + querypb "vitess.io/vitess/go/vt/proto/query" + vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" +) + +// Walk calls visit on every node. +// If visit returns true, the underlying nodes +// are also visited. If it returns an error, walking +// is interrupted, and the error is returned. +func Walk(visit Visit, nodes ...SQLNode) error { + for _, node := range nodes { + if node == nil { + continue + } + var err error + var kontinue bool + pre := func(cursor *Cursor) bool { + // If we already have found an error, don't visit these nodes, just exit early + if err != nil { + return false + } + kontinue, err = visit(cursor.Node()) + if err != nil { + return true // we have to return true here so that post gets called + } + return kontinue + } + post := func(cursor *Cursor) bool { + if err != nil { + return false // now we can abort the traversal if an error was found + } + + return true + } + + Rewrite(node, pre, post) + if err != nil { + return err + } + } + return nil +} + +// Visit defines the signature of a function that +// can be used to visit all nodes of a parse tree. +type Visit func(node SQLNode) (kontinue bool, err error) + +// Append appends the SQLNode to the buffer. +func Append(buf *strings.Builder, node SQLNode) { + tbuf := &TrackedBuffer{ + Builder: buf, + } + node.Format(tbuf) +} + +// IndexColumn describes a column in an index definition with optional length +type IndexColumn struct { + Column ColIdent + Length *SQLVal +} + +// LengthScaleOption is used for types that have an optional length +// and scale +type LengthScaleOption struct { + Length *SQLVal + Scale *SQLVal +} + +// IndexOption is used for trailing options for indexes: COMMENT, KEY_BLOCK_SIZE, USING +type IndexOption struct { + Name string + Value *SQLVal + Using string +} + +// ColumnKeyOption indicates whether or not the given column is defined as an +// index element and contains the type of the option +type ColumnKeyOption int + +const ( + colKeyNone ColumnKeyOption = iota + colKeyPrimary + colKeySpatialKey + colKeyUnique + colKeyUniqueKey + colKey +) + +// ReferenceAction indicates the action takes by a referential constraint e.g. +// the `CASCADE` in a `FOREIGN KEY .. ON DELETE CASCADE` table definition. +type ReferenceAction int + +// These map to the SQL-defined reference actions. +// See https://dev.mysql.com/doc/refman/8.0/en/create-table-foreign-keys.html#foreign-keys-referential-actions +const ( + // DefaultAction indicates no action was explicitly specified. + DefaultAction ReferenceAction = iota + Restrict + Cascade + NoAction + SetNull + SetDefault +) + +// ShowTablesOpt is show tables option +type ShowTablesOpt struct { + Full string + DbName string + Filter *ShowFilter +} + +// ValType specifies the type for SQLVal. +type ValType int + +// These are the possible Valtype values. +// HexNum represents a 0x... value. It cannot +// be treated as a simple value because it can +// be interpreted differently depending on the +// context. +const ( + StrVal = ValType(iota) + IntVal + FloatVal + HexNum + HexVal + ValArg + BitVal +) + +// AffectedTables returns the list table names affected by the DDL. +func (node *DDL) AffectedTables() TableNames { + if node.Action == RenameStr || node.Action == DropStr { + list := make(TableNames, 0, len(node.FromTables)+len(node.ToTables)) + list = append(list, node.FromTables...) + list = append(list, node.ToTables...) + return list + } + return TableNames{node.Table} +} + +// AddColumn appends the given column to the list in the spec +func (ts *TableSpec) AddColumn(cd *ColumnDefinition) { + ts.Columns = append(ts.Columns, cd) +} + +// AddIndex appends the given index to the list in the spec +func (ts *TableSpec) AddIndex(id *IndexDefinition) { + ts.Indexes = append(ts.Indexes, id) +} + +// AddConstraint appends the given index to the list in the spec +func (ts *TableSpec) AddConstraint(cd *ConstraintDefinition) { + ts.Constraints = append(ts.Constraints, cd) +} + +// DescribeType returns the abbreviated type information as required for +// describe table +func (ct *ColumnType) DescribeType() string { + buf := NewTrackedBuffer(nil) + buf.Myprintf("%s", ct.Type) + if ct.Length != nil && ct.Scale != nil { + buf.Myprintf("(%v,%v)", ct.Length, ct.Scale) + } else if ct.Length != nil { + buf.Myprintf("(%v)", ct.Length) + } + + opts := make([]string, 0, 16) + if ct.Unsigned { + opts = append(opts, keywordStrings[UNSIGNED]) + } + if ct.Zerofill { + opts = append(opts, keywordStrings[ZEROFILL]) + } + if len(opts) != 0 { + buf.Myprintf(" %s", strings.Join(opts, " ")) + } + return buf.String() +} + +// SQLType returns the sqltypes type code for the given column +func (ct *ColumnType) SQLType() querypb.Type { + switch ct.Type { + case keywordStrings[TINYINT]: + if ct.Unsigned { + return sqltypes.Uint8 + } + return sqltypes.Int8 + case keywordStrings[SMALLINT]: + if ct.Unsigned { + return sqltypes.Uint16 + } + return sqltypes.Int16 + case keywordStrings[MEDIUMINT]: + if ct.Unsigned { + return sqltypes.Uint24 + } + return sqltypes.Int24 + case keywordStrings[INT], keywordStrings[INTEGER]: + if ct.Unsigned { + return sqltypes.Uint32 + } + return sqltypes.Int32 + case keywordStrings[BIGINT]: + if ct.Unsigned { + return sqltypes.Uint64 + } + return sqltypes.Int64 + case keywordStrings[BOOL], keywordStrings[BOOLEAN]: + return sqltypes.Uint8 + case keywordStrings[TEXT]: + return sqltypes.Text + case keywordStrings[TINYTEXT]: + return sqltypes.Text + case keywordStrings[MEDIUMTEXT]: + return sqltypes.Text + case keywordStrings[LONGTEXT]: + return sqltypes.Text + case keywordStrings[BLOB]: + return sqltypes.Blob + case keywordStrings[TINYBLOB]: + return sqltypes.Blob + case keywordStrings[MEDIUMBLOB]: + return sqltypes.Blob + case keywordStrings[LONGBLOB]: + return sqltypes.Blob + case keywordStrings[CHAR]: + return sqltypes.Char + case keywordStrings[VARCHAR]: + return sqltypes.VarChar + case keywordStrings[BINARY]: + return sqltypes.Binary + case keywordStrings[VARBINARY]: + return sqltypes.VarBinary + case keywordStrings[DATE]: + return sqltypes.Date + case keywordStrings[TIME]: + return sqltypes.Time + case keywordStrings[DATETIME]: + return sqltypes.Datetime + case keywordStrings[TIMESTAMP]: + return sqltypes.Timestamp + case keywordStrings[YEAR]: + return sqltypes.Year + case keywordStrings[FLOAT_TYPE]: + return sqltypes.Float32 + case keywordStrings[DOUBLE]: + return sqltypes.Float64 + case keywordStrings[DECIMAL]: + return sqltypes.Decimal + case keywordStrings[BIT]: + return sqltypes.Bit + case keywordStrings[ENUM]: + return sqltypes.Enum + case keywordStrings[SET]: + return sqltypes.Set + case keywordStrings[JSON]: + return sqltypes.TypeJSON + case keywordStrings[GEOMETRY]: + return sqltypes.Geometry + case keywordStrings[POINT]: + return sqltypes.Geometry + case keywordStrings[LINESTRING]: + return sqltypes.Geometry + case keywordStrings[POLYGON]: + return sqltypes.Geometry + case keywordStrings[GEOMETRYCOLLECTION]: + return sqltypes.Geometry + case keywordStrings[MULTIPOINT]: + return sqltypes.Geometry + case keywordStrings[MULTILINESTRING]: + return sqltypes.Geometry + case keywordStrings[MULTIPOLYGON]: + return sqltypes.Geometry + } + panic("unimplemented type " + ct.Type) +} + +// ParseParams parses the vindex parameter list, pulling out the special-case +// "owner" parameter +func (node *VindexSpec) ParseParams() (string, map[string]string) { + var owner string + params := map[string]string{} + for _, p := range node.Params { + if p.Key.Lowered() == VindexOwnerStr { + owner = p.Val + } else { + params[p.Key.String()] = p.Val + } + } + return owner, params +} + +var _ ConstraintInfo = &ForeignKeyDefinition{} + +func (f *ForeignKeyDefinition) iConstraintInfo() {} + +// HasOnTable returns true if the show statement has an "on" clause +func (node *Show) HasOnTable() bool { + return node.OnTable.Name.v != "" +} + +// HasTable returns true if the show statement has a parsed table name. +// Not all show statements parse table names. +func (node *Show) HasTable() bool { + return node.Table.Name.v != "" +} + +// FindColumn finds a column in the column list, returning +// the index if it exists or -1 otherwise +func (node Columns) FindColumn(col ColIdent) int { + for i, colName := range node { + if colName.Equal(col) { + return i + } + } + return -1 +} + +// RemoveHints returns a new AliasedTableExpr with the hints removed. +func (node *AliasedTableExpr) RemoveHints() *AliasedTableExpr { + noHints := *node + noHints.Hints = nil + return &noHints +} + +// IsEmpty returns true if TableName is nil or empty. +func (node TableName) IsEmpty() bool { + // If Name is empty, Qualifier is also empty. + return node.Name.IsEmpty() +} + +// ToViewName returns a TableName acceptable for use as a VIEW. VIEW names are +// always lowercase, so ToViewName lowercasese the name. Databases are case-sensitive +// so Qualifier is left untouched. +func (node TableName) ToViewName() TableName { + return TableName{ + Qualifier: node.Qualifier, + Name: NewTableIdent(strings.ToLower(node.Name.v)), + } +} + +// NewWhere creates a WHERE or HAVING clause out +// of a Expr. If the expression is nil, it returns nil. +func NewWhere(typ string, expr Expr) *Where { + if expr == nil { + return nil + } + return &Where{Type: typ, Expr: expr} +} + +// ReplaceExpr finds the from expression from root +// and replaces it with to. If from matches root, +// then to is returned. +func ReplaceExpr(root, from, to Expr) Expr { + tmp := Rewrite(root, replaceExpr(from, to), nil) + expr, success := tmp.(Expr) + if !success { + log.Errorf("Failed to rewrite expression. Rewriter returned a non-expression: " + String(tmp)) + return from + } + + return expr +} + +func replaceExpr(from, to Expr) func(cursor *Cursor) bool { + return func(cursor *Cursor) bool { + if cursor.Node() == from { + cursor.Replace(to) + } + switch cursor.Node().(type) { + case *ExistsExpr, *SQLVal, *Subquery, *ValuesFuncExpr, *Default: + return false + } + + return true + } +} + +// IsImpossible returns true if the comparison in the expression can never evaluate to true. +// Note that this is not currently exhaustive to ALL impossible comparisons. +func (node *ComparisonExpr) IsImpossible() bool { + var left, right *SQLVal + var ok bool + if left, ok = node.Left.(*SQLVal); !ok { + return false + } + if right, ok = node.Right.(*SQLVal); !ok { + return false + } + if node.Operator == NotEqualStr && left.Type == right.Type { + if len(left.Val) != len(right.Val) { + return false + } + + for i := range left.Val { + if left.Val[i] != right.Val[i] { + return false + } + } + return true + } + return false +} + +// ExprFromValue converts the given Value into an Expr or returns an error. +func ExprFromValue(value sqltypes.Value) (Expr, error) { + // The type checks here follow the rules defined in sqltypes/types.go. + switch { + case value.Type() == sqltypes.Null: + return &NullVal{}, nil + case value.IsIntegral(): + return NewIntVal(value.ToBytes()), nil + case value.IsFloat() || value.Type() == sqltypes.Decimal: + return NewFloatVal(value.ToBytes()), nil + case value.IsQuoted(): + return NewStrVal(value.ToBytes()), nil + default: + // We cannot support sqltypes.Expression, or any other invalid type. + return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "cannot convert value %v to AST", value) + } +} + +// NewStrVal builds a new StrVal. +func NewStrVal(in []byte) *SQLVal { + return &SQLVal{Type: StrVal, Val: in} +} + +// NewIntVal builds a new IntVal. +func NewIntVal(in []byte) *SQLVal { + return &SQLVal{Type: IntVal, Val: in} +} + +// NewFloatVal builds a new FloatVal. +func NewFloatVal(in []byte) *SQLVal { + return &SQLVal{Type: FloatVal, Val: in} +} + +// NewHexNum builds a new HexNum. +func NewHexNum(in []byte) *SQLVal { + return &SQLVal{Type: HexNum, Val: in} +} + +// NewHexVal builds a new HexVal. +func NewHexVal(in []byte) *SQLVal { + return &SQLVal{Type: HexVal, Val: in} +} + +// NewBitVal builds a new BitVal containing a bit literal. +func NewBitVal(in []byte) *SQLVal { + return &SQLVal{Type: BitVal, Val: in} +} + +// NewValArg builds a new ValArg. +func NewValArg(in []byte) *SQLVal { + return &SQLVal{Type: ValArg, Val: in} +} + +// HexDecode decodes the hexval into bytes. +func (node *SQLVal) HexDecode() ([]byte, error) { + dst := make([]byte, hex.DecodedLen(len([]byte(node.Val)))) + _, err := hex.Decode(dst, []byte(node.Val)) + if err != nil { + return nil, err + } + return dst, err +} + +// Equal returns true if the column names match. +func (node *ColName) Equal(c *ColName) bool { + // Failsafe: ColName should not be empty. + if node == nil || c == nil { + return false + } + return node.Name.Equal(c.Name) && node.Qualifier == c.Qualifier +} + +// Aggregates is a map of all aggregate functions. +var Aggregates = map[string]bool{ + "avg": true, + "bit_and": true, + "bit_or": true, + "bit_xor": true, + "count": true, + "group_concat": true, + "max": true, + "min": true, + "std": true, + "stddev_pop": true, + "stddev_samp": true, + "stddev": true, + "sum": true, + "var_pop": true, + "var_samp": true, + "variance": true, +} + +// IsAggregate returns true if the function is an aggregate. +func (node *FuncExpr) IsAggregate() bool { + return Aggregates[node.Name.Lowered()] +} + +// NewColIdent makes a new ColIdent. +func NewColIdent(str string) ColIdent { + return ColIdent{ + val: str, + } +} + +// IsEmpty returns true if the name is empty. +func (node ColIdent) IsEmpty() bool { + return node.val == "" +} + +// String returns the unescaped column name. It must +// not be used for SQL generation. Use sqlparser.String +// instead. The Stringer conformance is for usage +// in templates. +func (node ColIdent) String() string { + return node.val +} + +// CompliantName returns a compliant id name +// that can be used for a bind var. +func (node ColIdent) CompliantName() string { + return compliantName(node.val) +} + +// Lowered returns a lower-cased column name. +// This function should generally be used only for optimizing +// comparisons. +func (node ColIdent) Lowered() string { + if node.val == "" { + return "" + } + if node.lowered == "" { + node.lowered = strings.ToLower(node.val) + } + return node.lowered +} + +// Equal performs a case-insensitive compare. +func (node ColIdent) Equal(in ColIdent) bool { + return node.Lowered() == in.Lowered() +} + +// EqualString performs a case-insensitive compare with str. +func (node ColIdent) EqualString(str string) bool { + return node.Lowered() == strings.ToLower(str) +} + +// MarshalJSON marshals into JSON. +func (node ColIdent) MarshalJSON() ([]byte, error) { + return json.Marshal(node.val) +} + +// UnmarshalJSON unmarshals from JSON. +func (node *ColIdent) UnmarshalJSON(b []byte) error { + var result string + err := json.Unmarshal(b, &result) + if err != nil { + return err + } + node.val = result + return nil +} + +// NewTableIdent creates a new TableIdent. +func NewTableIdent(str string) TableIdent { + return TableIdent{v: str} +} + +// IsEmpty returns true if TabIdent is empty. +func (node TableIdent) IsEmpty() bool { + return node.v == "" +} + +// String returns the unescaped table name. It must +// not be used for SQL generation. Use sqlparser.String +// instead. The Stringer conformance is for usage +// in templates. +func (node TableIdent) String() string { + return node.v +} + +// CompliantName returns a compliant id name +// that can be used for a bind var. +func (node TableIdent) CompliantName() string { + return compliantName(node.v) +} + +// MarshalJSON marshals into JSON. +func (node TableIdent) MarshalJSON() ([]byte, error) { + return json.Marshal(node.v) +} + +// UnmarshalJSON unmarshals from JSON. +func (node *TableIdent) UnmarshalJSON(b []byte) error { + var result string + err := json.Unmarshal(b, &result) + if err != nil { + return err + } + node.v = result + return nil +} + +func containEscapableChars(s string) bool { + isDbSystemVariable := false + if len(s) > 1 && s[:2] == "@@" { + isDbSystemVariable = true + } + + for i, c := range s { + if !isLetter(uint16(c)) && (!isDbSystemVariable || !isCarat(uint16(c))) { + if i == 0 || !isDigit(uint16(c)) { + return true + } + } + } + + return false +} + +func isKeyword(s string) bool { + _, isKeyword := keywords[s] + return isKeyword +} + +func formatID(buf *TrackedBuffer, original, lowered string) { + if containEscapableChars(original) || isKeyword(lowered) { + writeEscapedString(buf, original) + } else { + buf.Myprintf("%s", original) + } +} + +func writeEscapedString(buf *TrackedBuffer, original string) { + buf.WriteByte('`') + for _, c := range original { + buf.WriteRune(c) + if c == '`' { + buf.WriteByte('`') + } + } + buf.WriteByte('`') +} + +func compliantName(in string) string { + var buf strings.Builder + for i, c := range in { + if !isLetter(uint16(c)) { + if i == 0 || !isDigit(uint16(c)) { + buf.WriteByte('_') + continue + } + } + buf.WriteRune(c) + } + return buf.String() +} + +// AddOrder adds an order by element +func (node *Select) AddOrder(order *Order) { + node.OrderBy = append(node.OrderBy, order) +} + +// SetLimit sets the limit clause +func (node *Select) SetLimit(limit *Limit) { + node.Limit = limit +} + +// AddWhere adds the boolean expression to the +// WHERE clause as an AND condition. If the expression +// is an OR clause, it parenthesizes it. Currently, +// the OR operator is the only one that's lower precedence +// than AND. +func (node *Select) AddWhere(expr Expr) { + if _, ok := expr.(*OrExpr); ok { + expr = &ParenExpr{Expr: expr} + } + if node.Where == nil { + node.Where = &Where{ + Type: WhereStr, + Expr: expr, + } + return + } + node.Where.Expr = &AndExpr{ + Left: node.Where.Expr, + Right: expr, + } +} + +// AddHaving adds the boolean expression to the +// HAVING clause as an AND condition. If the expression +// is an OR clause, it parenthesizes it. Currently, +// the OR operator is the only one that's lower precedence +// than AND. +func (node *Select) AddHaving(expr Expr) { + if _, ok := expr.(*OrExpr); ok { + expr = &ParenExpr{Expr: expr} + } + if node.Having == nil { + node.Having = &Where{ + Type: HavingStr, + Expr: expr, + } + return + } + node.Having.Expr = &AndExpr{ + Left: node.Having.Expr, + Right: expr, + } +} + +// AddOrder adds an order by element +func (node *ParenSelect) AddOrder(order *Order) { + panic("unreachable") +} + +// SetLimit sets the limit clause +func (node *ParenSelect) SetLimit(limit *Limit) { + panic("unreachable") +} + +// AddOrder adds an order by element +func (node *Union) AddOrder(order *Order) { + node.OrderBy = append(node.OrderBy, order) +} + +// SetLimit sets the limit clause +func (node *Union) SetLimit(limit *Limit) { + node.Limit = limit +} diff --git a/go/vt/sqlparser/ast_test.go b/go/vt/sqlparser/ast_test.go index 1f18bcb07fa..579efc45dfd 100644 --- a/go/vt/sqlparser/ast_test.go +++ b/go/vt/sqlparser/ast_test.go @@ -24,15 +24,14 @@ import ( "testing" "unsafe" + "github.com/stretchr/testify/require" "vitess.io/vitess/go/sqltypes" ) func TestAppend(t *testing.T) { query := "select * from t where a = 1" tree, err := Parse(query) - if err != nil { - t.Error(err) - } + require.NoError(t, err) var b strings.Builder Append(&b, tree) got := b.String() @@ -50,9 +49,7 @@ func TestAppend(t *testing.T) { func TestSelect(t *testing.T) { tree, err := Parse("select * from t where a = 1") - if err != nil { - t.Error(err) - } + require.NoError(t, err) expr := tree.(*Select).Where.Expr sel := &Select{} @@ -88,9 +85,7 @@ func TestSelect(t *testing.T) { // OR clauses must be parenthesized. tree, err = Parse("select * from t where a = 1 or b = 1") - if err != nil { - t.Error(err) - } + require.NoError(t, err) expr = tree.(*Select).Where.Expr sel = &Select{} sel.AddWhere(expr) @@ -133,14 +128,10 @@ func TestRemoveHints(t *testing.T) { func TestAddOrder(t *testing.T) { src, err := Parse("select foo, bar from baz order by foo") - if err != nil { - t.Error(err) - } + require.NoError(t, err) order := src.(*Select).OrderBy[0] dst, err := Parse("select * from t") - if err != nil { - t.Error(err) - } + require.NoError(t, err) dst.(*Select).AddOrder(order) buf := NewTrackedBuffer(nil) dst.Format(buf) @@ -149,9 +140,7 @@ func TestAddOrder(t *testing.T) { t.Errorf("order: %q, want %s", buf.String(), want) } dst, err = Parse("select * from t union select * from s") - if err != nil { - t.Error(err) - } + require.NoError(t, err) dst.(*Union).AddOrder(order) buf = NewTrackedBuffer(nil) dst.Format(buf) @@ -163,14 +152,10 @@ func TestAddOrder(t *testing.T) { func TestSetLimit(t *testing.T) { src, err := Parse("select foo, bar from baz limit 4") - if err != nil { - t.Error(err) - } + require.NoError(t, err) limit := src.(*Select).Limit dst, err := Parse("select * from t") - if err != nil { - t.Error(err) - } + require.NoError(t, err) dst.(*Select).SetLimit(limit) buf := NewTrackedBuffer(nil) dst.Format(buf) @@ -179,9 +164,7 @@ func TestSetLimit(t *testing.T) { t.Errorf("limit: %q, want %s", buf.String(), want) } dst, err = Parse("select * from t union select * from s") - if err != nil { - t.Error(err) - } + require.NoError(t, err) dst.(*Union).SetLimit(limit) buf = NewTrackedBuffer(nil) dst.Format(buf) @@ -269,9 +252,7 @@ func TestDDL(t *testing.T) { func TestSetAutocommitON(t *testing.T) { stmt, err := Parse("SET autocommit=ON") - if err != nil { - t.Error(err) - } + require.NoError(t, err) s, ok := stmt.(*Set) if !ok { t.Errorf("SET statement is not Set: %T", s) @@ -296,9 +277,7 @@ func TestSetAutocommitON(t *testing.T) { } stmt, err = Parse("SET @@session.autocommit=ON") - if err != nil { - t.Error(err) - } + require.NoError(t, err) s, ok = stmt.(*Set) if !ok { t.Errorf("SET statement is not Set: %T", s) @@ -325,9 +304,7 @@ func TestSetAutocommitON(t *testing.T) { func TestSetAutocommitOFF(t *testing.T) { stmt, err := Parse("SET autocommit=OFF") - if err != nil { - t.Error(err) - } + require.NoError(t, err) s, ok := stmt.(*Set) if !ok { t.Errorf("SET statement is not Set: %T", s) @@ -352,9 +329,7 @@ func TestSetAutocommitOFF(t *testing.T) { } stmt, err = Parse("SET @@session.autocommit=OFF") - if err != nil { - t.Error(err) - } + require.NoError(t, err) s, ok = stmt.(*Set) if !ok { t.Errorf("SET statement is not Set: %T", s) diff --git a/go/vt/sqlparser/comments.go b/go/vt/sqlparser/comments.go index 26c664cf916..afffd326c8c 100644 --- a/go/vt/sqlparser/comments.go +++ b/go/vt/sqlparser/comments.go @@ -123,7 +123,9 @@ func SplitMarginComments(sql string) (query string, comments MarginComments) { Leading: strings.TrimLeftFunc(sql[:leadingEnd], unicode.IsSpace), Trailing: strings.TrimRightFunc(sql[trailingStart:], unicode.IsSpace), } - return strings.TrimFunc(sql[leadingEnd:trailingStart], unicode.IsSpace), comments + return strings.TrimFunc(sql[leadingEnd:trailingStart], func(c rune) bool { + return unicode.IsSpace(c) || c == ';' + }), comments } // StripLeadingComments trims the SQL string and removes any leading comments diff --git a/go/vt/sqlparser/constants.go b/go/vt/sqlparser/constants.go new file mode 100644 index 00000000000..b194967fa3b --- /dev/null +++ b/go/vt/sqlparser/constants.go @@ -0,0 +1,163 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package sqlparser + +const ( + // Select.Distinct + DistinctStr = "distinct " + StraightJoinHint = "straight_join " + + // Select.Lock + ForUpdateStr = " for update" + ShareModeStr = " lock in share mode" + + // Select.Cache + SQLCacheStr = "sql_cache " + SQLNoCacheStr = "sql_no_cache " + + // Union.Type + UnionStr = "union" + UnionAllStr = "union all" + UnionDistinctStr = "union distinct" + + // DDL strings. + InsertStr = "insert" + ReplaceStr = "replace" + + // Set.Scope or Show.Scope + SessionStr = "session" + GlobalStr = "global" + VitessMetadataStr = "vitess_metadata" + ImplicitStr = "" + + // DDL strings. + CreateStr = "create" + AlterStr = "alter" + DropStr = "drop" + RenameStr = "rename" + TruncateStr = "truncate" + FlushStr = "flush" + CreateVindexStr = "create vindex" + DropVindexStr = "drop vindex" + AddVschemaTableStr = "add vschema table" + DropVschemaTableStr = "drop vschema table" + AddColVindexStr = "on table add vindex" + DropColVindexStr = "on table drop vindex" + AddSequenceStr = "add sequence" + AddAutoIncStr = "add auto_increment" + + // Vindex DDL param to specify the owner of a vindex + VindexOwnerStr = "owner" + + // Partition strings + ReorganizeStr = "reorganize partition" + + // JoinTableExpr.Join + JoinStr = "join" + StraightJoinStr = "straight_join" + LeftJoinStr = "left join" + RightJoinStr = "right join" + NaturalJoinStr = "natural join" + NaturalLeftJoinStr = "natural left join" + NaturalRightJoinStr = "natural right join" + + // Index hints. + UseStr = "use " + IgnoreStr = "ignore " + ForceStr = "force " + + // Where.Type + WhereStr = "where" + HavingStr = "having" + + // ComparisonExpr.Operator + EqualStr = "=" + LessThanStr = "<" + GreaterThanStr = ">" + LessEqualStr = "<=" + GreaterEqualStr = ">=" + NotEqualStr = "!=" + NullSafeEqualStr = "<=>" + InStr = "in" + NotInStr = "not in" + LikeStr = "like" + NotLikeStr = "not like" + RegexpStr = "regexp" + NotRegexpStr = "not regexp" + JSONExtractOp = "->" + JSONUnquoteExtractOp = "->>" + + // RangeCond.Operator + BetweenStr = "between" + NotBetweenStr = "not between" + + // IsExpr.Operator + IsNullStr = "is null" + IsNotNullStr = "is not null" + IsTrueStr = "is true" + IsNotTrueStr = "is not true" + IsFalseStr = "is false" + IsNotFalseStr = "is not false" + + // BinaryExpr.Operator + BitAndStr = "&" + BitOrStr = "|" + BitXorStr = "^" + PlusStr = "+" + MinusStr = "-" + MultStr = "*" + DivStr = "/" + IntDivStr = "div" + ModStr = "%" + ShiftLeftStr = "<<" + ShiftRightStr = ">>" + + // UnaryExpr.Operator + UPlusStr = "+" + UMinusStr = "-" + TildaStr = "~" + BangStr = "!" + BinaryStr = "binary " + UBinaryStr = "_binary " + Utf8mb4Str = "_utf8mb4 " + + // this string is "character set" and this comment is required + CharacterSetStr = " character set" + CharsetStr = "charset" + + // MatchExpr.Option + BooleanModeStr = " in boolean mode" + NaturalLanguageModeStr = " in natural language mode" + NaturalLanguageModeWithQueryExpansionStr = " in natural language mode with query expansion" + QueryExpansionStr = " with query expansion" + + // Order.Direction + AscScr = "asc" + DescScr = "desc" + + // SetExpr.Expr, for SET TRANSACTION ... or START TRANSACTION + // TransactionStr is the Name for a SET TRANSACTION statement + TransactionStr = "transaction" + + IsolationLevelReadUncommitted = "isolation level read uncommitted" + IsolationLevelReadCommitted = "isolation level read committed" + IsolationLevelRepeatableRead = "isolation level repeatable read" + IsolationLevelSerializable = "isolation level serializable" + + TxReadOnly = "read only" + TxReadWrite = "read write" +) diff --git a/go/vt/sqlparser/expression_rewriting.go b/go/vt/sqlparser/expression_rewriting.go new file mode 100644 index 00000000000..667c3eb6667 --- /dev/null +++ b/go/vt/sqlparser/expression_rewriting.go @@ -0,0 +1,175 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package sqlparser + +import ( + "vitess.io/vitess/go/vt/log" + querypb "vitess.io/vitess/go/vt/proto/query" + "vitess.io/vitess/go/vt/proto/vtrpc" + "vitess.io/vitess/go/vt/vterrors" +) + +// PrepareAST will normalize the query +func PrepareAST(in Statement, bindVars map[string]*querypb.BindVariable, prefix string) (*RewriteASTResult, error) { + Normalize(in, bindVars, prefix) + return RewriteAST(in) +} + +// BindVarNeeds represents the bind vars that need to be provided as the result of expression rewriting. +type BindVarNeeds struct { + NeedLastInsertID bool + NeedDatabase bool + NeedFoundRows bool +} + +// RewriteAST rewrites the whole AST, replacing function calls and adding column aliases to queries +func RewriteAST(in Statement) (*RewriteASTResult, error) { + er := newExpressionRewriter() + er.shouldRewriteDatabaseFunc = shouldRewriteDatabaseFunc(in) + Rewrite(in, er.goingDown, nil) + + r := &RewriteASTResult{ + AST: in, + } + if _, ok := er.bindVars[LastInsertIDName]; ok { + r.NeedLastInsertID = true + } + if _, ok := er.bindVars[DBVarName]; ok { + r.NeedDatabase = true + } + if _, ok := er.bindVars[FoundRowsName]; ok { + r.NeedFoundRows = true + } + + return r, nil +} + +func shouldRewriteDatabaseFunc(in Statement) bool { + selct, ok := in.(*Select) + if !ok { + return false + } + if len(selct.From) != 1 { + return false + } + aliasedTable, ok := selct.From[0].(*AliasedTableExpr) + if !ok { + return false + } + tableName, ok := aliasedTable.Expr.(TableName) + if !ok { + return false + } + return tableName.Name.String() == "dual" +} + +// RewriteASTResult contains the rewritten ast and meta information about it +type RewriteASTResult struct { + BindVarNeeds + AST Statement // The rewritten AST +} + +type expressionRewriter struct { + bindVars map[string]struct{} + shouldRewriteDatabaseFunc bool + err error +} + +func newExpressionRewriter() *expressionRewriter { + return &expressionRewriter{bindVars: make(map[string]struct{})} +} + +const ( + //LastInsertIDName is a reserved bind var name for last_insert_id() + LastInsertIDName = "__lastInsertId" + + //DBVarName is a reserved bind var name for database() + DBVarName = "__vtdbname" + + //FoundRowsName is a reserved bind var name for found_rows() + FoundRowsName = "__vtfrows" +) + +func (er *expressionRewriter) goingDown(cursor *Cursor) bool { + switch node := cursor.Node().(type) { + case *AliasedExpr: + if node.As.IsEmpty() { + buf := NewTrackedBuffer(nil) + node.Expr.Format(buf) + inner := newExpressionRewriter() + inner.shouldRewriteDatabaseFunc = er.shouldRewriteDatabaseFunc + tmp := Rewrite(node.Expr, inner.goingDown, nil) + newExpr, ok := tmp.(Expr) + if !ok { + log.Errorf("failed to rewrite AST. function expected to return Expr returned a %s", String(tmp)) + return false + } + node.Expr = newExpr + if inner.didAnythingChange() { + node.As = NewColIdent(buf.String()) + } + for k := range inner.bindVars { + er.needBindVarFor(k) + } + return false + } + + case *FuncExpr: + switch { + case node.Name.EqualString("last_insert_id"): + if len(node.Exprs) > 0 { + er.err = vterrors.New(vtrpc.Code_UNIMPLEMENTED, "Argument to LAST_INSERT_ID() not supported") + } else { + cursor.Replace(bindVarExpression(LastInsertIDName)) + er.needBindVarFor(LastInsertIDName) + } + case er.shouldRewriteDatabaseFunc && + (node.Name.EqualString("database") || + node.Name.EqualString("schema")): + if len(node.Exprs) > 0 { + er.err = vterrors.Errorf(vtrpc.Code_INVALID_ARGUMENT, "Syntax error. %s() takes no arguments", node.Name.String()) + } else { + cursor.Replace(bindVarExpression(DBVarName)) + er.needBindVarFor(DBVarName) + } + case node.Name.EqualString("found_rows"): + if len(node.Exprs) > 0 { + er.err = vterrors.New(vtrpc.Code_INVALID_ARGUMENT, "Arguments to FOUND_ROWS() not supported") + } else { + cursor.Replace(bindVarExpression(FoundRowsName)) + er.needBindVarFor(FoundRowsName) + } + } + + } + return true +} + +// instead of creating new objects, we'll reuse this one +var token = struct{}{} + +func (er *expressionRewriter) needBindVarFor(name string) { + er.bindVars[name] = token +} + +func (er *expressionRewriter) didAnythingChange() bool { + return len(er.bindVars) > 0 +} + +func bindVarExpression(name string) *SQLVal { + return NewValArg([]byte(":" + name)) +} diff --git a/go/vt/sqlparser/expression_rewriting_test.go b/go/vt/sqlparser/expression_rewriting_test.go new file mode 100644 index 00000000000..b7dd524cbbb --- /dev/null +++ b/go/vt/sqlparser/expression_rewriting_test.go @@ -0,0 +1,117 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package sqlparser + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +type myTestCase struct { + in, expected string + liid, db, foundRows bool +} + +func TestRewrites(in *testing.T) { + tests := []myTestCase{ + { + in: "SELECT 42", + expected: "SELECT 42", + db: false, liid: false, foundRows: false, + }, + { + in: "SELECT last_insert_id()", + expected: "SELECT :__lastInsertId as `last_insert_id()`", + db: false, liid: true, + }, + { + in: "SELECT database()", + expected: "SELECT :__vtdbname as `database()`", + db: true, liid: false, foundRows: false, + }, + { + in: "SELECT database() from test", + expected: "SELECT database() from test", + db: false, liid: false, + }, + { + in: "SELECT last_insert_id() as test", + expected: "SELECT :__lastInsertId as test", + db: false, liid: true, foundRows: false, + }, + { + in: "SELECT last_insert_id() + database()", + expected: "SELECT :__lastInsertId + :__vtdbname as `last_insert_id() + database()`", + db: true, liid: true, foundRows: false, + }, + { + in: "select (select database()) from test", + expected: "select (select database() from dual) from test", + db: false, liid: false, + }, + { + in: "select (select database() from dual) from test", + expected: "select (select database() from dual) from test", + db: false, liid: false, + }, + { + in: "select (select database() from dual) from dual", + expected: "select (select :__vtdbname as `database()` from dual) as `(select database() from dual)` from dual", + db: true, liid: false, foundRows: false, + }, + { + in: "select id from user where database()", + expected: "select id from user where database()", + db: false, liid: false, + }, + { + in: "select table_name from information_schema.tables where table_schema = database()", + expected: "select table_name from information_schema.tables where table_schema = database()", + db: false, liid: false, foundRows: false, + }, + { + in: "select schema()", + expected: "select :__vtdbname as 'schema()'", + db: true, liid: false, foundRows: false, + }, + { + in: "select found_rows()", + expected: "select :__vtfrows as 'found_rows()'", + db: false, liid: false, foundRows: true, + }, + } + + for _, tc := range tests { + in.Run(tc.in, func(t *testing.T) { + stmt, err := Parse(tc.in) + require.NoError(t, err) + + result, err := RewriteAST(stmt) + require.NoError(t, err) + + expected, err := Parse(tc.expected) + require.NoError(t, err) + + s := String(expected) + require.Equal(t, s, String(result.AST)) + require.Equal(t, tc.liid, result.NeedLastInsertID, "should need last insert id") + require.Equal(t, tc.db, result.NeedDatabase, "should need database name") + require.Equal(t, tc.foundRows, result.NeedFoundRows, "should need found rows") + }) + } +} diff --git a/go/vt/sqlparser/normalizer_test.go b/go/vt/sqlparser/normalizer_test.go index 196f2a5d02f..6b4a0cca83c 100644 --- a/go/vt/sqlparser/normalizer_test.go +++ b/go/vt/sqlparser/normalizer_test.go @@ -38,6 +38,13 @@ func TestNormalize(t *testing.T) { outbv: map[string]*querypb.BindVariable{ "bv1": sqltypes.BytesBindVariable([]byte("aa")), }, + }, { + // str val in select + in: "select 'aa' from t", + outstmt: "select :bv1 from t", + outbv: map[string]*querypb.BindVariable{ + "bv1": sqltypes.BytesBindVariable([]byte("aa")), + }, }, { // int val in: "select * from t where v1 = 1", diff --git a/go/vt/sqlparser/parse_test.go b/go/vt/sqlparser/parse_test.go index 564edccefc5..2ba6a02cf05 100644 --- a/go/vt/sqlparser/parse_test.go +++ b/go/vt/sqlparser/parse_test.go @@ -196,6 +196,8 @@ var ( input: "select /* parenthessis in table list 2 */ 1 from t1, (t2)", }, { input: "select /* use */ 1 from t1 use index (a) where b = 1", + }, { + input: "select /* use */ 1 from t1 use index () where b = 1", }, { input: "select /* keyword index */ 1 from t1 use index (`By`) where b = 1", }, { @@ -425,6 +427,9 @@ var ( input: "select /* function with many params */ 1 from t where a = b(c, d)", }, { input: "select /* function with distinct */ count(distinct a) from t", + }, { + input: "select count(distinctrow(1)) from (select (1) from dual union all select 1 from dual) a", + output: "select count(distinct (1)) from (select (1) from dual union all select 1 from dual) as a", }, { input: "select /* if as func */ 1 from t where a = if(b)", }, { @@ -808,6 +813,10 @@ var ( input: "set tx_read_only = 1", }, { input: "set tx_read_only = 0", + }, { + input: "set transaction_read_only = 1", + }, { + input: "set transaction_read_only = 0", }, { input: "set tx_isolation = 'repeatable read'", }, { @@ -958,6 +967,30 @@ var ( }, { input: "alter table a drop id", output: "alter table a", + }, { + input: "alter database d default character set = charset", + output: "alter database d", + }, { + input: "alter database d character set = charset", + output: "alter database d", + }, { + input: "alter database d default collate = collation", + output: "alter database d", + }, { + input: "alter database d collate = collation", + output: "alter database d", + }, { + input: "alter schema d default character set = charset", + output: "alter database d", + }, { + input: "alter schema d character set = charset", + output: "alter database d", + }, { + input: "alter schema d default collate = collation", + output: "alter database d", + }, { + input: "alter schema d collate = collation", + output: "alter database d", }, { input: "create table a", }, { @@ -1111,13 +1144,19 @@ var ( output: "show charset", }, { input: "show character set like '%foo'", - output: "show charset", + output: "show charset like '%foo'", }, { input: "show charset", output: "show charset", }, { input: "show charset like '%foo'", - output: "show charset", + output: "show charset like '%foo'", + }, { + input: "show charset where 'charset' = 'utf8'", + output: "show charset where 'charset' = 'utf8'", + }, { + input: "show charset where 'charset' = '%foo'", + output: "show charset where 'charset' = '%foo'", }, { input: "show collation", output: "show collation", @@ -1412,12 +1451,22 @@ var ( input: "select match(a) against ('foo') from t", }, { input: "select match(a1, a2) against ('foo' in natural language mode with query expansion) from t", + }, { + input: "select database()", + output: "select database() from dual", + }, { + input: "select schema()", + output: "select schema() from dual", }, { input: "select title from video as v where match(v.title, v.tag) against ('DEMO' in boolean mode)", }, { input: "select name, group_concat(score) from t group by name", }, { input: "select name, group_concat(distinct id, score order by id desc separator ':') from t group by name", + }, { + input: "select name, group_concat(distinct id, score order by id desc separator ':' limit 1) from t group by name", + }, { + input: "select name, group_concat(distinct id, score order by id desc separator ':' limit 10, 2) from t group by name", }, { input: "select * from t partition (p0)", }, { @@ -1442,6 +1491,9 @@ var ( input: "stream /* comment */ * from t", }, { input: "begin", + }, { + input: "begin;", + output: "begin", }, { input: "start transaction", output: "begin", @@ -1468,35 +1520,46 @@ var ( }, { input: "delete a.*, b.* from tbl_a a, tbl_b b where a.id = b.id and b.name = 'test'", output: "delete a, b from tbl_a as a, tbl_b as b where a.id = b.id and b.name = 'test'", + }, { + input: "select distinctrow a.* from (select (1) from dual union all select 1 from dual) a", + output: "select distinct a.* from (select (1) from dual union all select 1 from dual) as a", + }, { + input: "select `weird function name`() from t", + }, { + input: "select status() from t", // should not escape function names that are keywords + }, { + input: "select * from `weird table name`", }} ) func TestValid(t *testing.T) { for _, tcase := range validSQL { - if tcase.output == "" { - tcase.output = tcase.input - } - tree, err := Parse(tcase.input) - if err != nil { - t.Errorf("Parse(%q) err: %v, want nil", tcase.input, err) - continue - } - out := String(tree) - if out != tcase.output { - t.Errorf("Parse(%q) = %q, want: %q", tcase.input, out, tcase.output) - } - // This test just exercises the tree walking functionality. - // There's no way automated way to verify that a node calls - // all its children. But we can examine code coverage and - // ensure that all walkSubtree functions were called. - Walk(func(node SQLNode) (bool, error) { - return true, nil - }, tree) + t.Run(tcase.input, func(t *testing.T) { + if tcase.output == "" { + tcase.output = tcase.input + } + tree, err := Parse(tcase.input) + if err != nil { + t.Errorf("Parse(%q) err: %v, want nil", tcase.input, err) + return + } + out := String(tree) + if out != tcase.output { + t.Errorf("Parse(%q) = %q, want: %q", tcase.input, out, tcase.output) + } + // This test just exercises the tree walking functionality. + // There's no way automated way to verify that a node calls + // all its children. But we can examine code coverage and + // ensure that all walkSubtree functions were called. + Walk(func(node SQLNode) (bool, error) { + return true, nil + }, tree) + }) } } // Ensure there is no corruption from using a pooled yyParserImpl in Parse. -func TestValidParallel(t *testing.T) { +func TestParallelValid(t *testing.T) { parallelism := 100 numIters := 1000 @@ -1724,9 +1787,15 @@ func TestKeywords(t *testing.T) { }, { input: "select status from t", output: "select `status` from t", + }, { + input: "select Status from t", + output: "select `Status` from t", }, { input: "select variables from t", output: "select `variables` from t", + }, { + input: "select Variables from t", + output: "select `Variables` from t", }} for _, tcase := range validSQL { @@ -1851,6 +1920,45 @@ func TestConvert(t *testing.T) { } } +func TestPositionedErr(t *testing.T) { + invalidSQL := []struct { + input string + output PositionedErr + }{{ + input: "select convert('abc' as date) from t", + output: PositionedErr{"syntax error", 24, []byte("as")}, + }, { + input: "select convert from t", + output: PositionedErr{"syntax error", 20, []byte("from")}, + }, { + input: "select cast('foo', decimal) from t", + output: PositionedErr{"syntax error", 19, nil}, + }, { + input: "select convert('abc', datetime(4+9)) from t", + output: PositionedErr{"syntax error", 34, nil}, + }, { + input: "select convert('abc', decimal(4+9)) from t", + output: PositionedErr{"syntax error", 33, nil}, + }, { + input: "set transaction isolation level 12345", + output: PositionedErr{"syntax error", 38, []byte("12345")}, + }, { + input: "select * from a left join b", + output: PositionedErr{"syntax error", 28, nil}, + }} + + for _, tcase := range invalidSQL { + tkn := NewStringTokenizer(tcase.input) + _, err := ParseNext(tkn) + + if posErr, ok := err.(PositionedErr); !ok { + t.Errorf("%s: %v expected PositionedErr, got (%T) %v", tcase.input, err, err, tcase.output) + } else if posErr.Pos != tcase.output.Pos || !bytes.Equal(posErr.Near, tcase.output.Near) || err.Error() != tcase.output.Error() { + t.Errorf("%s: %v, want: %v", tcase.input, err, tcase.output) + } + } +} + func TestSubStr(t *testing.T) { validSQL := []struct { @@ -2547,10 +2655,10 @@ func TestSkipToEnd(t *testing.T) { func TestParseDjangoQueries(t *testing.T) { file, err := os.Open("./test_queries/django_queries.txt") - defer file.Close() if err != nil { t.Errorf(" Error: %v", err) } + defer file.Close() scanner := bufio.NewScanner(file) for scanner.Scan() { diff --git a/go/vt/sqlparser/parser.go b/go/vt/sqlparser/parser.go new file mode 100644 index 00000000000..1885a408a70 --- /dev/null +++ b/go/vt/sqlparser/parser.go @@ -0,0 +1,222 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package sqlparser + +import ( + "errors" + "fmt" + "io" + "sync" + + "vitess.io/vitess/go/vt/log" + "vitess.io/vitess/go/vt/vterrors" + + vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" +) + +// parserPool is a pool for parser objects. +var parserPool = sync.Pool{} + +// zeroParser is a zero-initialized parser to help reinitialize the parser for pooling. +var zeroParser = *(yyNewParser().(*yyParserImpl)) + +// yyParsePooled is a wrapper around yyParse that pools the parser objects. There isn't a +// particularly good reason to use yyParse directly, since it immediately discards its parser. What +// would be ideal down the line is to actually pool the stacks themselves rather than the parser +// objects, as per https://github.com/cznic/goyacc/blob/master/main.go. However, absent an upstream +// change to goyacc, this is the next best option. +// +// N.B: Parser pooling means that you CANNOT take references directly to parse stack variables (e.g. +// $$ = &$4) in sql.y rules. You must instead add an intermediate reference like so: +// showCollationFilterOpt := $4 +// $$ = &Show{Type: string($2), ShowCollationFilterOpt: &showCollationFilterOpt} +func yyParsePooled(yylex yyLexer) int { + // Being very particular about using the base type and not an interface type b/c we depend on + // the implementation to know how to reinitialize the parser. + var parser *yyParserImpl + + i := parserPool.Get() + if i != nil { + parser = i.(*yyParserImpl) + } else { + parser = yyNewParser().(*yyParserImpl) + } + + defer func() { + *parser = zeroParser + parserPool.Put(parser) + }() + return parser.Parse(yylex) +} + +// Instructions for creating new types: If a type +// needs to satisfy an interface, declare that function +// along with that interface. This will help users +// identify the list of types to which they can assert +// those interfaces. +// If the member of a type has a string with a predefined +// list of values, declare those values as const following +// the type. +// For interfaces that define dummy functions to consolidate +// a set of types, define the function as iTypeName. +// This will help avoid name collisions. + +// Parse parses the SQL in full and returns a Statement, which +// is the AST representation of the query. If a DDL statement +// is partially parsed but still contains a syntax error, the +// error is ignored and the DDL is returned anyway. +func Parse(sql string) (Statement, error) { + tokenizer := NewStringTokenizer(sql) + if yyParsePooled(tokenizer) != 0 { + if tokenizer.partialDDL != nil { + if typ, val := tokenizer.Scan(); typ != 0 { + return nil, fmt.Errorf("extra characters encountered after end of DDL: '%s'", string(val)) + } + log.Warningf("ignoring error parsing DDL '%s': %v", sql, tokenizer.LastError) + tokenizer.ParseTree = tokenizer.partialDDL + return tokenizer.ParseTree, nil + } + return nil, vterrors.New(vtrpcpb.Code_INVALID_ARGUMENT, tokenizer.LastError.Error()) + } + if tokenizer.ParseTree == nil { + return nil, ErrEmpty + } + return tokenizer.ParseTree, nil +} + +// ParseStrictDDL is the same as Parse except it errors on +// partially parsed DDL statements. +func ParseStrictDDL(sql string) (Statement, error) { + tokenizer := NewStringTokenizer(sql) + if yyParsePooled(tokenizer) != 0 { + return nil, tokenizer.LastError + } + if tokenizer.ParseTree == nil { + return nil, ErrEmpty + } + return tokenizer.ParseTree, nil +} + +// ParseTokenizer is a raw interface to parse from the given tokenizer. +// This does not used pooled parsers, and should not be used in general. +func ParseTokenizer(tokenizer *Tokenizer) int { + return yyParse(tokenizer) +} + +// ParseNext parses a single SQL statement from the tokenizer +// returning a Statement which is the AST representation of the query. +// The tokenizer will always read up to the end of the statement, allowing for +// the next call to ParseNext to parse any subsequent SQL statements. When +// there are no more statements to parse, a error of io.EOF is returned. +func ParseNext(tokenizer *Tokenizer) (Statement, error) { + return parseNext(tokenizer, false) +} + +// ParseNextStrictDDL is the same as ParseNext except it errors on +// partially parsed DDL statements. +func ParseNextStrictDDL(tokenizer *Tokenizer) (Statement, error) { + return parseNext(tokenizer, true) +} + +func parseNext(tokenizer *Tokenizer, strict bool) (Statement, error) { + if tokenizer.lastChar == ';' { + tokenizer.next() + tokenizer.skipBlank() + } + if tokenizer.lastChar == eofChar { + return nil, io.EOF + } + + tokenizer.reset() + tokenizer.multi = true + if yyParsePooled(tokenizer) != 0 { + if tokenizer.partialDDL != nil && !strict { + tokenizer.ParseTree = tokenizer.partialDDL + return tokenizer.ParseTree, nil + } + return nil, tokenizer.LastError + } + if tokenizer.ParseTree == nil { + return ParseNext(tokenizer) + } + return tokenizer.ParseTree, nil +} + +// ErrEmpty is a sentinel error returned when parsing empty statements. +var ErrEmpty = errors.New("empty statement") + +// SplitStatement returns the first sql statement up to either a ; or EOF +// and the remainder from the given buffer +func SplitStatement(blob string) (string, string, error) { + tokenizer := NewStringTokenizer(blob) + tkn := 0 + for { + tkn, _ = tokenizer.Scan() + if tkn == 0 || tkn == ';' || tkn == eofChar { + break + } + } + if tokenizer.LastError != nil { + return "", "", tokenizer.LastError + } + if tkn == ';' { + return blob[:tokenizer.Position-2], blob[tokenizer.Position-1:], nil + } + return blob, "", nil +} + +// SplitStatementToPieces split raw sql statement that may have multi sql pieces to sql pieces +// returns the sql pieces blob contains; or error if sql cannot be parsed +func SplitStatementToPieces(blob string) (pieces []string, err error) { + pieces = make([]string, 0, 16) + tokenizer := NewStringTokenizer(blob) + + tkn := 0 + var stmt string + stmtBegin := 0 + for { + tkn, _ = tokenizer.Scan() + if tkn == ';' { + stmt = blob[stmtBegin : tokenizer.Position-2] + pieces = append(pieces, stmt) + stmtBegin = tokenizer.Position - 1 + + } else if tkn == 0 || tkn == eofChar { + blobTail := tokenizer.Position - 2 + + if stmtBegin < blobTail { + stmt = blob[stmtBegin : blobTail+1] + pieces = append(pieces, stmt) + } + break + } + } + + err = tokenizer.LastError + return +} + +// String returns a string representation of an SQLNode. +func String(node SQLNode) string { + if node == nil { + return "" + } + + buf := NewTrackedBuffer(nil) + buf.Myprintf("%v", node) + return buf.String() +} diff --git a/go/vt/sqlparser/rewriter.go b/go/vt/sqlparser/rewriter.go new file mode 100644 index 00000000000..3b912a79bb8 --- /dev/null +++ b/go/vt/sqlparser/rewriter.go @@ -0,0 +1,1325 @@ +// Code generated by visitorgen/main/main.go. DO NOT EDIT. + +package sqlparser + +//go:generate go run ./visitorgen/main -input=ast.go -output=rewriter.go + +import ( + "reflect" +) + +type replacerFunc func(newNode, parent SQLNode) + +// application carries all the shared data so we can pass it around cheaply. +type application struct { + pre, post ApplyFunc + cursor Cursor +} + +func replaceAliasedExprAs(newNode, parent SQLNode) { + parent.(*AliasedExpr).As = newNode.(ColIdent) +} + +func replaceAliasedExprExpr(newNode, parent SQLNode) { + parent.(*AliasedExpr).Expr = newNode.(Expr) +} + +func replaceAliasedTableExprAs(newNode, parent SQLNode) { + parent.(*AliasedTableExpr).As = newNode.(TableIdent) +} + +func replaceAliasedTableExprExpr(newNode, parent SQLNode) { + parent.(*AliasedTableExpr).Expr = newNode.(SimpleTableExpr) +} + +func replaceAliasedTableExprHints(newNode, parent SQLNode) { + parent.(*AliasedTableExpr).Hints = newNode.(*IndexHints) +} + +func replaceAliasedTableExprPartitions(newNode, parent SQLNode) { + parent.(*AliasedTableExpr).Partitions = newNode.(Partitions) +} + +func replaceAndExprLeft(newNode, parent SQLNode) { + parent.(*AndExpr).Left = newNode.(Expr) +} + +func replaceAndExprRight(newNode, parent SQLNode) { + parent.(*AndExpr).Right = newNode.(Expr) +} + +func replaceAutoIncSpecColumn(newNode, parent SQLNode) { + parent.(*AutoIncSpec).Column = newNode.(ColIdent) +} + +func replaceAutoIncSpecSequence(newNode, parent SQLNode) { + parent.(*AutoIncSpec).Sequence = newNode.(TableName) +} + +func replaceBinaryExprLeft(newNode, parent SQLNode) { + parent.(*BinaryExpr).Left = newNode.(Expr) +} + +func replaceBinaryExprRight(newNode, parent SQLNode) { + parent.(*BinaryExpr).Right = newNode.(Expr) +} + +func replaceCaseExprElse(newNode, parent SQLNode) { + parent.(*CaseExpr).Else = newNode.(Expr) +} + +func replaceCaseExprExpr(newNode, parent SQLNode) { + parent.(*CaseExpr).Expr = newNode.(Expr) +} + +type replaceCaseExprWhens int + +func (r *replaceCaseExprWhens) replace(newNode, container SQLNode) { + container.(*CaseExpr).Whens[int(*r)] = newNode.(*When) +} + +func (r *replaceCaseExprWhens) inc() { + *r++ +} + +func replaceColNameName(newNode, parent SQLNode) { + parent.(*ColName).Name = newNode.(ColIdent) +} + +func replaceColNameQualifier(newNode, parent SQLNode) { + parent.(*ColName).Qualifier = newNode.(TableName) +} + +func replaceCollateExprExpr(newNode, parent SQLNode) { + parent.(*CollateExpr).Expr = newNode.(Expr) +} + +func replaceColumnDefinitionName(newNode, parent SQLNode) { + parent.(*ColumnDefinition).Name = newNode.(ColIdent) +} + +func replaceColumnTypeAutoincrement(newNode, parent SQLNode) { + parent.(*ColumnType).Autoincrement = newNode.(BoolVal) +} + +func replaceColumnTypeComment(newNode, parent SQLNode) { + parent.(*ColumnType).Comment = newNode.(*SQLVal) +} + +func replaceColumnTypeDefault(newNode, parent SQLNode) { + parent.(*ColumnType).Default = newNode.(Expr) +} + +func replaceColumnTypeLength(newNode, parent SQLNode) { + parent.(*ColumnType).Length = newNode.(*SQLVal) +} + +func replaceColumnTypeNotNull(newNode, parent SQLNode) { + parent.(*ColumnType).NotNull = newNode.(BoolVal) +} + +func replaceColumnTypeOnUpdate(newNode, parent SQLNode) { + parent.(*ColumnType).OnUpdate = newNode.(Expr) +} + +func replaceColumnTypeScale(newNode, parent SQLNode) { + parent.(*ColumnType).Scale = newNode.(*SQLVal) +} + +func replaceColumnTypeUnsigned(newNode, parent SQLNode) { + parent.(*ColumnType).Unsigned = newNode.(BoolVal) +} + +func replaceColumnTypeZerofill(newNode, parent SQLNode) { + parent.(*ColumnType).Zerofill = newNode.(BoolVal) +} + +type replaceColumnsItems int + +func (r *replaceColumnsItems) replace(newNode, container SQLNode) { + container.(Columns)[int(*r)] = newNode.(ColIdent) +} + +func (r *replaceColumnsItems) inc() { + *r++ +} + +func replaceComparisonExprEscape(newNode, parent SQLNode) { + parent.(*ComparisonExpr).Escape = newNode.(Expr) +} + +func replaceComparisonExprLeft(newNode, parent SQLNode) { + parent.(*ComparisonExpr).Left = newNode.(Expr) +} + +func replaceComparisonExprRight(newNode, parent SQLNode) { + parent.(*ComparisonExpr).Right = newNode.(Expr) +} + +func replaceConstraintDefinitionDetails(newNode, parent SQLNode) { + parent.(*ConstraintDefinition).Details = newNode.(ConstraintInfo) +} + +func replaceConvertExprExpr(newNode, parent SQLNode) { + parent.(*ConvertExpr).Expr = newNode.(Expr) +} + +func replaceConvertExprType(newNode, parent SQLNode) { + parent.(*ConvertExpr).Type = newNode.(*ConvertType) +} + +func replaceConvertTypeLength(newNode, parent SQLNode) { + parent.(*ConvertType).Length = newNode.(*SQLVal) +} + +func replaceConvertTypeScale(newNode, parent SQLNode) { + parent.(*ConvertType).Scale = newNode.(*SQLVal) +} + +func replaceConvertUsingExprExpr(newNode, parent SQLNode) { + parent.(*ConvertUsingExpr).Expr = newNode.(Expr) +} + +func replaceCurTimeFuncExprFsp(newNode, parent SQLNode) { + parent.(*CurTimeFuncExpr).Fsp = newNode.(Expr) +} + +func replaceCurTimeFuncExprName(newNode, parent SQLNode) { + parent.(*CurTimeFuncExpr).Name = newNode.(ColIdent) +} + +func replaceDDLAutoIncSpec(newNode, parent SQLNode) { + parent.(*DDL).AutoIncSpec = newNode.(*AutoIncSpec) +} + +func replaceDDLFromTables(newNode, parent SQLNode) { + parent.(*DDL).FromTables = newNode.(TableNames) +} + +func replaceDDLOptLike(newNode, parent SQLNode) { + parent.(*DDL).OptLike = newNode.(*OptLike) +} + +func replaceDDLPartitionSpec(newNode, parent SQLNode) { + parent.(*DDL).PartitionSpec = newNode.(*PartitionSpec) +} + +func replaceDDLTable(newNode, parent SQLNode) { + parent.(*DDL).Table = newNode.(TableName) +} + +func replaceDDLTableSpec(newNode, parent SQLNode) { + parent.(*DDL).TableSpec = newNode.(*TableSpec) +} + +func replaceDDLToTables(newNode, parent SQLNode) { + parent.(*DDL).ToTables = newNode.(TableNames) +} + +type replaceDDLVindexCols int + +func (r *replaceDDLVindexCols) replace(newNode, container SQLNode) { + container.(*DDL).VindexCols[int(*r)] = newNode.(ColIdent) +} + +func (r *replaceDDLVindexCols) inc() { + *r++ +} + +func replaceDDLVindexSpec(newNode, parent SQLNode) { + parent.(*DDL).VindexSpec = newNode.(*VindexSpec) +} + +func replaceDeleteComments(newNode, parent SQLNode) { + parent.(*Delete).Comments = newNode.(Comments) +} + +func replaceDeleteLimit(newNode, parent SQLNode) { + parent.(*Delete).Limit = newNode.(*Limit) +} + +func replaceDeleteOrderBy(newNode, parent SQLNode) { + parent.(*Delete).OrderBy = newNode.(OrderBy) +} + +func replaceDeletePartitions(newNode, parent SQLNode) { + parent.(*Delete).Partitions = newNode.(Partitions) +} + +func replaceDeleteTableExprs(newNode, parent SQLNode) { + parent.(*Delete).TableExprs = newNode.(TableExprs) +} + +func replaceDeleteTargets(newNode, parent SQLNode) { + parent.(*Delete).Targets = newNode.(TableNames) +} + +func replaceDeleteWhere(newNode, parent SQLNode) { + parent.(*Delete).Where = newNode.(*Where) +} + +func replaceExistsExprSubquery(newNode, parent SQLNode) { + parent.(*ExistsExpr).Subquery = newNode.(*Subquery) +} + +type replaceExprsItems int + +func (r *replaceExprsItems) replace(newNode, container SQLNode) { + container.(Exprs)[int(*r)] = newNode.(Expr) +} + +func (r *replaceExprsItems) inc() { + *r++ +} + +func replaceForeignKeyDefinitionOnDelete(newNode, parent SQLNode) { + parent.(*ForeignKeyDefinition).OnDelete = newNode.(ReferenceAction) +} + +func replaceForeignKeyDefinitionOnUpdate(newNode, parent SQLNode) { + parent.(*ForeignKeyDefinition).OnUpdate = newNode.(ReferenceAction) +} + +func replaceForeignKeyDefinitionReferencedColumns(newNode, parent SQLNode) { + parent.(*ForeignKeyDefinition).ReferencedColumns = newNode.(Columns) +} + +func replaceForeignKeyDefinitionReferencedTable(newNode, parent SQLNode) { + parent.(*ForeignKeyDefinition).ReferencedTable = newNode.(TableName) +} + +func replaceForeignKeyDefinitionSource(newNode, parent SQLNode) { + parent.(*ForeignKeyDefinition).Source = newNode.(Columns) +} + +func replaceFuncExprExprs(newNode, parent SQLNode) { + parent.(*FuncExpr).Exprs = newNode.(SelectExprs) +} + +func replaceFuncExprName(newNode, parent SQLNode) { + parent.(*FuncExpr).Name = newNode.(ColIdent) +} + +func replaceFuncExprQualifier(newNode, parent SQLNode) { + parent.(*FuncExpr).Qualifier = newNode.(TableIdent) +} + +type replaceGroupByItems int + +func (r *replaceGroupByItems) replace(newNode, container SQLNode) { + container.(GroupBy)[int(*r)] = newNode.(Expr) +} + +func (r *replaceGroupByItems) inc() { + *r++ +} + +func replaceGroupConcatExprExprs(newNode, parent SQLNode) { + parent.(*GroupConcatExpr).Exprs = newNode.(SelectExprs) +} + +func replaceGroupConcatExprLimit(newNode, parent SQLNode) { + parent.(*GroupConcatExpr).Limit = newNode.(*Limit) +} + +func replaceGroupConcatExprOrderBy(newNode, parent SQLNode) { + parent.(*GroupConcatExpr).OrderBy = newNode.(OrderBy) +} + +func replaceIndexDefinitionInfo(newNode, parent SQLNode) { + parent.(*IndexDefinition).Info = newNode.(*IndexInfo) +} + +type replaceIndexHintsIndexes int + +func (r *replaceIndexHintsIndexes) replace(newNode, container SQLNode) { + container.(*IndexHints).Indexes[int(*r)] = newNode.(ColIdent) +} + +func (r *replaceIndexHintsIndexes) inc() { + *r++ +} + +func replaceIndexInfoName(newNode, parent SQLNode) { + parent.(*IndexInfo).Name = newNode.(ColIdent) +} + +func replaceInsertColumns(newNode, parent SQLNode) { + parent.(*Insert).Columns = newNode.(Columns) +} + +func replaceInsertComments(newNode, parent SQLNode) { + parent.(*Insert).Comments = newNode.(Comments) +} + +func replaceInsertOnDup(newNode, parent SQLNode) { + parent.(*Insert).OnDup = newNode.(OnDup) +} + +func replaceInsertPartitions(newNode, parent SQLNode) { + parent.(*Insert).Partitions = newNode.(Partitions) +} + +func replaceInsertRows(newNode, parent SQLNode) { + parent.(*Insert).Rows = newNode.(InsertRows) +} + +func replaceInsertTable(newNode, parent SQLNode) { + parent.(*Insert).Table = newNode.(TableName) +} + +func replaceIntervalExprExpr(newNode, parent SQLNode) { + parent.(*IntervalExpr).Expr = newNode.(Expr) +} + +func replaceIsExprExpr(newNode, parent SQLNode) { + parent.(*IsExpr).Expr = newNode.(Expr) +} + +func replaceJoinConditionOn(newNode, parent SQLNode) { + tmp := parent.(JoinCondition) + tmp.On = newNode.(Expr) +} + +func replaceJoinConditionUsing(newNode, parent SQLNode) { + tmp := parent.(JoinCondition) + tmp.Using = newNode.(Columns) +} + +func replaceJoinTableExprCondition(newNode, parent SQLNode) { + parent.(*JoinTableExpr).Condition = newNode.(JoinCondition) +} + +func replaceJoinTableExprLeftExpr(newNode, parent SQLNode) { + parent.(*JoinTableExpr).LeftExpr = newNode.(TableExpr) +} + +func replaceJoinTableExprRightExpr(newNode, parent SQLNode) { + parent.(*JoinTableExpr).RightExpr = newNode.(TableExpr) +} + +func replaceLimitOffset(newNode, parent SQLNode) { + parent.(*Limit).Offset = newNode.(Expr) +} + +func replaceLimitRowcount(newNode, parent SQLNode) { + parent.(*Limit).Rowcount = newNode.(Expr) +} + +func replaceMatchExprColumns(newNode, parent SQLNode) { + parent.(*MatchExpr).Columns = newNode.(SelectExprs) +} + +func replaceMatchExprExpr(newNode, parent SQLNode) { + parent.(*MatchExpr).Expr = newNode.(Expr) +} + +func replaceNextvalExpr(newNode, parent SQLNode) { + tmp := parent.(Nextval) + tmp.Expr = newNode.(Expr) +} + +func replaceNotExprExpr(newNode, parent SQLNode) { + parent.(*NotExpr).Expr = newNode.(Expr) +} + +type replaceOnDupItems int + +func (r *replaceOnDupItems) replace(newNode, container SQLNode) { + container.(OnDup)[int(*r)] = newNode.(*UpdateExpr) +} + +func (r *replaceOnDupItems) inc() { + *r++ +} + +func replaceOptLikeLikeTable(newNode, parent SQLNode) { + parent.(*OptLike).LikeTable = newNode.(TableName) +} + +func replaceOrExprLeft(newNode, parent SQLNode) { + parent.(*OrExpr).Left = newNode.(Expr) +} + +func replaceOrExprRight(newNode, parent SQLNode) { + parent.(*OrExpr).Right = newNode.(Expr) +} + +func replaceOrderExpr(newNode, parent SQLNode) { + parent.(*Order).Expr = newNode.(Expr) +} + +type replaceOrderByItems int + +func (r *replaceOrderByItems) replace(newNode, container SQLNode) { + container.(OrderBy)[int(*r)] = newNode.(*Order) +} + +func (r *replaceOrderByItems) inc() { + *r++ +} + +func replaceParenExprExpr(newNode, parent SQLNode) { + parent.(*ParenExpr).Expr = newNode.(Expr) +} + +func replaceParenSelectSelect(newNode, parent SQLNode) { + parent.(*ParenSelect).Select = newNode.(SelectStatement) +} + +func replaceParenTableExprExprs(newNode, parent SQLNode) { + parent.(*ParenTableExpr).Exprs = newNode.(TableExprs) +} + +func replacePartitionDefinitionLimit(newNode, parent SQLNode) { + parent.(*PartitionDefinition).Limit = newNode.(Expr) +} + +func replacePartitionDefinitionName(newNode, parent SQLNode) { + parent.(*PartitionDefinition).Name = newNode.(ColIdent) +} + +type replacePartitionSpecDefinitions int + +func (r *replacePartitionSpecDefinitions) replace(newNode, container SQLNode) { + container.(*PartitionSpec).Definitions[int(*r)] = newNode.(*PartitionDefinition) +} + +func (r *replacePartitionSpecDefinitions) inc() { + *r++ +} + +func replacePartitionSpecName(newNode, parent SQLNode) { + parent.(*PartitionSpec).Name = newNode.(ColIdent) +} + +type replacePartitionsItems int + +func (r *replacePartitionsItems) replace(newNode, container SQLNode) { + container.(Partitions)[int(*r)] = newNode.(ColIdent) +} + +func (r *replacePartitionsItems) inc() { + *r++ +} + +func replaceRangeCondFrom(newNode, parent SQLNode) { + parent.(*RangeCond).From = newNode.(Expr) +} + +func replaceRangeCondLeft(newNode, parent SQLNode) { + parent.(*RangeCond).Left = newNode.(Expr) +} + +func replaceRangeCondTo(newNode, parent SQLNode) { + parent.(*RangeCond).To = newNode.(Expr) +} + +func replaceSelectComments(newNode, parent SQLNode) { + parent.(*Select).Comments = newNode.(Comments) +} + +func replaceSelectFrom(newNode, parent SQLNode) { + parent.(*Select).From = newNode.(TableExprs) +} + +func replaceSelectGroupBy(newNode, parent SQLNode) { + parent.(*Select).GroupBy = newNode.(GroupBy) +} + +func replaceSelectHaving(newNode, parent SQLNode) { + parent.(*Select).Having = newNode.(*Where) +} + +func replaceSelectLimit(newNode, parent SQLNode) { + parent.(*Select).Limit = newNode.(*Limit) +} + +func replaceSelectOrderBy(newNode, parent SQLNode) { + parent.(*Select).OrderBy = newNode.(OrderBy) +} + +func replaceSelectSelectExprs(newNode, parent SQLNode) { + parent.(*Select).SelectExprs = newNode.(SelectExprs) +} + +func replaceSelectWhere(newNode, parent SQLNode) { + parent.(*Select).Where = newNode.(*Where) +} + +type replaceSelectExprsItems int + +func (r *replaceSelectExprsItems) replace(newNode, container SQLNode) { + container.(SelectExprs)[int(*r)] = newNode.(SelectExpr) +} + +func (r *replaceSelectExprsItems) inc() { + *r++ +} + +func replaceSetComments(newNode, parent SQLNode) { + parent.(*Set).Comments = newNode.(Comments) +} + +func replaceSetExprs(newNode, parent SQLNode) { + parent.(*Set).Exprs = newNode.(SetExprs) +} + +func replaceSetExprExpr(newNode, parent SQLNode) { + parent.(*SetExpr).Expr = newNode.(Expr) +} + +func replaceSetExprName(newNode, parent SQLNode) { + parent.(*SetExpr).Name = newNode.(ColIdent) +} + +type replaceSetExprsItems int + +func (r *replaceSetExprsItems) replace(newNode, container SQLNode) { + container.(SetExprs)[int(*r)] = newNode.(*SetExpr) +} + +func (r *replaceSetExprsItems) inc() { + *r++ +} + +func replaceShowOnTable(newNode, parent SQLNode) { + parent.(*Show).OnTable = newNode.(TableName) +} + +func replaceShowTable(newNode, parent SQLNode) { + parent.(*Show).Table = newNode.(TableName) +} + +func replaceShowFilterFilter(newNode, parent SQLNode) { + parent.(*ShowFilter).Filter = newNode.(Expr) +} + +func replaceStarExprTableName(newNode, parent SQLNode) { + parent.(*StarExpr).TableName = newNode.(TableName) +} + +func replaceStreamComments(newNode, parent SQLNode) { + parent.(*Stream).Comments = newNode.(Comments) +} + +func replaceStreamSelectExpr(newNode, parent SQLNode) { + parent.(*Stream).SelectExpr = newNode.(SelectExpr) +} + +func replaceStreamTable(newNode, parent SQLNode) { + parent.(*Stream).Table = newNode.(TableName) +} + +func replaceSubquerySelect(newNode, parent SQLNode) { + parent.(*Subquery).Select = newNode.(SelectStatement) +} + +func replaceSubstrExprFrom(newNode, parent SQLNode) { + parent.(*SubstrExpr).From = newNode.(Expr) +} + +func replaceSubstrExprName(newNode, parent SQLNode) { + parent.(*SubstrExpr).Name = newNode.(*ColName) +} + +func replaceSubstrExprStrVal(newNode, parent SQLNode) { + parent.(*SubstrExpr).StrVal = newNode.(*SQLVal) +} + +func replaceSubstrExprTo(newNode, parent SQLNode) { + parent.(*SubstrExpr).To = newNode.(Expr) +} + +type replaceTableExprsItems int + +func (r *replaceTableExprsItems) replace(newNode, container SQLNode) { + container.(TableExprs)[int(*r)] = newNode.(TableExpr) +} + +func (r *replaceTableExprsItems) inc() { + *r++ +} + +func replaceTableNameName(newNode, parent SQLNode) { + tmp := parent.(TableName) + tmp.Name = newNode.(TableIdent) +} + +func replaceTableNameQualifier(newNode, parent SQLNode) { + tmp := parent.(TableName) + tmp.Qualifier = newNode.(TableIdent) +} + +type replaceTableNamesItems int + +func (r *replaceTableNamesItems) replace(newNode, container SQLNode) { + container.(TableNames)[int(*r)] = newNode.(TableName) +} + +func (r *replaceTableNamesItems) inc() { + *r++ +} + +type replaceTableSpecColumns int + +func (r *replaceTableSpecColumns) replace(newNode, container SQLNode) { + container.(*TableSpec).Columns[int(*r)] = newNode.(*ColumnDefinition) +} + +func (r *replaceTableSpecColumns) inc() { + *r++ +} + +type replaceTableSpecConstraints int + +func (r *replaceTableSpecConstraints) replace(newNode, container SQLNode) { + container.(*TableSpec).Constraints[int(*r)] = newNode.(*ConstraintDefinition) +} + +func (r *replaceTableSpecConstraints) inc() { + *r++ +} + +type replaceTableSpecIndexes int + +func (r *replaceTableSpecIndexes) replace(newNode, container SQLNode) { + container.(*TableSpec).Indexes[int(*r)] = newNode.(*IndexDefinition) +} + +func (r *replaceTableSpecIndexes) inc() { + *r++ +} + +func replaceTimestampFuncExprExpr1(newNode, parent SQLNode) { + parent.(*TimestampFuncExpr).Expr1 = newNode.(Expr) +} + +func replaceTimestampFuncExprExpr2(newNode, parent SQLNode) { + parent.(*TimestampFuncExpr).Expr2 = newNode.(Expr) +} + +func replaceUnaryExprExpr(newNode, parent SQLNode) { + parent.(*UnaryExpr).Expr = newNode.(Expr) +} + +func replaceUnionLeft(newNode, parent SQLNode) { + parent.(*Union).Left = newNode.(SelectStatement) +} + +func replaceUnionLimit(newNode, parent SQLNode) { + parent.(*Union).Limit = newNode.(*Limit) +} + +func replaceUnionOrderBy(newNode, parent SQLNode) { + parent.(*Union).OrderBy = newNode.(OrderBy) +} + +func replaceUnionRight(newNode, parent SQLNode) { + parent.(*Union).Right = newNode.(SelectStatement) +} + +func replaceUpdateComments(newNode, parent SQLNode) { + parent.(*Update).Comments = newNode.(Comments) +} + +func replaceUpdateExprs(newNode, parent SQLNode) { + parent.(*Update).Exprs = newNode.(UpdateExprs) +} + +func replaceUpdateLimit(newNode, parent SQLNode) { + parent.(*Update).Limit = newNode.(*Limit) +} + +func replaceUpdateOrderBy(newNode, parent SQLNode) { + parent.(*Update).OrderBy = newNode.(OrderBy) +} + +func replaceUpdateTableExprs(newNode, parent SQLNode) { + parent.(*Update).TableExprs = newNode.(TableExprs) +} + +func replaceUpdateWhere(newNode, parent SQLNode) { + parent.(*Update).Where = newNode.(*Where) +} + +func replaceUpdateExprExpr(newNode, parent SQLNode) { + parent.(*UpdateExpr).Expr = newNode.(Expr) +} + +func replaceUpdateExprName(newNode, parent SQLNode) { + parent.(*UpdateExpr).Name = newNode.(*ColName) +} + +type replaceUpdateExprsItems int + +func (r *replaceUpdateExprsItems) replace(newNode, container SQLNode) { + container.(UpdateExprs)[int(*r)] = newNode.(*UpdateExpr) +} + +func (r *replaceUpdateExprsItems) inc() { + *r++ +} + +func replaceUseDBName(newNode, parent SQLNode) { + parent.(*Use).DBName = newNode.(TableIdent) +} + +type replaceValTupleItems int + +func (r *replaceValTupleItems) replace(newNode, container SQLNode) { + container.(ValTuple)[int(*r)] = newNode.(Expr) +} + +func (r *replaceValTupleItems) inc() { + *r++ +} + +type replaceValuesItems int + +func (r *replaceValuesItems) replace(newNode, container SQLNode) { + container.(Values)[int(*r)] = newNode.(ValTuple) +} + +func (r *replaceValuesItems) inc() { + *r++ +} + +func replaceValuesFuncExprName(newNode, parent SQLNode) { + parent.(*ValuesFuncExpr).Name = newNode.(*ColName) +} + +func replaceVindexParamKey(newNode, parent SQLNode) { + tmp := parent.(VindexParam) + tmp.Key = newNode.(ColIdent) +} + +func replaceVindexSpecName(newNode, parent SQLNode) { + parent.(*VindexSpec).Name = newNode.(ColIdent) +} + +type replaceVindexSpecParams int + +func (r *replaceVindexSpecParams) replace(newNode, container SQLNode) { + container.(*VindexSpec).Params[int(*r)] = newNode.(VindexParam) +} + +func (r *replaceVindexSpecParams) inc() { + *r++ +} + +func replaceVindexSpecType(newNode, parent SQLNode) { + parent.(*VindexSpec).Type = newNode.(ColIdent) +} + +func replaceWhenCond(newNode, parent SQLNode) { + parent.(*When).Cond = newNode.(Expr) +} + +func replaceWhenVal(newNode, parent SQLNode) { + parent.(*When).Val = newNode.(Expr) +} + +func replaceWhereExpr(newNode, parent SQLNode) { + parent.(*Where).Expr = newNode.(Expr) +} + +// apply is where the visiting happens. Here is where we keep the big switch-case that will be used +// to do the actual visiting of SQLNodes +func (a *application) apply(parent, node SQLNode, replacer replacerFunc) { + if node == nil || isNilValue(node) { + return + } + + // avoid heap-allocating a new cursor for each apply call; reuse a.cursor instead + saved := a.cursor + a.cursor.replacer = replacer + a.cursor.node = node + a.cursor.parent = parent + + if a.pre != nil && !a.pre(&a.cursor) { + a.cursor = saved + return + } + + // walk children + // (the order of the cases is alphabetical) + switch n := node.(type) { + case nil: + case *AliasedExpr: + a.apply(node, n.As, replaceAliasedExprAs) + a.apply(node, n.Expr, replaceAliasedExprExpr) + + case *AliasedTableExpr: + a.apply(node, n.As, replaceAliasedTableExprAs) + a.apply(node, n.Expr, replaceAliasedTableExprExpr) + a.apply(node, n.Hints, replaceAliasedTableExprHints) + a.apply(node, n.Partitions, replaceAliasedTableExprPartitions) + + case *AndExpr: + a.apply(node, n.Left, replaceAndExprLeft) + a.apply(node, n.Right, replaceAndExprRight) + + case *AutoIncSpec: + a.apply(node, n.Column, replaceAutoIncSpecColumn) + a.apply(node, n.Sequence, replaceAutoIncSpecSequence) + + case *Begin: + + case *BinaryExpr: + a.apply(node, n.Left, replaceBinaryExprLeft) + a.apply(node, n.Right, replaceBinaryExprRight) + + case BoolVal: + + case *CaseExpr: + a.apply(node, n.Else, replaceCaseExprElse) + a.apply(node, n.Expr, replaceCaseExprExpr) + replacerWhens := replaceCaseExprWhens(0) + replacerWhensB := &replacerWhens + for _, item := range n.Whens { + a.apply(node, item, replacerWhensB.replace) + replacerWhensB.inc() + } + + case ColIdent: + + case *ColName: + a.apply(node, n.Name, replaceColNameName) + a.apply(node, n.Qualifier, replaceColNameQualifier) + + case *CollateExpr: + a.apply(node, n.Expr, replaceCollateExprExpr) + + case *ColumnDefinition: + a.apply(node, n.Name, replaceColumnDefinitionName) + + case *ColumnType: + a.apply(node, n.Autoincrement, replaceColumnTypeAutoincrement) + a.apply(node, n.Comment, replaceColumnTypeComment) + a.apply(node, n.Default, replaceColumnTypeDefault) + a.apply(node, n.Length, replaceColumnTypeLength) + a.apply(node, n.NotNull, replaceColumnTypeNotNull) + a.apply(node, n.OnUpdate, replaceColumnTypeOnUpdate) + a.apply(node, n.Scale, replaceColumnTypeScale) + a.apply(node, n.Unsigned, replaceColumnTypeUnsigned) + a.apply(node, n.Zerofill, replaceColumnTypeZerofill) + + case Columns: + replacer := replaceColumnsItems(0) + replacerRef := &replacer + for _, item := range n { + a.apply(node, item, replacerRef.replace) + replacerRef.inc() + } + + case Comments: + + case *Commit: + + case *ComparisonExpr: + a.apply(node, n.Escape, replaceComparisonExprEscape) + a.apply(node, n.Left, replaceComparisonExprLeft) + a.apply(node, n.Right, replaceComparisonExprRight) + + case *ConstraintDefinition: + a.apply(node, n.Details, replaceConstraintDefinitionDetails) + + case *ConvertExpr: + a.apply(node, n.Expr, replaceConvertExprExpr) + a.apply(node, n.Type, replaceConvertExprType) + + case *ConvertType: + a.apply(node, n.Length, replaceConvertTypeLength) + a.apply(node, n.Scale, replaceConvertTypeScale) + + case *ConvertUsingExpr: + a.apply(node, n.Expr, replaceConvertUsingExprExpr) + + case *CurTimeFuncExpr: + a.apply(node, n.Fsp, replaceCurTimeFuncExprFsp) + a.apply(node, n.Name, replaceCurTimeFuncExprName) + + case *DBDDL: + + case *DDL: + a.apply(node, n.AutoIncSpec, replaceDDLAutoIncSpec) + a.apply(node, n.FromTables, replaceDDLFromTables) + a.apply(node, n.OptLike, replaceDDLOptLike) + a.apply(node, n.PartitionSpec, replaceDDLPartitionSpec) + a.apply(node, n.Table, replaceDDLTable) + a.apply(node, n.TableSpec, replaceDDLTableSpec) + a.apply(node, n.ToTables, replaceDDLToTables) + replacerVindexCols := replaceDDLVindexCols(0) + replacerVindexColsB := &replacerVindexCols + for _, item := range n.VindexCols { + a.apply(node, item, replacerVindexColsB.replace) + replacerVindexColsB.inc() + } + a.apply(node, n.VindexSpec, replaceDDLVindexSpec) + + case *Default: + + case *Delete: + a.apply(node, n.Comments, replaceDeleteComments) + a.apply(node, n.Limit, replaceDeleteLimit) + a.apply(node, n.OrderBy, replaceDeleteOrderBy) + a.apply(node, n.Partitions, replaceDeletePartitions) + a.apply(node, n.TableExprs, replaceDeleteTableExprs) + a.apply(node, n.Targets, replaceDeleteTargets) + a.apply(node, n.Where, replaceDeleteWhere) + + case *ExistsExpr: + a.apply(node, n.Subquery, replaceExistsExprSubquery) + + case Exprs: + replacer := replaceExprsItems(0) + replacerRef := &replacer + for _, item := range n { + a.apply(node, item, replacerRef.replace) + replacerRef.inc() + } + + case *ForeignKeyDefinition: + a.apply(node, n.OnDelete, replaceForeignKeyDefinitionOnDelete) + a.apply(node, n.OnUpdate, replaceForeignKeyDefinitionOnUpdate) + a.apply(node, n.ReferencedColumns, replaceForeignKeyDefinitionReferencedColumns) + a.apply(node, n.ReferencedTable, replaceForeignKeyDefinitionReferencedTable) + a.apply(node, n.Source, replaceForeignKeyDefinitionSource) + + case *FuncExpr: + a.apply(node, n.Exprs, replaceFuncExprExprs) + a.apply(node, n.Name, replaceFuncExprName) + a.apply(node, n.Qualifier, replaceFuncExprQualifier) + + case GroupBy: + replacer := replaceGroupByItems(0) + replacerRef := &replacer + for _, item := range n { + a.apply(node, item, replacerRef.replace) + replacerRef.inc() + } + + case *GroupConcatExpr: + a.apply(node, n.Exprs, replaceGroupConcatExprExprs) + a.apply(node, n.Limit, replaceGroupConcatExprLimit) + a.apply(node, n.OrderBy, replaceGroupConcatExprOrderBy) + + case *IndexDefinition: + a.apply(node, n.Info, replaceIndexDefinitionInfo) + + case *IndexHints: + replacerIndexes := replaceIndexHintsIndexes(0) + replacerIndexesB := &replacerIndexes + for _, item := range n.Indexes { + a.apply(node, item, replacerIndexesB.replace) + replacerIndexesB.inc() + } + + case *IndexInfo: + a.apply(node, n.Name, replaceIndexInfoName) + + case *Insert: + a.apply(node, n.Columns, replaceInsertColumns) + a.apply(node, n.Comments, replaceInsertComments) + a.apply(node, n.OnDup, replaceInsertOnDup) + a.apply(node, n.Partitions, replaceInsertPartitions) + a.apply(node, n.Rows, replaceInsertRows) + a.apply(node, n.Table, replaceInsertTable) + + case *IntervalExpr: + a.apply(node, n.Expr, replaceIntervalExprExpr) + + case *IsExpr: + a.apply(node, n.Expr, replaceIsExprExpr) + + case JoinCondition: + a.apply(node, n.On, replaceJoinConditionOn) + a.apply(node, n.Using, replaceJoinConditionUsing) + + case *JoinTableExpr: + a.apply(node, n.Condition, replaceJoinTableExprCondition) + a.apply(node, n.LeftExpr, replaceJoinTableExprLeftExpr) + a.apply(node, n.RightExpr, replaceJoinTableExprRightExpr) + + case *Limit: + a.apply(node, n.Offset, replaceLimitOffset) + a.apply(node, n.Rowcount, replaceLimitRowcount) + + case ListArg: + + case *MatchExpr: + a.apply(node, n.Columns, replaceMatchExprColumns) + a.apply(node, n.Expr, replaceMatchExprExpr) + + case Nextval: + a.apply(node, n.Expr, replaceNextvalExpr) + + case *NotExpr: + a.apply(node, n.Expr, replaceNotExprExpr) + + case *NullVal: + + case OnDup: + replacer := replaceOnDupItems(0) + replacerRef := &replacer + for _, item := range n { + a.apply(node, item, replacerRef.replace) + replacerRef.inc() + } + + case *OptLike: + a.apply(node, n.LikeTable, replaceOptLikeLikeTable) + + case *OrExpr: + a.apply(node, n.Left, replaceOrExprLeft) + a.apply(node, n.Right, replaceOrExprRight) + + case *Order: + a.apply(node, n.Expr, replaceOrderExpr) + + case OrderBy: + replacer := replaceOrderByItems(0) + replacerRef := &replacer + for _, item := range n { + a.apply(node, item, replacerRef.replace) + replacerRef.inc() + } + + case *OtherAdmin: + + case *OtherRead: + + case *ParenExpr: + a.apply(node, n.Expr, replaceParenExprExpr) + + case *ParenSelect: + a.apply(node, n.Select, replaceParenSelectSelect) + + case *ParenTableExpr: + a.apply(node, n.Exprs, replaceParenTableExprExprs) + + case *PartitionDefinition: + a.apply(node, n.Limit, replacePartitionDefinitionLimit) + a.apply(node, n.Name, replacePartitionDefinitionName) + + case *PartitionSpec: + replacerDefinitions := replacePartitionSpecDefinitions(0) + replacerDefinitionsB := &replacerDefinitions + for _, item := range n.Definitions { + a.apply(node, item, replacerDefinitionsB.replace) + replacerDefinitionsB.inc() + } + a.apply(node, n.Name, replacePartitionSpecName) + + case Partitions: + replacer := replacePartitionsItems(0) + replacerRef := &replacer + for _, item := range n { + a.apply(node, item, replacerRef.replace) + replacerRef.inc() + } + + case *RangeCond: + a.apply(node, n.From, replaceRangeCondFrom) + a.apply(node, n.Left, replaceRangeCondLeft) + a.apply(node, n.To, replaceRangeCondTo) + + case ReferenceAction: + + case *Rollback: + + case *SQLVal: + + case *Select: + a.apply(node, n.Comments, replaceSelectComments) + a.apply(node, n.From, replaceSelectFrom) + a.apply(node, n.GroupBy, replaceSelectGroupBy) + a.apply(node, n.Having, replaceSelectHaving) + a.apply(node, n.Limit, replaceSelectLimit) + a.apply(node, n.OrderBy, replaceSelectOrderBy) + a.apply(node, n.SelectExprs, replaceSelectSelectExprs) + a.apply(node, n.Where, replaceSelectWhere) + + case SelectExprs: + replacer := replaceSelectExprsItems(0) + replacerRef := &replacer + for _, item := range n { + a.apply(node, item, replacerRef.replace) + replacerRef.inc() + } + + case *Set: + a.apply(node, n.Comments, replaceSetComments) + a.apply(node, n.Exprs, replaceSetExprs) + + case *SetExpr: + a.apply(node, n.Expr, replaceSetExprExpr) + a.apply(node, n.Name, replaceSetExprName) + + case SetExprs: + replacer := replaceSetExprsItems(0) + replacerRef := &replacer + for _, item := range n { + a.apply(node, item, replacerRef.replace) + replacerRef.inc() + } + + case *Show: + a.apply(node, n.OnTable, replaceShowOnTable) + a.apply(node, n.Table, replaceShowTable) + + case *ShowFilter: + a.apply(node, n.Filter, replaceShowFilterFilter) + + case *StarExpr: + a.apply(node, n.TableName, replaceStarExprTableName) + + case *Stream: + a.apply(node, n.Comments, replaceStreamComments) + a.apply(node, n.SelectExpr, replaceStreamSelectExpr) + a.apply(node, n.Table, replaceStreamTable) + + case *Subquery: + a.apply(node, n.Select, replaceSubquerySelect) + + case *SubstrExpr: + a.apply(node, n.From, replaceSubstrExprFrom) + a.apply(node, n.Name, replaceSubstrExprName) + a.apply(node, n.StrVal, replaceSubstrExprStrVal) + a.apply(node, n.To, replaceSubstrExprTo) + + case TableExprs: + replacer := replaceTableExprsItems(0) + replacerRef := &replacer + for _, item := range n { + a.apply(node, item, replacerRef.replace) + replacerRef.inc() + } + + case TableIdent: + + case TableName: + a.apply(node, n.Name, replaceTableNameName) + a.apply(node, n.Qualifier, replaceTableNameQualifier) + + case TableNames: + replacer := replaceTableNamesItems(0) + replacerRef := &replacer + for _, item := range n { + a.apply(node, item, replacerRef.replace) + replacerRef.inc() + } + + case *TableSpec: + replacerColumns := replaceTableSpecColumns(0) + replacerColumnsB := &replacerColumns + for _, item := range n.Columns { + a.apply(node, item, replacerColumnsB.replace) + replacerColumnsB.inc() + } + replacerConstraints := replaceTableSpecConstraints(0) + replacerConstraintsB := &replacerConstraints + for _, item := range n.Constraints { + a.apply(node, item, replacerConstraintsB.replace) + replacerConstraintsB.inc() + } + replacerIndexes := replaceTableSpecIndexes(0) + replacerIndexesB := &replacerIndexes + for _, item := range n.Indexes { + a.apply(node, item, replacerIndexesB.replace) + replacerIndexesB.inc() + } + + case *TimestampFuncExpr: + a.apply(node, n.Expr1, replaceTimestampFuncExprExpr1) + a.apply(node, n.Expr2, replaceTimestampFuncExprExpr2) + + case *UnaryExpr: + a.apply(node, n.Expr, replaceUnaryExprExpr) + + case *Union: + a.apply(node, n.Left, replaceUnionLeft) + a.apply(node, n.Limit, replaceUnionLimit) + a.apply(node, n.OrderBy, replaceUnionOrderBy) + a.apply(node, n.Right, replaceUnionRight) + + case *Update: + a.apply(node, n.Comments, replaceUpdateComments) + a.apply(node, n.Exprs, replaceUpdateExprs) + a.apply(node, n.Limit, replaceUpdateLimit) + a.apply(node, n.OrderBy, replaceUpdateOrderBy) + a.apply(node, n.TableExprs, replaceUpdateTableExprs) + a.apply(node, n.Where, replaceUpdateWhere) + + case *UpdateExpr: + a.apply(node, n.Expr, replaceUpdateExprExpr) + a.apply(node, n.Name, replaceUpdateExprName) + + case UpdateExprs: + replacer := replaceUpdateExprsItems(0) + replacerRef := &replacer + for _, item := range n { + a.apply(node, item, replacerRef.replace) + replacerRef.inc() + } + + case *Use: + a.apply(node, n.DBName, replaceUseDBName) + + case ValTuple: + replacer := replaceValTupleItems(0) + replacerRef := &replacer + for _, item := range n { + a.apply(node, item, replacerRef.replace) + replacerRef.inc() + } + + case Values: + replacer := replaceValuesItems(0) + replacerRef := &replacer + for _, item := range n { + a.apply(node, item, replacerRef.replace) + replacerRef.inc() + } + + case *ValuesFuncExpr: + a.apply(node, n.Name, replaceValuesFuncExprName) + + case VindexParam: + a.apply(node, n.Key, replaceVindexParamKey) + + case *VindexSpec: + a.apply(node, n.Name, replaceVindexSpecName) + replacerParams := replaceVindexSpecParams(0) + replacerParamsB := &replacerParams + for _, item := range n.Params { + a.apply(node, item, replacerParamsB.replace) + replacerParamsB.inc() + } + a.apply(node, n.Type, replaceVindexSpecType) + + case *When: + a.apply(node, n.Cond, replaceWhenCond) + a.apply(node, n.Val, replaceWhenVal) + + case *Where: + a.apply(node, n.Expr, replaceWhereExpr) + + default: + panic("unknown ast type " + reflect.TypeOf(node).String()) + } + + if a.post != nil && !a.post(&a.cursor) { + panic(abort) + } + + a.cursor = saved +} + +func isNilValue(i interface{}) bool { + valueOf := reflect.ValueOf(i) + kind := valueOf.Kind() + isNullable := kind == reflect.Ptr || kind == reflect.Array || kind == reflect.Slice + return isNullable && valueOf.IsNil() +} diff --git a/go/vt/sqlparser/rewriter_api.go b/go/vt/sqlparser/rewriter_api.go new file mode 100644 index 00000000000..c5732d1aceb --- /dev/null +++ b/go/vt/sqlparser/rewriter_api.go @@ -0,0 +1,91 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package sqlparser + +// The rewriter was heavily inspired by https://github.com/golang/tools/blob/master/go/ast/astutil/rewrite.go + +// Rewrite traverses a syntax tree recursively, starting with root, +// and calling pre and post for each node as described below. +// Rewrite returns the syntax tree, possibly modified. +// +// If pre is not nil, it is called for each node before the node's +// children are traversed (pre-order). If pre returns false, no +// children are traversed, and post is not called for that node. +// +// If post is not nil, and a prior call of pre didn't return false, +// post is called for each node after its children are traversed +// (post-order). If post returns false, traversal is terminated and +// Apply returns immediately. +// +// Only fields that refer to AST nodes are considered children; +// i.e., fields of basic types (strings, []byte, etc.) are ignored. +// +func Rewrite(node SQLNode, pre, post ApplyFunc) (result SQLNode) { + parent := &struct{ SQLNode }{node} + defer func() { + if r := recover(); r != nil && r != abort { + panic(r) + } + result = parent.SQLNode + }() + + a := &application{ + pre: pre, + post: post, + cursor: Cursor{}, + } + + // this is the root-replacer, used when the user replaces the root of the ast + replacer := func(newNode SQLNode, _ SQLNode) { + parent.SQLNode = newNode + } + + a.apply(parent, node, replacer) + + return parent.SQLNode +} + +// An ApplyFunc is invoked by Rewrite for each node n, even if n is nil, +// before and/or after the node's children, using a Cursor describing +// the current node and providing operations on it. +// +// The return value of ApplyFunc controls the syntax tree traversal. +// See Rewrite for details. +type ApplyFunc func(*Cursor) bool + +var abort = new(int) // singleton, to signal termination of Apply + +// A Cursor describes a node encountered during Apply. +// Information about the node and its parent is available +// from the Node and Parent methods. +type Cursor struct { + parent SQLNode + replacer replacerFunc + node SQLNode +} + +// Node returns the current Node. +func (c *Cursor) Node() SQLNode { return c.node } + +// Parent returns the parent of the current Node. +func (c *Cursor) Parent() SQLNode { return c.parent } + +// Replace replaces the current node in the parent field with this new object. The use needs to make sure to not +// replace the object with something of the wrong type, or the visitor will panic. +func (c *Cursor) Replace(newNode SQLNode) { + c.replacer(newNode, c.parent) +} diff --git a/go/vt/sqlparser/sql.go b/go/vt/sqlparser/sql.go index ab9a9ad7337..3415bbfbbbe 100644 --- a/go/vt/sqlparser/sql.go +++ b/go/vt/sqlparser/sql.go @@ -137,302 +137,303 @@ const SET = 57372 const LOCK = 57373 const UNLOCK = 57374 const KEYS = 57375 -const VALUES = 57376 -const LAST_INSERT_ID = 57377 -const NEXT = 57378 -const VALUE = 57379 -const SHARE = 57380 -const MODE = 57381 -const SQL_NO_CACHE = 57382 -const SQL_CACHE = 57383 -const JOIN = 57384 -const STRAIGHT_JOIN = 57385 -const LEFT = 57386 -const RIGHT = 57387 -const INNER = 57388 -const OUTER = 57389 -const CROSS = 57390 -const NATURAL = 57391 -const USE = 57392 -const FORCE = 57393 -const ON = 57394 -const USING = 57395 -const ID = 57396 -const HEX = 57397 -const STRING = 57398 -const INTEGRAL = 57399 -const FLOAT = 57400 -const HEXNUM = 57401 -const VALUE_ARG = 57402 -const LIST_ARG = 57403 -const COMMENT = 57404 -const COMMENT_KEYWORD = 57405 -const BIT_LITERAL = 57406 -const NULL = 57407 -const TRUE = 57408 -const FALSE = 57409 -const OFF = 57410 -const OR = 57411 -const AND = 57412 -const NOT = 57413 -const BETWEEN = 57414 -const CASE = 57415 -const WHEN = 57416 -const THEN = 57417 -const ELSE = 57418 -const END = 57419 -const LE = 57420 -const GE = 57421 -const NE = 57422 -const NULL_SAFE_EQUAL = 57423 -const IS = 57424 -const LIKE = 57425 -const REGEXP = 57426 -const IN = 57427 -const SHIFT_LEFT = 57428 -const SHIFT_RIGHT = 57429 -const DIV = 57430 -const MOD = 57431 -const UNARY = 57432 -const COLLATE = 57433 -const BINARY = 57434 -const UNDERSCORE_BINARY = 57435 -const UNDERSCORE_UTF8MB4 = 57436 -const INTERVAL = 57437 -const JSON_EXTRACT_OP = 57438 -const JSON_UNQUOTE_EXTRACT_OP = 57439 -const CREATE = 57440 -const ALTER = 57441 -const DROP = 57442 -const RENAME = 57443 -const ANALYZE = 57444 -const ADD = 57445 -const FLUSH = 57446 -const SCHEMA = 57447 -const TABLE = 57448 -const INDEX = 57449 -const VIEW = 57450 -const TO = 57451 -const IGNORE = 57452 -const IF = 57453 -const UNIQUE = 57454 -const PRIMARY = 57455 -const COLUMN = 57456 -const SPATIAL = 57457 -const FULLTEXT = 57458 -const KEY_BLOCK_SIZE = 57459 -const CHECK = 57460 -const ACTION = 57461 -const CASCADE = 57462 -const CONSTRAINT = 57463 -const FOREIGN = 57464 -const NO = 57465 -const REFERENCES = 57466 -const RESTRICT = 57467 -const SHOW = 57468 -const DESCRIBE = 57469 -const EXPLAIN = 57470 -const DATE = 57471 -const ESCAPE = 57472 -const REPAIR = 57473 -const OPTIMIZE = 57474 -const TRUNCATE = 57475 -const MAXVALUE = 57476 -const PARTITION = 57477 -const REORGANIZE = 57478 -const LESS = 57479 -const THAN = 57480 -const PROCEDURE = 57481 -const TRIGGER = 57482 -const VINDEX = 57483 -const VINDEXES = 57484 -const STATUS = 57485 -const VARIABLES = 57486 -const WARNINGS = 57487 -const SEQUENCE = 57488 -const BEGIN = 57489 -const START = 57490 -const TRANSACTION = 57491 -const COMMIT = 57492 -const ROLLBACK = 57493 -const BIT = 57494 -const TINYINT = 57495 -const SMALLINT = 57496 -const MEDIUMINT = 57497 -const INT = 57498 -const INTEGER = 57499 -const BIGINT = 57500 -const INTNUM = 57501 -const REAL = 57502 -const DOUBLE = 57503 -const FLOAT_TYPE = 57504 -const DECIMAL = 57505 -const NUMERIC = 57506 -const TIME = 57507 -const TIMESTAMP = 57508 -const DATETIME = 57509 -const YEAR = 57510 -const CHAR = 57511 -const VARCHAR = 57512 -const BOOL = 57513 -const CHARACTER = 57514 -const VARBINARY = 57515 -const NCHAR = 57516 -const TEXT = 57517 -const TINYTEXT = 57518 -const MEDIUMTEXT = 57519 -const LONGTEXT = 57520 -const BLOB = 57521 -const TINYBLOB = 57522 -const MEDIUMBLOB = 57523 -const LONGBLOB = 57524 -const JSON = 57525 -const ENUM = 57526 -const GEOMETRY = 57527 -const POINT = 57528 -const LINESTRING = 57529 -const POLYGON = 57530 -const GEOMETRYCOLLECTION = 57531 -const MULTIPOINT = 57532 -const MULTILINESTRING = 57533 -const MULTIPOLYGON = 57534 -const NULLX = 57535 -const AUTO_INCREMENT = 57536 -const APPROXNUM = 57537 -const SIGNED = 57538 -const UNSIGNED = 57539 -const ZEROFILL = 57540 -const COLLATION = 57541 -const DATABASES = 57542 -const TABLES = 57543 -const VITESS_METADATA = 57544 -const VSCHEMA = 57545 -const FULL = 57546 -const PROCESSLIST = 57547 -const COLUMNS = 57548 -const FIELDS = 57549 -const ENGINES = 57550 -const PLUGINS = 57551 -const NAMES = 57552 -const CHARSET = 57553 -const GLOBAL = 57554 -const SESSION = 57555 -const ISOLATION = 57556 -const LEVEL = 57557 -const READ = 57558 -const WRITE = 57559 -const ONLY = 57560 -const REPEATABLE = 57561 -const COMMITTED = 57562 -const UNCOMMITTED = 57563 -const SERIALIZABLE = 57564 -const CURRENT_TIMESTAMP = 57565 -const DATABASE = 57566 -const CURRENT_DATE = 57567 -const CURRENT_TIME = 57568 -const LOCALTIME = 57569 -const LOCALTIMESTAMP = 57570 -const UTC_DATE = 57571 -const UTC_TIME = 57572 -const UTC_TIMESTAMP = 57573 -const REPLACE = 57574 -const CONVERT = 57575 -const CAST = 57576 -const SUBSTR = 57577 -const SUBSTRING = 57578 -const GROUP_CONCAT = 57579 -const SEPARATOR = 57580 -const TIMESTAMPADD = 57581 -const TIMESTAMPDIFF = 57582 -const MATCH = 57583 -const AGAINST = 57584 -const BOOLEAN = 57585 -const LANGUAGE = 57586 -const WITH = 57587 -const QUERY = 57588 -const EXPANSION = 57589 -const UNUSED = 57590 -const ARRAY = 57591 -const CUME_DIST = 57592 -const DESCRIPTION = 57593 -const DENSE_RANK = 57594 -const EMPTY = 57595 -const EXCEPT = 57596 -const FIRST_VALUE = 57597 -const GROUPING = 57598 -const GROUPS = 57599 -const JSON_TABLE = 57600 -const LAG = 57601 -const LAST_VALUE = 57602 -const LATERAL = 57603 -const LEAD = 57604 -const MEMBER = 57605 -const NTH_VALUE = 57606 -const NTILE = 57607 -const OF = 57608 -const OVER = 57609 -const PERCENT_RANK = 57610 -const RANK = 57611 -const RECURSIVE = 57612 -const ROW_NUMBER = 57613 -const SYSTEM = 57614 -const WINDOW = 57615 -const ACTIVE = 57616 -const ADMIN = 57617 -const BUCKETS = 57618 -const CLONE = 57619 -const COMPONENT = 57620 -const DEFINITION = 57621 -const ENFORCED = 57622 -const EXCLUDE = 57623 -const FOLLOWING = 57624 -const GEOMCOLLECTION = 57625 -const GET_MASTER_PUBLIC_KEY = 57626 -const HISTOGRAM = 57627 -const HISTORY = 57628 -const INACTIVE = 57629 -const INVISIBLE = 57630 -const LOCKED = 57631 -const MASTER_COMPRESSION_ALGORITHMS = 57632 -const MASTER_PUBLIC_KEY_PATH = 57633 -const MASTER_TLS_CIPHERSUITES = 57634 -const MASTER_ZSTD_COMPRESSION_LEVEL = 57635 -const NESTED = 57636 -const NETWORK_NAMESPACE = 57637 -const NOWAIT = 57638 -const NULLS = 57639 -const OJ = 57640 -const OLD = 57641 -const OPTIONAL = 57642 -const ORDINALITY = 57643 -const ORGANIZATION = 57644 -const OTHERS = 57645 -const PATH = 57646 -const PERSIST = 57647 -const PERSIST_ONLY = 57648 -const PRECEDING = 57649 -const PRIVILEGE_CHECKS_USER = 57650 -const PROCESS = 57651 -const RANDOM = 57652 -const REFERENCE = 57653 -const REQUIRE_ROW_FORMAT = 57654 -const RESOURCE = 57655 -const RESPECT = 57656 -const RESTART = 57657 -const RETAIN = 57658 -const REUSE = 57659 -const ROLE = 57660 -const SECONDARY = 57661 -const SECONDARY_ENGINE = 57662 -const SECONDARY_LOAD = 57663 -const SECONDARY_UNLOAD = 57664 -const SKIP = 57665 -const SRID = 57666 -const THREAD_PRIORITY = 57667 -const TIES = 57668 -const UNBOUNDED = 57669 -const VCPU = 57670 -const VISIBLE = 57671 +const DISTINCTROW = 57376 +const VALUES = 57377 +const LAST_INSERT_ID = 57378 +const NEXT = 57379 +const VALUE = 57380 +const SHARE = 57381 +const MODE = 57382 +const SQL_NO_CACHE = 57383 +const SQL_CACHE = 57384 +const JOIN = 57385 +const STRAIGHT_JOIN = 57386 +const LEFT = 57387 +const RIGHT = 57388 +const INNER = 57389 +const OUTER = 57390 +const CROSS = 57391 +const NATURAL = 57392 +const USE = 57393 +const FORCE = 57394 +const ON = 57395 +const USING = 57396 +const ID = 57397 +const HEX = 57398 +const STRING = 57399 +const INTEGRAL = 57400 +const FLOAT = 57401 +const HEXNUM = 57402 +const VALUE_ARG = 57403 +const LIST_ARG = 57404 +const COMMENT = 57405 +const COMMENT_KEYWORD = 57406 +const BIT_LITERAL = 57407 +const NULL = 57408 +const TRUE = 57409 +const FALSE = 57410 +const OFF = 57411 +const OR = 57412 +const AND = 57413 +const NOT = 57414 +const BETWEEN = 57415 +const CASE = 57416 +const WHEN = 57417 +const THEN = 57418 +const ELSE = 57419 +const END = 57420 +const LE = 57421 +const GE = 57422 +const NE = 57423 +const NULL_SAFE_EQUAL = 57424 +const IS = 57425 +const LIKE = 57426 +const REGEXP = 57427 +const IN = 57428 +const SHIFT_LEFT = 57429 +const SHIFT_RIGHT = 57430 +const DIV = 57431 +const MOD = 57432 +const UNARY = 57433 +const COLLATE = 57434 +const BINARY = 57435 +const UNDERSCORE_BINARY = 57436 +const UNDERSCORE_UTF8MB4 = 57437 +const INTERVAL = 57438 +const JSON_EXTRACT_OP = 57439 +const JSON_UNQUOTE_EXTRACT_OP = 57440 +const CREATE = 57441 +const ALTER = 57442 +const DROP = 57443 +const RENAME = 57444 +const ANALYZE = 57445 +const ADD = 57446 +const FLUSH = 57447 +const SCHEMA = 57448 +const TABLE = 57449 +const INDEX = 57450 +const VIEW = 57451 +const TO = 57452 +const IGNORE = 57453 +const IF = 57454 +const UNIQUE = 57455 +const PRIMARY = 57456 +const COLUMN = 57457 +const SPATIAL = 57458 +const FULLTEXT = 57459 +const KEY_BLOCK_SIZE = 57460 +const CHECK = 57461 +const ACTION = 57462 +const CASCADE = 57463 +const CONSTRAINT = 57464 +const FOREIGN = 57465 +const NO = 57466 +const REFERENCES = 57467 +const RESTRICT = 57468 +const SHOW = 57469 +const DESCRIBE = 57470 +const EXPLAIN = 57471 +const DATE = 57472 +const ESCAPE = 57473 +const REPAIR = 57474 +const OPTIMIZE = 57475 +const TRUNCATE = 57476 +const MAXVALUE = 57477 +const PARTITION = 57478 +const REORGANIZE = 57479 +const LESS = 57480 +const THAN = 57481 +const PROCEDURE = 57482 +const TRIGGER = 57483 +const VINDEX = 57484 +const VINDEXES = 57485 +const STATUS = 57486 +const VARIABLES = 57487 +const WARNINGS = 57488 +const SEQUENCE = 57489 +const BEGIN = 57490 +const START = 57491 +const TRANSACTION = 57492 +const COMMIT = 57493 +const ROLLBACK = 57494 +const BIT = 57495 +const TINYINT = 57496 +const SMALLINT = 57497 +const MEDIUMINT = 57498 +const INT = 57499 +const INTEGER = 57500 +const BIGINT = 57501 +const INTNUM = 57502 +const REAL = 57503 +const DOUBLE = 57504 +const FLOAT_TYPE = 57505 +const DECIMAL = 57506 +const NUMERIC = 57507 +const TIME = 57508 +const TIMESTAMP = 57509 +const DATETIME = 57510 +const YEAR = 57511 +const CHAR = 57512 +const VARCHAR = 57513 +const BOOL = 57514 +const CHARACTER = 57515 +const VARBINARY = 57516 +const NCHAR = 57517 +const TEXT = 57518 +const TINYTEXT = 57519 +const MEDIUMTEXT = 57520 +const LONGTEXT = 57521 +const BLOB = 57522 +const TINYBLOB = 57523 +const MEDIUMBLOB = 57524 +const LONGBLOB = 57525 +const JSON = 57526 +const ENUM = 57527 +const GEOMETRY = 57528 +const POINT = 57529 +const LINESTRING = 57530 +const POLYGON = 57531 +const GEOMETRYCOLLECTION = 57532 +const MULTIPOINT = 57533 +const MULTILINESTRING = 57534 +const MULTIPOLYGON = 57535 +const NULLX = 57536 +const AUTO_INCREMENT = 57537 +const APPROXNUM = 57538 +const SIGNED = 57539 +const UNSIGNED = 57540 +const ZEROFILL = 57541 +const COLLATION = 57542 +const DATABASES = 57543 +const TABLES = 57544 +const VITESS_METADATA = 57545 +const VSCHEMA = 57546 +const FULL = 57547 +const PROCESSLIST = 57548 +const COLUMNS = 57549 +const FIELDS = 57550 +const ENGINES = 57551 +const PLUGINS = 57552 +const NAMES = 57553 +const CHARSET = 57554 +const GLOBAL = 57555 +const SESSION = 57556 +const ISOLATION = 57557 +const LEVEL = 57558 +const READ = 57559 +const WRITE = 57560 +const ONLY = 57561 +const REPEATABLE = 57562 +const COMMITTED = 57563 +const UNCOMMITTED = 57564 +const SERIALIZABLE = 57565 +const CURRENT_TIMESTAMP = 57566 +const DATABASE = 57567 +const CURRENT_DATE = 57568 +const CURRENT_TIME = 57569 +const LOCALTIME = 57570 +const LOCALTIMESTAMP = 57571 +const UTC_DATE = 57572 +const UTC_TIME = 57573 +const UTC_TIMESTAMP = 57574 +const REPLACE = 57575 +const CONVERT = 57576 +const CAST = 57577 +const SUBSTR = 57578 +const SUBSTRING = 57579 +const GROUP_CONCAT = 57580 +const SEPARATOR = 57581 +const TIMESTAMPADD = 57582 +const TIMESTAMPDIFF = 57583 +const MATCH = 57584 +const AGAINST = 57585 +const BOOLEAN = 57586 +const LANGUAGE = 57587 +const WITH = 57588 +const QUERY = 57589 +const EXPANSION = 57590 +const UNUSED = 57591 +const ARRAY = 57592 +const CUME_DIST = 57593 +const DESCRIPTION = 57594 +const DENSE_RANK = 57595 +const EMPTY = 57596 +const EXCEPT = 57597 +const FIRST_VALUE = 57598 +const GROUPING = 57599 +const GROUPS = 57600 +const JSON_TABLE = 57601 +const LAG = 57602 +const LAST_VALUE = 57603 +const LATERAL = 57604 +const LEAD = 57605 +const MEMBER = 57606 +const NTH_VALUE = 57607 +const NTILE = 57608 +const OF = 57609 +const OVER = 57610 +const PERCENT_RANK = 57611 +const RANK = 57612 +const RECURSIVE = 57613 +const ROW_NUMBER = 57614 +const SYSTEM = 57615 +const WINDOW = 57616 +const ACTIVE = 57617 +const ADMIN = 57618 +const BUCKETS = 57619 +const CLONE = 57620 +const COMPONENT = 57621 +const DEFINITION = 57622 +const ENFORCED = 57623 +const EXCLUDE = 57624 +const FOLLOWING = 57625 +const GEOMCOLLECTION = 57626 +const GET_MASTER_PUBLIC_KEY = 57627 +const HISTOGRAM = 57628 +const HISTORY = 57629 +const INACTIVE = 57630 +const INVISIBLE = 57631 +const LOCKED = 57632 +const MASTER_COMPRESSION_ALGORITHMS = 57633 +const MASTER_PUBLIC_KEY_PATH = 57634 +const MASTER_TLS_CIPHERSUITES = 57635 +const MASTER_ZSTD_COMPRESSION_LEVEL = 57636 +const NESTED = 57637 +const NETWORK_NAMESPACE = 57638 +const NOWAIT = 57639 +const NULLS = 57640 +const OJ = 57641 +const OLD = 57642 +const OPTIONAL = 57643 +const ORDINALITY = 57644 +const ORGANIZATION = 57645 +const OTHERS = 57646 +const PATH = 57647 +const PERSIST = 57648 +const PERSIST_ONLY = 57649 +const PRECEDING = 57650 +const PRIVILEGE_CHECKS_USER = 57651 +const PROCESS = 57652 +const RANDOM = 57653 +const REFERENCE = 57654 +const REQUIRE_ROW_FORMAT = 57655 +const RESOURCE = 57656 +const RESPECT = 57657 +const RESTART = 57658 +const RETAIN = 57659 +const REUSE = 57660 +const ROLE = 57661 +const SECONDARY = 57662 +const SECONDARY_ENGINE = 57663 +const SECONDARY_LOAD = 57664 +const SECONDARY_UNLOAD = 57665 +const SKIP = 57666 +const SRID = 57667 +const THREAD_PRIORITY = 57668 +const TIES = 57669 +const UNBOUNDED = 57670 +const VCPU = 57671 +const VISIBLE = 57672 var yyToknames = [...]string{ "$end", @@ -468,6 +469,7 @@ var yyToknames = [...]string{ "LOCK", "UNLOCK", "KEYS", + "DISTINCTROW", "VALUES", "LAST_INSERT_ID", "NEXT", @@ -798,343 +800,365 @@ var yyExca = [...]int{ 5, 29, -2, 4, -1, 37, - 160, 300, - 161, 300, - -2, 288, - -1, 320, - 112, 640, - -2, 636, - -1, 321, - 112, 641, - -2, 637, - -1, 389, - 82, 888, + 161, 302, + 162, 302, + -2, 290, + -1, 322, + 113, 646, + -2, 642, + -1, 323, + 113, 647, + -2, 643, + -1, 392, + 83, 895, -2, 63, - -1, 390, - 82, 806, + -1, 393, + 83, 813, -2, 64, - -1, 395, - 82, 775, - -2, 602, - -1, 397, - 82, 836, - -2, 604, - -1, 689, - 1, 352, - 5, 352, - 12, 352, - 13, 352, - 14, 352, - 15, 352, - 17, 352, - 19, 352, - 30, 352, - 31, 352, - 42, 352, - 43, 352, - 44, 352, - 45, 352, - 46, 352, - 48, 352, - 49, 352, - 52, 352, - 53, 352, - 55, 352, - 56, 352, - 347, 352, - -2, 370, - -1, 692, - 53, 44, - 55, 44, + -1, 398, + 83, 782, + -2, 608, + -1, 400, + 83, 843, + -2, 610, + -1, 699, + 1, 355, + 5, 355, + 12, 355, + 13, 355, + 14, 355, + 15, 355, + 17, 355, + 19, 355, + 30, 355, + 31, 355, + 43, 355, + 44, 355, + 45, 355, + 46, 355, + 47, 355, + 49, 355, + 50, 355, + 53, 355, + 54, 355, + 56, 355, + 57, 355, + 348, 355, + -2, 373, + -1, 702, + 54, 44, + 56, 44, -2, 48, - -1, 840, - 112, 643, - -2, 639, - -1, 1069, + -1, 854, + 113, 649, + -2, 645, + -1, 1084, 5, 30, - -2, 437, - -1, 1099, + -2, 441, + -1, 1115, 5, 29, - -2, 576, - -1, 1344, + -2, 582, + -1, 1359, 5, 30, - -2, 577, - -1, 1397, + -2, 583, + -1, 1412, 5, 29, - -2, 579, - -1, 1475, + -2, 585, + -1, 1492, 5, 30, - -2, 580, + -2, 586, } const yyPrivate = 57344 -const yyLast = 16596 +const yyLast = 16995 var yyAct = [...]int{ - 321, 1509, 1499, 1306, 1463, 1102, 1194, 645, 1377, 1364, - 953, 1120, 1280, 351, 1246, 1409, 338, 926, 299, 982, - 546, 1243, 1247, 996, 1103, 325, 924, 57, 1033, 1147, - 962, 952, 81, 1253, 1218, 1259, 264, 865, 789, 264, - 1061, 872, 803, 1126, 1173, 875, 686, 1164, 966, 705, - 842, 992, 394, 290, 928, 644, 3, 913, 893, 577, - 388, 352, 51, 704, 583, 517, 589, 264, 81, 597, - 323, 685, 264, 383, 264, 385, 694, 659, 906, 949, - 56, 308, 1502, 1486, 660, 1497, 1473, 1494, 380, 1307, - 1485, 1015, 691, 1472, 1235, 1336, 61, 535, 291, 292, - 293, 294, 522, 1274, 297, 1014, 943, 298, 1135, 312, - 1155, 1134, 550, 51, 1136, 571, 976, 259, 255, 256, - 257, 304, 63, 64, 65, 66, 67, 296, 261, 1275, - 1276, 944, 945, 1019, 706, 566, 707, 548, 295, 567, - 564, 565, 1013, 1438, 610, 609, 619, 620, 612, 613, - 614, 615, 616, 617, 618, 611, 975, 1196, 621, 382, - 1367, 251, 983, 253, 519, 363, 521, 369, 370, 367, - 368, 366, 365, 364, 570, 1384, 1327, 1325, 552, 289, - 554, 371, 372, 778, 559, 560, 569, 777, 1198, 775, - 1496, 1493, 1010, 1007, 1008, 1464, 1006, 1193, 907, 1456, - 967, 1517, 1410, 536, 253, 391, 1219, 1513, 524, 1199, - 1197, 551, 553, 1121, 1123, 1412, 782, 768, 1269, 1418, - 1190, 1268, 776, 779, 1267, 520, 1192, 969, 1017, 1020, - 527, 969, 266, 254, 1027, 1445, 258, 1026, 532, 1347, - 1078, 633, 634, 1205, 1221, 1131, 1088, 1055, 814, 1075, - 700, 601, 264, 542, 950, 264, 252, 1292, 621, 611, - 1148, 264, 621, 939, 811, 1012, 808, 264, 596, 518, - 81, 1454, 81, 804, 81, 81, 1427, 81, 1223, 81, - 1227, 969, 1222, 1411, 1220, 81, 1257, 1011, 708, 1225, - 1122, 1237, 555, 894, 556, 557, 549, 558, 1224, 561, - 594, 529, 516, 530, 1471, 572, 531, 983, 1293, 70, - 518, 1226, 1228, 1439, 1511, 81, 596, 1512, 770, 1510, - 1419, 1417, 1191, 968, 1189, 1035, 1016, 968, 1153, 318, - 585, 547, 894, 547, 1085, 547, 547, 1459, 547, 591, - 547, 1018, 633, 634, 528, 71, 547, 534, 849, 573, - 574, 633, 634, 541, 805, 538, 539, 540, 1477, 543, - 586, 972, 847, 848, 846, 1373, 51, 973, 614, 615, - 616, 617, 618, 611, 1518, 1181, 621, 968, 264, 264, - 264, 630, 965, 963, 632, 964, 1372, 81, 523, 595, - 594, 961, 967, 81, 595, 594, 1239, 1052, 1053, 1054, - 54, 1168, 587, 1034, 1179, 684, 596, 22, 817, 818, - 845, 596, 643, 1519, 647, 648, 649, 650, 651, 652, - 653, 654, 655, 1167, 658, 661, 661, 661, 667, 661, - 661, 667, 661, 675, 676, 677, 678, 679, 680, 866, - 690, 867, 662, 664, 666, 668, 670, 672, 673, 663, - 665, 1156, 669, 671, 1479, 674, 595, 594, 698, 1137, - 250, 1138, 702, 1455, 813, 525, 526, 303, 693, 1391, - 683, 1180, 692, 596, 1370, 1202, 1185, 1182, 1175, 1183, - 1178, 1074, 1174, 1165, 1038, 1176, 1177, 1415, 1495, 350, - 612, 613, 614, 615, 616, 617, 618, 611, 1452, 1184, - 621, 812, 610, 609, 619, 620, 612, 613, 614, 615, - 616, 617, 618, 611, 1309, 1148, 621, 264, 595, 594, - 1143, 79, 81, 868, 391, 377, 378, 264, 264, 81, - 788, 595, 594, 264, 787, 596, 264, 1481, 576, 264, - 1415, 1467, 767, 264, 771, 81, 81, 769, 596, 774, - 81, 81, 81, 264, 81, 81, 1062, 393, 1415, 576, - 81, 81, 832, 834, 835, 792, 793, 1073, 833, 1072, - 794, 795, 796, 766, 798, 799, 1415, 1446, 1415, 1414, - 800, 801, 544, 547, 1362, 1361, 595, 594, 537, 81, - 547, 1349, 576, 264, 576, 791, 1346, 576, 1424, 81, - 1299, 1298, 1423, 596, 819, 1244, 547, 547, 1256, 716, - 1289, 547, 547, 547, 970, 547, 547, 1256, 843, 772, - 773, 547, 547, 898, 783, 780, 1295, 1296, 382, 1195, - 877, 786, 341, 340, 343, 344, 345, 346, 1295, 1294, - 838, 342, 347, 81, 1127, 797, 915, 918, 919, 920, - 916, 1342, 917, 921, 840, 1127, 1260, 1261, 635, 636, - 637, 638, 639, 640, 641, 642, 1067, 576, 836, 821, - 910, 576, 877, 576, 715, 714, 81, 81, 884, 887, - 1208, 1426, 909, 264, 895, 828, 910, 910, 54, 576, - 24, 264, 264, 24, 51, 264, 264, 1297, 1256, 264, - 264, 264, 81, 879, 869, 870, 58, 910, 933, 647, - 695, 1139, 942, 696, 1097, 81, 1091, 24, 1098, 1090, - 903, 934, 891, 1067, 1067, 936, 610, 609, 619, 620, - 612, 613, 614, 615, 616, 617, 618, 611, 54, 839, - 621, 54, 1504, 695, 701, 1396, 1067, 815, 781, 984, - 985, 986, 925, 791, 696, 697, 690, 699, 1487, 393, - 690, 393, 940, 393, 393, 54, 393, 941, 393, 264, - 81, 932, 81, 937, 393, 908, 264, 264, 264, 264, - 264, 957, 264, 264, 305, 1379, 264, 81, 935, 998, - 1002, 977, 1004, 1354, 997, 1285, 697, 1380, 695, 1260, - 1261, 1500, 1142, 264, 599, 264, 264, 1031, 993, 988, - 264, 987, 1000, 1287, 994, 995, 609, 619, 620, 612, - 613, 614, 615, 616, 617, 618, 611, 314, 1263, 621, - 827, 547, 54, 547, 1244, 1169, 809, 785, 1266, 391, - 1114, 978, 979, 980, 981, 1115, 1112, 1116, 547, 919, - 920, 1113, 954, 1043, 1265, 1111, 1110, 989, 990, 991, - 843, 1001, 309, 310, 1491, 1484, 1204, 840, 1021, 1022, - 1023, 1024, 1025, 1040, 1028, 1029, 393, 1489, 1030, 1045, - 1044, 1050, 710, 590, 619, 620, 612, 613, 614, 615, - 616, 617, 618, 611, 1049, 1032, 621, 1057, 588, 1160, - 713, 1056, 1039, 545, 578, 1152, 327, 1461, 1460, 1394, - 1150, 264, 264, 264, 264, 264, 579, 1144, 874, 1340, - 1375, 1003, 575, 264, 784, 923, 264, 306, 307, 590, - 264, 300, 1432, 841, 264, 1104, 850, 851, 852, 853, - 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, - 864, 1084, 839, 81, 301, 58, 1048, 1431, 1106, 1107, - 1128, 1109, 1099, 1140, 1047, 1382, 1127, 568, 1100, 1101, - 1079, 1076, 690, 690, 690, 690, 690, 802, 1129, 1117, - 1130, 879, 1105, 592, 1125, 1108, 1506, 925, 1442, 1124, - 1368, 899, 1132, 1506, 1505, 690, 1149, 810, 1157, 1158, - 60, 81, 81, 915, 918, 919, 920, 916, 62, 917, - 921, 393, 55, 1145, 1146, 1, 1498, 1308, 393, 1376, - 1009, 1462, 1171, 1408, 1279, 960, 951, 69, 515, 68, - 1453, 81, 959, 958, 393, 393, 1166, 1416, 1366, 393, - 393, 393, 971, 393, 393, 1154, 974, 264, 1286, 393, - 393, 1200, 1186, 1151, 1458, 721, 81, 719, 720, 1172, - 718, 723, 1159, 547, 1161, 1162, 1163, 722, 717, 277, - 386, 922, 709, 999, 593, 1201, 72, 1188, 823, 1187, - 1005, 807, 562, 563, 279, 629, 1046, 1133, 599, 392, - 954, 393, 547, 1251, 816, 582, 1430, 1381, 1211, 1212, - 1083, 81, 81, 1245, 656, 892, 326, 831, 339, 1230, - 1236, 1229, 1248, 1217, 336, 337, 822, 1096, 603, 324, - 316, 688, 681, 1104, 914, 81, 912, 1043, 580, 584, - 911, 381, 871, 1262, 1258, 687, 1207, 1335, 1437, 1206, - 81, 840, 81, 81, 1264, 602, 1255, 826, 896, 26, - 59, 311, 1278, 19, 1271, 18, 1250, 17, 1270, 20, - 1249, 16, 51, 15, 14, 900, 901, 533, 30, 21, - 264, 1277, 1273, 1339, 1282, 1283, 1284, 1058, 1059, 1060, - 646, 13, 12, 11, 10, 9, 8, 7, 264, 657, - 6, 393, 5, 1210, 81, 4, 302, 81, 81, 81, - 264, 23, 2, 0, 393, 0, 81, 0, 0, 264, - 820, 610, 609, 619, 620, 612, 613, 614, 615, 616, - 617, 618, 611, 0, 0, 621, 1240, 1301, 0, 631, - 1314, 0, 0, 0, 0, 1316, 0, 1290, 1291, 0, - 1302, 0, 1304, 0, 0, 0, 0, 1323, 0, 0, - 0, 1315, 0, 0, 0, 0, 0, 0, 0, 393, - 0, 393, 1300, 0, 0, 0, 0, 1341, 876, 878, - 690, 0, 0, 0, 0, 0, 393, 954, 81, 954, - 1303, 1351, 1104, 1350, 0, 689, 81, 0, 1140, 0, - 1360, 0, 1313, 0, 0, 0, 0, 1334, 0, 0, - 0, 81, 0, 0, 393, 0, 0, 0, 81, 0, - 0, 0, 0, 0, 1369, 0, 1371, 0, 0, 0, - 0, 1374, 0, 0, 0, 0, 0, 0, 0, 1356, - 1357, 1358, 0, 0, 0, 0, 1320, 1321, 0, 1322, - 0, 1383, 1324, 1210, 1326, 0, 0, 81, 81, 0, - 81, 0, 0, 0, 0, 81, 1248, 81, 81, 81, - 264, 0, 547, 81, 1403, 1395, 1404, 1405, 1406, 1402, - 0, 0, 0, 0, 0, 1413, 0, 1407, 0, 0, - 81, 264, 0, 0, 0, 1420, 0, 0, 0, 1428, - 0, 0, 1214, 1215, 0, 0, 806, 0, 1363, 896, - 0, 1397, 0, 0, 1249, 1231, 1232, 1398, 1233, 1234, - 1248, 1443, 0, 0, 0, 954, 81, 0, 0, 1450, - 1241, 1242, 829, 830, 1451, 0, 0, 81, 81, 0, - 0, 0, 0, 0, 0, 1465, 0, 1425, 1466, 0, - 1469, 0, 393, 0, 0, 1378, 81, 0, 1474, 1421, - 0, 1422, 0, 0, 1444, 0, 0, 264, 1249, 0, - 51, 0, 0, 0, 0, 81, 0, 0, 1104, 0, - 0, 0, 0, 1429, 1483, 646, 0, 0, 882, 883, - 0, 0, 1288, 0, 0, 0, 1488, 1490, 81, 0, - 1170, 393, 1064, 0, 0, 0, 1065, 1492, 0, 0, - 0, 1503, 0, 1069, 1070, 1071, 0, 0, 1514, 0, - 1077, 844, 0, 1080, 1081, 0, 0, 0, 0, 1087, - 393, 581, 0, 1089, 0, 0, 1092, 1093, 1094, 1095, - 0, 0, 0, 0, 0, 0, 948, 0, 0, 0, - 0, 0, 0, 1318, 0, 393, 0, 0, 1119, 1478, - 0, 0, 0, 0, 0, 274, 0, 262, 1501, 0, - 288, 0, 0, 0, 1378, 954, 0, 880, 881, 0, - 0, 886, 889, 890, 0, 0, 0, 0, 393, 284, - 0, 0, 0, 0, 0, 315, 0, 896, 384, 0, - 1252, 1254, 0, 262, 0, 262, 902, 689, 904, 905, - 0, 689, 0, 0, 0, 689, 0, 0, 0, 0, - 0, 0, 0, 0, 1254, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 393, - 267, 393, 1281, 0, 0, 0, 0, 270, 0, 0, - 1041, 1042, 0, 584, 0, 278, 273, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1385, 1386, 1387, 1388, 1389, 0, 0, 0, 1392, 1393, - 0, 0, 0, 0, 0, 0, 0, 0, 276, 0, - 0, 0, 0, 1305, 283, 0, 1310, 1311, 1312, 0, - 1216, 0, 0, 0, 0, 393, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1068, 0, 605, 0, 608, - 0, 268, 0, 0, 0, 622, 623, 624, 625, 626, - 627, 628, 1086, 606, 607, 604, 610, 609, 619, 620, - 612, 613, 614, 615, 616, 617, 618, 611, 280, 271, - 621, 281, 282, 287, 0, 1051, 896, 272, 275, 0, - 269, 286, 285, 844, 0, 0, 0, 0, 0, 0, - 1338, 0, 0, 0, 0, 0, 0, 393, 0, 0, - 0, 0, 0, 262, 0, 1365, 262, 0, 0, 0, - 0, 0, 262, 0, 0, 0, 0, 0, 262, 0, - 393, 0, 1066, 0, 0, 0, 0, 393, 610, 609, - 619, 620, 612, 613, 614, 615, 616, 617, 618, 611, - 1082, 0, 621, 0, 0, 0, 0, 689, 689, 689, - 689, 689, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1507, 689, 0, 0, 1317, 1399, 1400, 0, 1401, - 689, 0, 1319, 0, 1365, 0, 1365, 1365, 1365, 0, - 0, 0, 1281, 1328, 1329, 0, 0, 0, 0, 0, - 0, 0, 1333, 1203, 0, 0, 0, 0, 0, 1365, - 0, 0, 0, 1343, 1344, 1345, 0, 1348, 0, 0, - 0, 0, 0, 24, 25, 52, 27, 28, 1332, 0, - 0, 0, 0, 0, 1359, 0, 0, 0, 0, 262, - 262, 262, 43, 0, 0, 1457, 0, 29, 48, 49, - 0, 0, 0, 1238, 0, 0, 393, 393, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, - 0, 54, 896, 0, 0, 1476, 610, 609, 619, 620, - 612, 613, 614, 615, 616, 617, 618, 611, 0, 0, - 621, 0, 0, 0, 1482, 1272, 0, 0, 0, 1390, - 0, 0, 610, 609, 619, 620, 612, 613, 614, 615, - 616, 617, 618, 611, 0, 0, 621, 1365, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 31, 32, 34, 33, 36, 0, 50, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1433, - 1434, 1435, 1436, 0, 0, 0, 1440, 1441, 1331, 0, - 37, 44, 45, 0, 0, 46, 47, 35, 1447, 1448, - 1449, 0, 0, 0, 0, 0, 0, 0, 262, 0, - 0, 39, 40, 0, 41, 42, 0, 0, 262, 262, - 0, 0, 0, 0, 262, 0, 0, 262, 0, 1330, - 262, 1470, 0, 0, 790, 0, 0, 1337, 1475, 0, - 0, 0, 0, 0, 262, 0, 0, 646, 0, 0, - 0, 0, 0, 0, 0, 1352, 1480, 0, 1353, 0, - 0, 1355, 610, 609, 619, 620, 612, 613, 614, 615, - 616, 617, 618, 611, 0, 0, 621, 0, 0, 0, - 0, 0, 0, 0, 262, 689, 0, 0, 0, 0, - 0, 0, 0, 790, 0, 0, 53, 0, 1213, 0, - 0, 1515, 1516, 610, 609, 619, 620, 612, 613, 614, - 615, 616, 617, 618, 611, 0, 0, 621, 610, 609, - 619, 620, 612, 613, 614, 615, 616, 617, 618, 611, - 0, 1063, 621, 0, 0, 315, 0, 0, 0, 0, - 315, 315, 0, 0, 315, 315, 315, 0, 0, 0, - 897, 610, 609, 619, 620, 612, 613, 614, 615, 616, - 617, 618, 611, 0, 0, 621, 0, 0, 0, 315, - 315, 315, 315, 0, 262, 0, 0, 0, 0, 0, - 0, 0, 262, 930, 0, 0, 262, 262, 0, 0, - 262, 938, 790, 610, 609, 619, 620, 612, 613, 614, - 615, 616, 617, 618, 611, 0, 0, 621, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1468, - 646, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 262, 0, 0, 0, 0, 0, 0, 262, 262, 262, - 262, 262, 0, 262, 262, 0, 0, 262, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 738, 0, 0, 262, 0, 1036, 1037, 0, 0, - 0, 262, 0, 0, 0, 0, 790, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 315, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 315, 0, 0, 0, 726, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 315, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 897, 262, 262, 262, 262, 262, 739, 0, 0, - 0, 0, 0, 0, 1118, 0, 0, 262, 0, 0, - 0, 930, 0, 0, 0, 262, 0, 0, 0, 0, - 752, 755, 756, 757, 758, 759, 760, 0, 761, 762, - 763, 764, 765, 740, 741, 742, 743, 724, 725, 753, - 0, 727, 0, 728, 729, 730, 731, 732, 733, 734, - 735, 736, 737, 744, 745, 746, 747, 748, 749, 750, - 751, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 323, 1526, 1516, 1321, 1480, 654, 1392, 1379, 1210, 1118, + 327, 353, 1261, 340, 969, 1295, 942, 1425, 1262, 998, + 965, 1136, 1119, 940, 552, 1258, 968, 1012, 1163, 978, + 1268, 57, 81, 397, 301, 1274, 266, 1233, 801, 266, + 817, 879, 890, 1189, 1180, 886, 1075, 982, 715, 992, + 908, 292, 856, 585, 944, 591, 714, 521, 386, 701, + 391, 922, 1008, 310, 929, 597, 606, 266, 81, 383, + 325, 388, 266, 1142, 266, 696, 668, 704, 56, 1519, + 1503, 61, 695, 669, 1514, 653, 3, 1031, 1490, 1511, + 1322, 541, 1502, 563, 1489, 263, 293, 294, 295, 296, + 1250, 1030, 299, 329, 1351, 526, 314, 63, 64, 65, + 66, 67, 1454, 619, 618, 628, 629, 621, 622, 623, + 624, 625, 626, 627, 620, 1289, 385, 630, 556, 1151, + 1035, 523, 1150, 525, 716, 1152, 717, 300, 365, 1029, + 371, 372, 369, 370, 368, 367, 366, 1290, 1291, 960, + 961, 959, 579, 298, 373, 374, 261, 257, 258, 259, + 574, 394, 297, 1171, 575, 572, 573, 1234, 991, 1212, + 1382, 1399, 253, 999, 1342, 251, 1340, 255, 291, 790, + 577, 567, 568, 789, 1214, 787, 1513, 1510, 1481, 1026, + 1023, 1024, 1209, 1022, 558, 923, 560, 983, 1473, 1534, + 542, 1215, 528, 255, 1426, 1236, 794, 1530, 778, 1137, + 1139, 578, 1284, 985, 1283, 1282, 524, 1428, 788, 791, + 531, 268, 1213, 1434, 1206, 1033, 1036, 557, 559, 538, + 1208, 256, 1043, 642, 643, 1042, 1093, 1462, 1090, 1238, + 1362, 1242, 1219, 1237, 1147, 1235, 1103, 1069, 985, 828, + 1240, 710, 266, 610, 548, 1307, 966, 266, 620, 1239, + 630, 630, 1028, 266, 24, 25, 52, 27, 28, 266, + 254, 955, 1241, 1243, 81, 260, 81, 81, 1164, 81, + 825, 81, 1455, 43, 1027, 1427, 1138, 81, 29, 48, + 49, 252, 535, 605, 536, 822, 1471, 537, 522, 1443, + 554, 1272, 718, 999, 818, 1488, 1308, 70, 276, 38, + 984, 532, 555, 54, 1252, 1528, 540, 81, 1529, 780, + 1527, 909, 547, 1032, 1476, 1435, 1433, 1207, 549, 1205, + 1169, 520, 863, 286, 54, 1088, 593, 1087, 1034, 642, + 643, 642, 643, 71, 859, 984, 861, 862, 860, 581, + 582, 544, 545, 546, 604, 603, 619, 618, 628, 629, + 621, 622, 623, 624, 625, 626, 627, 620, 1089, 603, + 630, 605, 600, 1494, 31, 32, 34, 33, 36, 553, + 50, 266, 266, 266, 269, 605, 819, 1388, 988, 595, + 81, 272, 594, 909, 989, 1100, 81, 1535, 1387, 280, + 275, 527, 37, 44, 45, 694, 1184, 46, 47, 35, + 1076, 621, 622, 623, 624, 625, 626, 627, 620, 604, + 603, 630, 1183, 39, 40, 985, 41, 42, 640, 584, + 1172, 880, 278, 881, 1348, 1496, 605, 1536, 285, 1153, + 693, 1154, 702, 671, 673, 675, 677, 679, 681, 682, + 672, 674, 703, 678, 680, 522, 683, 846, 848, 849, + 1472, 712, 708, 847, 1406, 270, 619, 618, 628, 629, + 621, 622, 623, 624, 625, 626, 627, 620, 529, 530, + 630, 1385, 1181, 394, 1052, 699, 623, 624, 625, 626, + 627, 620, 282, 273, 630, 283, 284, 289, 831, 832, + 806, 274, 277, 22, 271, 288, 287, 1469, 53, 619, + 618, 628, 629, 621, 622, 623, 624, 625, 626, 627, + 620, 266, 984, 630, 604, 603, 81, 981, 979, 1324, + 980, 266, 266, 81, 81, 81, 977, 983, 1164, 266, + 827, 605, 266, 1431, 1512, 266, 1159, 604, 603, 266, + 250, 81, 882, 352, 1498, 584, 81, 81, 81, 266, + 81, 81, 800, 305, 605, 799, 604, 603, 81, 81, + 913, 1431, 1484, 1254, 1431, 584, 805, 781, 826, 779, + 726, 776, 803, 605, 550, 79, 1066, 1067, 1068, 543, + 782, 783, 534, 1354, 533, 604, 603, 81, 792, 1431, + 1463, 385, 266, 584, 798, 1431, 1430, 1440, 81, 889, + 1439, 795, 605, 1377, 1376, 380, 381, 1304, 811, 354, + 51, 396, 1364, 584, 986, 857, 1361, 584, 833, 1314, + 1313, 619, 618, 628, 629, 621, 622, 623, 624, 625, + 626, 627, 620, 1271, 854, 630, 1310, 1311, 1259, 852, + 1211, 1271, 81, 343, 342, 345, 346, 347, 348, 835, + 892, 842, 344, 349, 1310, 1309, 1082, 584, 926, 584, + 1222, 51, 899, 902, 850, 892, 584, 706, 910, 306, + 725, 724, 58, 1357, 706, 81, 81, 24, 931, 934, + 935, 936, 932, 266, 933, 937, 1143, 24, 1275, 1276, + 24, 266, 266, 1442, 853, 266, 266, 1143, 926, 266, + 266, 266, 81, 883, 884, 1082, 1411, 858, 1312, 925, + 707, 1113, 709, 1082, 1155, 81, 1114, 707, 950, 705, + 906, 958, 952, 918, 919, 1106, 54, 949, 1105, 705, + 926, 1082, 894, 705, 803, 926, 54, 307, 711, 54, + 1395, 1271, 924, 829, 793, 54, 1504, 1394, 993, 1000, + 1001, 1002, 1369, 1013, 948, 951, 1300, 1158, 953, 1009, + 957, 1004, 956, 1275, 1276, 1521, 1003, 1016, 1517, 266, + 81, 1302, 81, 973, 994, 995, 996, 997, 266, 266, + 266, 266, 266, 1278, 266, 266, 54, 1259, 266, 81, + 1005, 1006, 1007, 1014, 699, 394, 1185, 823, 699, 797, + 1130, 1128, 699, 1197, 841, 1131, 1129, 266, 970, 266, + 266, 1281, 1280, 1132, 266, 935, 936, 396, 1054, 396, + 396, 1127, 396, 1126, 396, 1010, 1011, 1508, 1017, 1501, + 396, 1218, 1049, 1195, 311, 312, 1506, 1037, 1038, 1039, + 1040, 1041, 598, 1044, 1045, 1064, 1063, 1046, 1176, 723, + 598, 1168, 854, 586, 551, 599, 1478, 1057, 596, 1477, + 608, 583, 857, 599, 1409, 587, 1048, 1166, 1160, 1355, + 1390, 1448, 1019, 1053, 796, 1058, 939, 1059, 308, 309, + 302, 1062, 303, 562, 58, 562, 562, 1447, 562, 1061, + 562, 931, 934, 935, 936, 932, 562, 933, 937, 1397, + 1196, 1143, 576, 1071, 1094, 1201, 1198, 1191, 1199, 1194, + 1091, 1190, 853, 816, 1192, 1193, 51, 266, 266, 266, + 266, 266, 1523, 1522, 1523, 601, 1120, 1459, 1200, 266, + 1383, 639, 266, 396, 641, 824, 266, 60, 62, 720, + 266, 55, 1, 1515, 1323, 1391, 1025, 1479, 1099, 1424, + 1294, 976, 967, 69, 858, 519, 68, 1470, 975, 81, + 974, 1432, 652, 1144, 656, 657, 658, 659, 660, 661, + 662, 663, 664, 1156, 667, 670, 670, 670, 676, 670, + 670, 676, 670, 684, 685, 686, 687, 688, 689, 690, + 1141, 700, 1133, 1122, 1123, 1381, 1125, 1148, 1115, 1121, + 987, 1165, 1124, 1170, 1173, 1174, 1347, 81, 81, 1175, + 990, 1177, 1178, 1179, 1145, 1301, 1146, 894, 1161, 1162, + 699, 699, 699, 699, 699, 1167, 1475, 731, 729, 730, + 728, 733, 732, 727, 279, 699, 389, 81, 938, 1182, + 719, 1015, 602, 699, 72, 1204, 1203, 1021, 821, 570, + 571, 266, 970, 281, 638, 1060, 1149, 1202, 395, 1266, + 81, 830, 590, 1188, 1446, 1396, 1098, 665, 907, 396, + 328, 845, 341, 338, 339, 836, 396, 396, 396, 1217, + 1112, 619, 618, 628, 629, 621, 622, 623, 624, 625, + 626, 627, 620, 320, 396, 630, 612, 326, 318, 396, + 396, 396, 698, 396, 396, 691, 1225, 81, 81, 1226, + 1220, 396, 396, 1260, 1120, 1232, 1263, 1245, 930, 1251, + 1244, 928, 927, 384, 1277, 1273, 697, 854, 1221, 1350, + 1453, 81, 1057, 840, 26, 562, 59, 313, 19, 18, + 837, 1346, 562, 562, 562, 17, 81, 20, 81, 81, + 1279, 608, 16, 1224, 396, 834, 15, 14, 539, 30, + 562, 1285, 1293, 21, 1286, 562, 562, 562, 13, 562, + 562, 12, 1292, 11, 10, 9, 266, 562, 562, 1297, + 1298, 1299, 1270, 8, 1305, 1306, 7, 1255, 6, 5, + 4, 304, 1265, 23, 266, 885, 2, 0, 0, 0, + 81, 0, 0, 81, 81, 81, 266, 0, 1288, 0, + 81, 911, 0, 266, 891, 893, 619, 618, 628, 629, + 621, 622, 623, 624, 625, 626, 627, 620, 915, 916, + 630, 1316, 1329, 0, 0, 1315, 1331, 0, 0, 970, + 0, 970, 0, 0, 1317, 0, 1319, 0, 0, 0, + 0, 51, 0, 1318, 0, 396, 1338, 895, 896, 0, + 0, 901, 904, 905, 0, 1328, 656, 0, 396, 0, + 0, 0, 1120, 0, 1335, 1336, 1356, 1337, 0, 316, + 1339, 0, 1341, 81, 1366, 1330, 917, 0, 0, 920, + 921, 81, 1365, 0, 0, 0, 0, 1156, 0, 0, + 0, 0, 0, 1224, 0, 0, 81, 0, 0, 0, + 941, 1375, 0, 81, 700, 0, 699, 0, 700, 1384, + 0, 1386, 0, 396, 0, 396, 628, 629, 621, 622, + 623, 624, 625, 626, 627, 620, 1378, 0, 630, 0, + 0, 0, 396, 0, 0, 0, 1398, 0, 0, 0, + 0, 0, 81, 81, 0, 81, 0, 0, 0, 1263, + 81, 0, 81, 81, 81, 266, 1410, 1418, 81, 1419, + 1421, 1422, 396, 0, 0, 1405, 970, 0, 0, 0, + 0, 1423, 0, 1429, 0, 81, 266, 1436, 0, 562, + 1417, 562, 1444, 0, 0, 1437, 0, 1438, 0, 0, + 0, 0, 0, 0, 0, 0, 1393, 0, 562, 0, + 0, 0, 0, 1263, 1460, 0, 0, 0, 0, 0, + 0, 0, 81, 0, 644, 645, 646, 647, 648, 649, + 650, 651, 1468, 81, 81, 1467, 1412, 0, 0, 1482, + 1065, 0, 0, 1078, 1486, 1445, 0, 1079, 1483, 0, + 0, 0, 0, 81, 0, 1084, 1085, 1086, 0, 1491, + 1120, 0, 1092, 1070, 266, 1095, 1096, 0, 0, 911, + 0, 1102, 81, 0, 0, 1104, 0, 0, 1107, 1108, + 1109, 1110, 1111, 1500, 0, 0, 0, 1080, 1081, 1461, + 0, 0, 0, 1505, 1507, 81, 0, 0, 0, 0, + 561, 1135, 1509, 0, 0, 0, 1097, 0, 1520, 0, + 0, 0, 396, 0, 0, 1531, 0, 0, 0, 0, + 0, 0, 0, 1495, 1353, 0, 1393, 970, 0, 0, + 0, 0, 1116, 1117, 0, 0, 700, 700, 700, 700, + 700, 0, 0, 0, 0, 589, 0, 0, 0, 0, + 0, 941, 0, 1140, 0, 0, 0, 0, 0, 700, + 1186, 396, 619, 618, 628, 629, 621, 622, 623, 624, + 625, 626, 627, 620, 0, 0, 630, 0, 0, 0, + 0, 264, 588, 592, 290, 0, 0, 1345, 0, 0, + 396, 0, 0, 0, 0, 0, 0, 0, 0, 611, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 317, + 0, 0, 387, 396, 0, 0, 0, 264, 0, 264, + 0, 0, 0, 0, 0, 0, 0, 562, 0, 0, + 0, 0, 0, 0, 655, 0, 0, 0, 0, 0, + 0, 1230, 1231, 666, 0, 0, 0, 396, 0, 0, + 0, 0, 0, 0, 0, 0, 562, 911, 0, 0, + 1267, 1269, 619, 618, 628, 629, 621, 622, 623, 624, + 625, 626, 627, 620, 0, 0, 630, 0, 0, 0, + 0, 0, 0, 0, 1269, 0, 619, 618, 628, 629, + 621, 622, 623, 624, 625, 626, 627, 620, 0, 396, + 630, 396, 1296, 0, 0, 0, 855, 1227, 0, 864, + 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, + 875, 876, 877, 878, 1264, 0, 51, 619, 618, 628, + 629, 621, 622, 623, 624, 625, 626, 627, 620, 0, + 0, 630, 618, 628, 629, 621, 622, 623, 624, 625, + 626, 627, 620, 1320, 0, 630, 1325, 1326, 1327, 0, + 0, 0, 0, 396, 914, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 564, 565, 0, 566, + 0, 569, 0, 0, 0, 0, 1332, 580, 0, 0, + 0, 0, 0, 0, 1334, 0, 0, 264, 0, 0, + 0, 0, 264, 0, 0, 1343, 1344, 0, 264, 0, + 0, 0, 0, 0, 264, 911, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1358, 1359, 1360, 0, 1363, + 0, 0, 700, 0, 807, 0, 396, 0, 0, 0, + 0, 0, 0, 0, 1380, 0, 1374, 1077, 0, 0, + 0, 0, 0, 0, 0, 0, 820, 0, 0, 396, + 1349, 0, 0, 0, 0, 0, 396, 619, 618, 628, + 629, 621, 622, 623, 624, 625, 626, 627, 620, 0, + 0, 630, 0, 843, 844, 0, 0, 0, 0, 0, + 0, 0, 1371, 1372, 1373, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1414, 1415, 0, 1416, 0, + 0, 0, 0, 1380, 0, 1380, 1380, 1380, 0, 0, + 0, 1296, 0, 0, 0, 562, 264, 264, 264, 0, + 0, 0, 1420, 0, 0, 0, 655, 0, 1380, 897, + 898, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1072, 1073, 1074, 0, 0, + 0, 1449, 1450, 1451, 1452, 0, 1456, 1264, 1457, 1458, + 1413, 0, 0, 0, 0, 1474, 0, 0, 0, 0, + 1464, 0, 1465, 1466, 0, 0, 396, 396, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 964, 0, + 1441, 0, 0, 911, 0, 0, 1493, 0, 0, 0, + 0, 0, 0, 0, 1487, 0, 0, 0, 0, 0, + 0, 1264, 1492, 51, 0, 1499, 777, 0, 0, 0, + 0, 0, 0, 784, 785, 786, 0, 0, 0, 0, + 1497, 0, 0, 0, 0, 0, 0, 0, 1380, 0, + 0, 804, 0, 0, 0, 0, 808, 809, 810, 0, + 812, 813, 0, 0, 0, 0, 264, 0, 814, 815, + 0, 0, 0, 0, 0, 0, 264, 264, 0, 0, + 0, 0, 0, 0, 264, 1532, 1533, 264, 0, 0, + 264, 0, 0, 0, 802, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 264, 0, 1055, 1056, 614, 592, + 617, 0, 0, 0, 0, 0, 631, 632, 633, 634, + 635, 636, 637, 1518, 615, 616, 613, 619, 618, 628, + 629, 621, 622, 623, 624, 625, 626, 627, 620, 0, + 0, 630, 0, 0, 0, 0, 0, 264, 0, 0, + 0, 0, 0, 0, 0, 0, 802, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1228, 1229, 1083, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1246, 1247, 0, 1248, 1249, 1101, + 0, 0, 0, 0, 0, 0, 0, 0, 317, 1256, + 1257, 0, 0, 317, 317, 0, 0, 317, 317, 317, + 0, 0, 0, 912, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 317, 317, 317, 317, 317, 0, 264, 0, + 0, 0, 0, 0, 0, 0, 264, 946, 0, 0, + 264, 264, 0, 0, 264, 954, 802, 0, 0, 0, + 0, 0, 1303, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1018, 0, 1020, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1047, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1333, 0, 0, 264, 0, 0, 0, 0, 0, + 0, 0, 0, 264, 264, 264, 264, 264, 0, 264, + 264, 0, 0, 264, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 264, 0, 1050, 1051, 0, 0, 0, 264, + 0, 0, 0, 0, 802, 0, 0, 0, 0, 0, + 1253, 0, 0, 0, 0, 0, 317, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 748, + 0, 0, 0, 1287, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 317, 317, 0, 0, 0, 0, 1400, + 1401, 1402, 1403, 1404, 0, 0, 0, 1407, 1408, 0, + 0, 0, 317, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 912, 264, 264, 264, 264, 264, 0, 0, 0, + 0, 0, 0, 0, 1134, 0, 0, 264, 0, 0, + 0, 946, 0, 0, 0, 264, 0, 0, 736, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1187, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1352, 0, 749, 0, 0, 0, + 0, 0, 0, 0, 655, 0, 0, 1216, 0, 0, + 0, 0, 1367, 0, 0, 1368, 0, 0, 1370, 762, + 765, 766, 767, 768, 769, 770, 0, 771, 772, 773, + 774, 775, 750, 751, 752, 753, 734, 735, 763, 0, + 737, 0, 738, 739, 740, 741, 742, 743, 744, 745, + 746, 747, 754, 755, 756, 757, 758, 759, 760, 761, + 0, 0, 0, 0, 0, 0, 264, 0, 0, 0, + 0, 0, 1524, 0, 0, 0, 317, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 317, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 802, + 764, 0, 0, 0, 0, 0, 0, 0, 0, 912, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1485, 655, 0, + 0, 264, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 264, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 264, 0, 0, 0, 0, 0, 0, 264, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 754, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 262, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 315, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 315, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1389, 912, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 790, 0, 0, 0, 0, 0, 0, 0, 0, 897, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1142,747 +1166,829 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 262, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 262, 0, 0, 0, 0, 0, 0, 0, 0, - 262, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 897, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 930, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 262, 0, 0, 0, 0, 0, 502, 490, - 0, 447, 505, 421, 437, 513, 438, 441, 478, 406, - 460, 165, 435, 0, 425, 401, 431, 402, 423, 449, - 111, 453, 420, 492, 463, 504, 137, 511, 139, 469, - 0, 211, 153, 0, 0, 451, 494, 458, 487, 446, - 479, 411, 468, 506, 436, 476, 507, 0, 0, 0, - 80, 0, 955, 956, 897, 0, 0, 0, 0, 101, - 0, 473, 501, 433, 475, 477, 400, 470, 262, 404, - 407, 512, 497, 428, 429, 1141, 0, 0, 0, 0, - 0, 0, 450, 459, 484, 444, 0, 0, 0, 0, - 0, 0, 0, 0, 426, 0, 467, 0, 0, 0, - 408, 405, 0, 0, 448, 0, 0, 0, 410, 0, - 427, 485, 0, 398, 119, 489, 496, 445, 265, 500, - 443, 442, 503, 184, 0, 215, 122, 136, 97, 83, - 93, 0, 121, 162, 191, 195, 493, 424, 432, 105, - 430, 193, 172, 231, 466, 174, 192, 140, 221, 185, - 230, 240, 241, 218, 238, 245, 208, 86, 217, 229, - 102, 203, 88, 227, 214, 151, 131, 132, 87, 0, - 189, 110, 117, 107, 164, 224, 225, 106, 248, 94, - 237, 90, 95, 236, 158, 220, 228, 152, 145, 89, - 226, 150, 144, 135, 114, 124, 182, 142, 183, 125, - 155, 154, 156, 0, 403, 0, 212, 234, 249, 99, - 419, 219, 243, 244, 0, 0, 100, 118, 113, 181, - 157, 96, 127, 209, 134, 141, 188, 247, 171, 194, - 103, 233, 210, 415, 418, 413, 414, 461, 462, 508, - 509, 510, 486, 409, 0, 416, 417, 0, 491, 498, - 499, 465, 82, 91, 138, 246, 186, 116, 235, 399, - 412, 109, 422, 0, 0, 434, 439, 440, 452, 454, - 455, 456, 457, 464, 471, 472, 474, 480, 481, 482, - 483, 488, 495, 514, 84, 85, 92, 98, 104, 108, - 112, 115, 120, 123, 126, 128, 129, 130, 133, 143, - 146, 147, 148, 149, 159, 160, 161, 163, 166, 167, - 168, 169, 170, 173, 175, 176, 177, 178, 179, 180, - 187, 190, 196, 197, 198, 199, 200, 201, 202, 204, - 205, 206, 207, 213, 216, 222, 223, 232, 239, 242, - 502, 490, 0, 447, 505, 421, 437, 513, 438, 441, - 478, 406, 460, 165, 435, 0, 425, 401, 431, 402, - 423, 449, 111, 453, 420, 492, 463, 504, 137, 511, - 139, 469, 0, 211, 153, 0, 0, 451, 494, 458, - 487, 446, 479, 411, 468, 506, 436, 476, 507, 0, - 0, 0, 80, 0, 955, 956, 0, 0, 0, 0, - 0, 101, 0, 473, 501, 433, 475, 477, 400, 470, - 0, 404, 407, 512, 497, 428, 429, 0, 0, 0, - 0, 0, 0, 0, 450, 459, 484, 444, 0, 0, - 0, 0, 0, 0, 0, 0, 426, 0, 467, 0, - 0, 0, 408, 405, 0, 0, 448, 0, 0, 0, - 410, 0, 427, 485, 0, 398, 119, 489, 496, 445, - 265, 500, 443, 442, 503, 184, 0, 215, 122, 136, - 97, 83, 93, 0, 121, 162, 191, 195, 493, 424, - 432, 105, 430, 193, 172, 231, 466, 174, 192, 140, + 946, 0, 0, 0, 0, 0, 506, 494, 0, 451, + 509, 424, 441, 517, 442, 445, 482, 409, 464, 165, + 439, 264, 428, 404, 435, 405, 426, 453, 111, 457, + 423, 496, 467, 508, 137, 429, 515, 139, 473, 0, + 211, 153, 0, 0, 455, 498, 462, 491, 450, 483, + 414, 472, 510, 440, 480, 511, 0, 0, 0, 80, + 0, 971, 972, 0, 0, 0, 0, 0, 101, 0, + 477, 505, 437, 479, 481, 403, 474, 0, 407, 410, + 516, 501, 432, 433, 1157, 912, 0, 0, 0, 0, + 0, 454, 463, 488, 448, 0, 0, 0, 0, 264, + 0, 0, 0, 430, 0, 471, 0, 0, 0, 411, + 408, 0, 0, 452, 0, 0, 0, 413, 0, 431, + 489, 0, 401, 119, 493, 500, 449, 267, 504, 447, + 446, 507, 184, 0, 215, 122, 136, 97, 83, 93, + 0, 121, 162, 191, 195, 497, 427, 436, 105, 434, + 193, 172, 231, 470, 174, 192, 140, 221, 185, 230, + 240, 241, 218, 238, 245, 208, 86, 217, 229, 102, + 203, 88, 227, 214, 151, 131, 132, 87, 0, 189, + 110, 117, 107, 164, 224, 225, 106, 248, 94, 237, + 90, 95, 236, 158, 220, 228, 152, 145, 89, 226, + 150, 144, 135, 114, 124, 182, 142, 183, 125, 155, + 154, 156, 0, 406, 0, 212, 234, 249, 99, 422, + 219, 243, 244, 0, 0, 100, 118, 113, 181, 157, + 96, 127, 209, 134, 141, 188, 247, 171, 194, 103, + 233, 210, 418, 421, 416, 417, 465, 466, 512, 513, + 514, 490, 412, 0, 419, 420, 0, 495, 502, 503, + 469, 82, 91, 138, 246, 186, 116, 235, 402, 415, + 109, 425, 0, 0, 438, 443, 444, 456, 458, 459, + 460, 461, 468, 475, 476, 478, 484, 485, 486, 487, + 492, 499, 518, 84, 85, 92, 98, 104, 108, 112, + 115, 120, 123, 126, 128, 129, 130, 133, 143, 146, + 147, 148, 149, 159, 160, 161, 163, 166, 167, 168, + 169, 170, 173, 175, 176, 177, 178, 179, 180, 187, + 190, 196, 197, 198, 199, 200, 201, 202, 204, 205, + 206, 207, 213, 216, 222, 223, 232, 239, 242, 506, + 494, 0, 451, 509, 424, 441, 517, 442, 445, 482, + 409, 464, 165, 439, 0, 428, 404, 435, 405, 426, + 453, 111, 457, 423, 496, 467, 508, 137, 429, 515, + 139, 473, 0, 211, 153, 0, 0, 455, 498, 462, + 491, 450, 483, 414, 472, 510, 440, 480, 511, 0, + 0, 0, 80, 0, 971, 972, 0, 0, 0, 0, + 0, 101, 0, 477, 505, 437, 479, 481, 403, 474, + 0, 407, 410, 516, 501, 432, 433, 0, 0, 0, + 0, 0, 0, 0, 454, 463, 488, 448, 0, 0, + 0, 0, 0, 0, 0, 0, 430, 0, 471, 0, + 0, 0, 411, 408, 0, 0, 452, 0, 0, 0, + 413, 0, 431, 489, 0, 401, 119, 493, 500, 449, + 267, 504, 447, 446, 507, 184, 0, 215, 122, 136, + 97, 83, 93, 0, 121, 162, 191, 195, 497, 427, + 436, 105, 434, 193, 172, 231, 470, 174, 192, 140, 221, 185, 230, 240, 241, 218, 238, 245, 208, 86, 217, 229, 102, 203, 88, 227, 214, 151, 131, 132, 87, 0, 189, 110, 117, 107, 164, 224, 225, 106, 248, 94, 237, 90, 95, 236, 158, 220, 228, 152, 145, 89, 226, 150, 144, 135, 114, 124, 182, 142, - 183, 125, 155, 154, 156, 0, 403, 0, 212, 234, - 249, 99, 419, 219, 243, 244, 0, 0, 100, 118, + 183, 125, 155, 154, 156, 0, 406, 0, 212, 234, + 249, 99, 422, 219, 243, 244, 0, 0, 100, 118, 113, 181, 157, 96, 127, 209, 134, 141, 188, 247, - 171, 194, 103, 233, 210, 415, 418, 413, 414, 461, - 462, 508, 509, 510, 486, 409, 0, 416, 417, 0, - 491, 498, 499, 465, 82, 91, 138, 246, 186, 116, - 235, 399, 412, 109, 422, 0, 0, 434, 439, 440, - 452, 454, 455, 456, 457, 464, 471, 472, 474, 480, - 481, 482, 483, 488, 495, 514, 84, 85, 92, 98, + 171, 194, 103, 233, 210, 418, 421, 416, 417, 465, + 466, 512, 513, 514, 490, 412, 0, 419, 420, 0, + 495, 502, 503, 469, 82, 91, 138, 246, 186, 116, + 235, 402, 415, 109, 425, 0, 0, 438, 443, 444, + 456, 458, 459, 460, 461, 468, 475, 476, 478, 484, + 485, 486, 487, 492, 499, 518, 84, 85, 92, 98, 104, 108, 112, 115, 120, 123, 126, 128, 129, 130, 133, 143, 146, 147, 148, 149, 159, 160, 161, 163, 166, 167, 168, 169, 170, 173, 175, 176, 177, 178, 179, 180, 187, 190, 196, 197, 198, 199, 200, 201, 202, 204, 205, 206, 207, 213, 216, 222, 223, 232, - 239, 242, 502, 490, 0, 447, 505, 421, 437, 513, - 438, 441, 478, 406, 460, 165, 435, 0, 425, 401, - 431, 402, 423, 449, 111, 453, 420, 492, 463, 504, - 137, 511, 139, 469, 0, 211, 153, 0, 0, 451, - 494, 458, 487, 446, 479, 411, 468, 506, 436, 476, - 507, 54, 0, 0, 80, 0, 0, 0, 0, 0, - 0, 0, 0, 101, 0, 473, 501, 433, 475, 477, - 400, 470, 0, 404, 407, 512, 497, 428, 429, 0, - 0, 0, 0, 0, 0, 0, 450, 459, 484, 444, - 0, 0, 0, 0, 0, 0, 0, 0, 426, 0, - 467, 0, 0, 0, 408, 405, 0, 0, 448, 0, - 0, 0, 410, 0, 427, 485, 0, 398, 119, 489, - 496, 445, 265, 500, 443, 442, 503, 184, 0, 215, + 239, 242, 506, 494, 0, 451, 509, 424, 441, 517, + 442, 445, 482, 409, 464, 165, 439, 0, 428, 404, + 435, 405, 426, 453, 111, 457, 423, 496, 467, 508, + 137, 429, 515, 139, 473, 0, 211, 153, 0, 0, + 455, 498, 462, 491, 450, 483, 414, 472, 510, 440, + 480, 511, 54, 0, 0, 80, 0, 0, 0, 0, + 0, 0, 0, 0, 101, 0, 477, 505, 437, 479, + 481, 403, 474, 0, 407, 410, 516, 501, 432, 433, + 0, 0, 0, 0, 0, 0, 0, 454, 463, 488, + 448, 0, 0, 0, 0, 0, 0, 0, 0, 430, + 0, 471, 0, 0, 0, 411, 408, 0, 0, 452, + 0, 0, 0, 413, 0, 431, 489, 0, 401, 119, + 493, 500, 449, 267, 504, 447, 446, 507, 184, 0, + 215, 122, 136, 97, 83, 93, 0, 121, 162, 191, + 195, 497, 427, 436, 105, 434, 193, 172, 231, 470, + 174, 192, 140, 221, 185, 230, 240, 241, 218, 238, + 245, 208, 86, 217, 229, 102, 203, 88, 227, 214, + 151, 131, 132, 87, 0, 189, 110, 117, 107, 164, + 224, 225, 106, 248, 94, 237, 90, 95, 236, 158, + 220, 228, 152, 145, 89, 226, 150, 144, 135, 114, + 124, 182, 142, 183, 125, 155, 154, 156, 0, 406, + 0, 212, 234, 249, 99, 422, 219, 243, 244, 0, + 0, 100, 118, 113, 181, 157, 96, 127, 209, 134, + 141, 188, 247, 171, 194, 103, 233, 210, 418, 421, + 416, 417, 465, 466, 512, 513, 514, 490, 412, 0, + 419, 420, 0, 495, 502, 503, 469, 82, 91, 138, + 246, 186, 116, 235, 402, 415, 109, 425, 0, 0, + 438, 443, 444, 456, 458, 459, 460, 461, 468, 475, + 476, 478, 484, 485, 486, 487, 492, 499, 518, 84, + 85, 92, 98, 104, 108, 112, 115, 120, 123, 126, + 128, 129, 130, 133, 143, 146, 147, 148, 149, 159, + 160, 161, 163, 166, 167, 168, 169, 170, 173, 175, + 176, 177, 178, 179, 180, 187, 190, 196, 197, 198, + 199, 200, 201, 202, 204, 205, 206, 207, 213, 216, + 222, 223, 232, 239, 242, 506, 494, 0, 451, 509, + 424, 441, 517, 442, 445, 482, 409, 464, 165, 439, + 0, 428, 404, 435, 405, 426, 453, 111, 457, 423, + 496, 467, 508, 137, 429, 515, 139, 473, 0, 211, + 153, 0, 0, 455, 498, 462, 491, 450, 483, 414, + 472, 510, 440, 480, 511, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, 0, 101, 0, 477, + 505, 437, 479, 481, 403, 474, 0, 407, 410, 516, + 501, 432, 433, 0, 0, 0, 0, 0, 0, 0, + 454, 463, 488, 448, 0, 0, 0, 0, 0, 0, + 1223, 0, 430, 0, 471, 0, 0, 0, 411, 408, + 0, 0, 452, 0, 0, 0, 413, 0, 431, 489, + 0, 401, 119, 493, 500, 449, 267, 504, 447, 446, + 507, 184, 0, 215, 122, 136, 97, 83, 93, 0, + 121, 162, 191, 195, 497, 427, 436, 105, 434, 193, + 172, 231, 470, 174, 192, 140, 221, 185, 230, 240, + 241, 218, 238, 245, 208, 86, 217, 229, 102, 203, + 88, 227, 214, 151, 131, 132, 87, 0, 189, 110, + 117, 107, 164, 224, 225, 106, 248, 94, 237, 90, + 95, 236, 158, 220, 228, 152, 145, 89, 226, 150, + 144, 135, 114, 124, 182, 142, 183, 125, 155, 154, + 156, 0, 406, 0, 212, 234, 249, 99, 422, 219, + 243, 244, 0, 0, 100, 118, 113, 181, 157, 96, + 127, 209, 134, 141, 188, 247, 171, 194, 103, 233, + 210, 418, 421, 416, 417, 465, 466, 512, 513, 514, + 490, 412, 0, 419, 420, 0, 495, 502, 503, 469, + 82, 91, 138, 246, 186, 116, 235, 402, 415, 109, + 425, 0, 0, 438, 443, 444, 456, 458, 459, 460, + 461, 468, 475, 476, 478, 484, 485, 486, 487, 492, + 499, 518, 84, 85, 92, 98, 104, 108, 112, 115, + 120, 123, 126, 128, 129, 130, 133, 143, 146, 147, + 148, 149, 159, 160, 161, 163, 166, 167, 168, 169, + 170, 173, 175, 176, 177, 178, 179, 180, 187, 190, + 196, 197, 198, 199, 200, 201, 202, 204, 205, 206, + 207, 213, 216, 222, 223, 232, 239, 242, 506, 494, + 0, 451, 509, 424, 441, 517, 442, 445, 482, 409, + 464, 165, 439, 0, 428, 404, 435, 405, 426, 453, + 111, 457, 423, 496, 467, 508, 137, 429, 515, 139, + 473, 0, 211, 153, 0, 0, 455, 498, 462, 491, + 450, 483, 414, 472, 510, 440, 480, 511, 0, 0, + 0, 265, 0, 0, 0, 0, 0, 0, 0, 0, + 101, 0, 477, 505, 437, 479, 481, 403, 474, 0, + 407, 410, 516, 501, 432, 433, 0, 0, 0, 0, + 0, 0, 0, 454, 463, 488, 448, 0, 0, 0, + 0, 0, 0, 955, 0, 430, 0, 471, 0, 0, + 0, 411, 408, 0, 0, 452, 0, 0, 0, 413, + 0, 431, 489, 0, 401, 119, 493, 500, 449, 267, + 504, 447, 446, 507, 184, 0, 215, 122, 136, 97, + 83, 93, 0, 121, 162, 191, 195, 497, 427, 436, + 105, 434, 193, 172, 231, 470, 174, 192, 140, 221, + 185, 230, 240, 241, 218, 238, 245, 208, 86, 217, + 229, 102, 203, 88, 227, 214, 151, 131, 132, 87, + 0, 189, 110, 117, 107, 164, 224, 225, 106, 248, + 94, 237, 90, 95, 236, 158, 220, 228, 152, 145, + 89, 226, 150, 144, 135, 114, 124, 182, 142, 183, + 125, 155, 154, 156, 0, 406, 0, 212, 234, 249, + 99, 422, 219, 243, 244, 0, 0, 100, 118, 113, + 181, 157, 96, 127, 209, 134, 141, 188, 247, 171, + 194, 103, 233, 210, 418, 421, 416, 417, 465, 466, + 512, 513, 514, 490, 412, 0, 419, 420, 0, 495, + 502, 503, 469, 82, 91, 138, 246, 186, 116, 235, + 402, 415, 109, 425, 0, 0, 438, 443, 444, 456, + 458, 459, 460, 461, 468, 475, 476, 478, 484, 485, + 486, 487, 492, 499, 518, 84, 85, 92, 98, 104, + 108, 112, 115, 120, 123, 126, 128, 129, 130, 133, + 143, 146, 147, 148, 149, 159, 160, 161, 163, 166, + 167, 168, 169, 170, 173, 175, 176, 177, 178, 179, + 180, 187, 190, 196, 197, 198, 199, 200, 201, 202, + 204, 205, 206, 207, 213, 216, 222, 223, 232, 239, + 242, 506, 494, 0, 451, 509, 424, 441, 517, 442, + 445, 482, 409, 464, 165, 439, 0, 428, 404, 435, + 405, 426, 453, 111, 457, 423, 496, 467, 508, 137, + 429, 515, 139, 473, 0, 211, 153, 0, 0, 455, + 498, 462, 491, 450, 483, 414, 472, 510, 440, 480, + 511, 0, 0, 0, 322, 0, 0, 0, 0, 0, + 0, 0, 0, 101, 0, 477, 505, 437, 479, 481, + 403, 474, 0, 407, 410, 516, 501, 432, 433, 0, + 0, 0, 0, 0, 0, 0, 454, 463, 488, 448, + 0, 0, 0, 0, 0, 0, 851, 0, 430, 0, + 471, 0, 0, 0, 411, 408, 0, 0, 452, 0, + 0, 0, 413, 0, 431, 489, 0, 401, 119, 493, + 500, 449, 267, 504, 447, 446, 507, 184, 0, 215, 122, 136, 97, 83, 93, 0, 121, 162, 191, 195, - 493, 424, 432, 105, 430, 193, 172, 231, 466, 174, + 497, 427, 436, 105, 434, 193, 172, 231, 470, 174, 192, 140, 221, 185, 230, 240, 241, 218, 238, 245, 208, 86, 217, 229, 102, 203, 88, 227, 214, 151, 131, 132, 87, 0, 189, 110, 117, 107, 164, 224, 225, 106, 248, 94, 237, 90, 95, 236, 158, 220, 228, 152, 145, 89, 226, 150, 144, 135, 114, 124, - 182, 142, 183, 125, 155, 154, 156, 0, 403, 0, - 212, 234, 249, 99, 419, 219, 243, 244, 0, 0, + 182, 142, 183, 125, 155, 154, 156, 0, 406, 0, + 212, 234, 249, 99, 422, 219, 243, 244, 0, 0, 100, 118, 113, 181, 157, 96, 127, 209, 134, 141, - 188, 247, 171, 194, 103, 233, 210, 415, 418, 413, - 414, 461, 462, 508, 509, 510, 486, 409, 0, 416, - 417, 0, 491, 498, 499, 465, 82, 91, 138, 246, - 186, 116, 235, 399, 412, 109, 422, 0, 0, 434, - 439, 440, 452, 454, 455, 456, 457, 464, 471, 472, - 474, 480, 481, 482, 483, 488, 495, 514, 84, 85, + 188, 247, 171, 194, 103, 233, 210, 418, 421, 416, + 417, 465, 466, 512, 513, 514, 490, 412, 0, 419, + 420, 0, 495, 502, 503, 469, 82, 91, 138, 246, + 186, 116, 235, 402, 415, 109, 425, 0, 0, 438, + 443, 444, 456, 458, 459, 460, 461, 468, 475, 476, + 478, 484, 485, 486, 487, 492, 499, 518, 84, 85, 92, 98, 104, 108, 112, 115, 120, 123, 126, 128, 129, 130, 133, 143, 146, 147, 148, 149, 159, 160, 161, 163, 166, 167, 168, 169, 170, 173, 175, 176, 177, 178, 179, 180, 187, 190, 196, 197, 198, 199, 200, 201, 202, 204, 205, 206, 207, 213, 216, 222, - 223, 232, 239, 242, 502, 490, 0, 447, 505, 421, - 437, 513, 438, 441, 478, 406, 460, 165, 435, 0, - 425, 401, 431, 402, 423, 449, 111, 453, 420, 492, - 463, 504, 137, 511, 139, 469, 0, 211, 153, 0, - 0, 451, 494, 458, 487, 446, 479, 411, 468, 506, - 436, 476, 507, 0, 0, 0, 80, 0, 0, 0, - 0, 0, 0, 0, 0, 101, 0, 473, 501, 433, - 475, 477, 400, 470, 0, 404, 407, 512, 497, 428, - 429, 0, 0, 0, 0, 0, 0, 0, 450, 459, - 484, 444, 0, 0, 0, 0, 0, 0, 1209, 0, - 426, 0, 467, 0, 0, 0, 408, 405, 0, 0, - 448, 0, 0, 0, 410, 0, 427, 485, 0, 398, - 119, 489, 496, 445, 265, 500, 443, 442, 503, 184, + 223, 232, 239, 242, 506, 494, 0, 451, 509, 424, + 441, 517, 442, 445, 482, 409, 464, 165, 439, 0, + 428, 404, 435, 405, 426, 453, 111, 457, 423, 496, + 467, 508, 137, 429, 515, 139, 473, 0, 211, 153, + 0, 0, 455, 498, 462, 491, 450, 483, 414, 472, + 510, 440, 480, 511, 0, 0, 0, 80, 0, 0, + 0, 0, 0, 0, 0, 0, 101, 0, 477, 505, + 437, 479, 481, 403, 474, 0, 407, 410, 516, 501, + 432, 433, 0, 0, 0, 0, 0, 0, 0, 454, + 463, 488, 448, 0, 0, 0, 0, 0, 0, 0, + 0, 430, 0, 471, 0, 0, 0, 411, 408, 0, + 0, 452, 0, 0, 0, 413, 0, 431, 489, 0, + 401, 119, 493, 500, 449, 267, 504, 447, 446, 507, + 184, 0, 215, 122, 136, 97, 83, 93, 0, 121, + 162, 191, 195, 497, 427, 436, 105, 434, 193, 172, + 231, 470, 174, 192, 140, 221, 185, 230, 240, 241, + 218, 238, 245, 208, 86, 217, 229, 102, 203, 88, + 227, 214, 151, 131, 132, 87, 0, 189, 110, 117, + 107, 164, 224, 225, 106, 248, 94, 237, 90, 95, + 236, 158, 220, 228, 152, 145, 89, 226, 150, 144, + 135, 114, 124, 182, 142, 183, 125, 155, 154, 156, + 0, 406, 0, 212, 234, 249, 99, 422, 219, 243, + 244, 0, 0, 100, 118, 113, 181, 157, 96, 127, + 209, 134, 141, 188, 247, 171, 194, 103, 233, 210, + 418, 421, 416, 417, 465, 466, 512, 513, 514, 490, + 412, 0, 419, 420, 0, 495, 502, 503, 469, 82, + 91, 138, 246, 186, 116, 235, 402, 415, 109, 425, + 0, 0, 438, 443, 444, 456, 458, 459, 460, 461, + 468, 475, 476, 478, 484, 485, 486, 487, 492, 499, + 518, 84, 85, 92, 98, 104, 108, 112, 115, 120, + 123, 126, 128, 129, 130, 133, 143, 146, 147, 148, + 149, 159, 160, 161, 163, 166, 167, 168, 169, 170, + 173, 175, 176, 177, 178, 179, 180, 187, 190, 196, + 197, 198, 199, 200, 201, 202, 204, 205, 206, 207, + 213, 216, 222, 223, 232, 239, 242, 506, 494, 0, + 451, 509, 424, 441, 517, 442, 445, 482, 409, 464, + 165, 439, 0, 428, 404, 435, 405, 426, 453, 111, + 457, 423, 496, 467, 508, 137, 429, 515, 139, 473, + 0, 211, 153, 0, 0, 455, 498, 462, 491, 450, + 483, 414, 472, 510, 440, 480, 511, 0, 0, 0, + 322, 0, 0, 0, 0, 0, 0, 0, 0, 101, + 0, 477, 505, 437, 479, 481, 403, 474, 0, 407, + 410, 516, 501, 432, 433, 0, 0, 0, 0, 0, + 0, 0, 454, 463, 488, 448, 0, 0, 0, 0, + 0, 0, 0, 0, 430, 0, 471, 0, 0, 0, + 411, 408, 0, 0, 452, 0, 0, 0, 413, 0, + 431, 489, 0, 401, 119, 493, 500, 449, 267, 504, + 447, 446, 507, 184, 0, 215, 122, 136, 97, 83, + 93, 0, 121, 162, 191, 195, 497, 427, 436, 105, + 434, 193, 172, 231, 470, 174, 192, 140, 221, 185, + 230, 240, 241, 218, 238, 245, 208, 86, 217, 229, + 102, 203, 88, 227, 214, 151, 131, 132, 87, 0, + 189, 110, 117, 107, 164, 224, 225, 106, 248, 94, + 237, 90, 95, 236, 158, 220, 228, 152, 145, 89, + 226, 150, 144, 135, 114, 124, 182, 142, 183, 125, + 155, 154, 156, 0, 406, 0, 212, 234, 249, 99, + 422, 219, 243, 244, 0, 0, 100, 118, 113, 181, + 157, 96, 127, 209, 134, 141, 188, 247, 171, 194, + 103, 233, 210, 418, 421, 416, 417, 465, 466, 512, + 513, 514, 490, 412, 0, 419, 420, 0, 495, 502, + 503, 469, 82, 91, 138, 246, 186, 116, 235, 402, + 415, 109, 425, 0, 0, 438, 443, 444, 456, 458, + 459, 460, 461, 468, 475, 476, 478, 484, 485, 486, + 487, 492, 499, 518, 84, 85, 92, 98, 104, 108, + 112, 115, 120, 123, 126, 128, 129, 130, 133, 143, + 146, 147, 148, 149, 159, 160, 161, 163, 166, 167, + 168, 169, 170, 173, 175, 176, 177, 178, 179, 180, + 187, 190, 196, 197, 198, 199, 200, 201, 202, 204, + 205, 206, 207, 213, 216, 222, 223, 232, 239, 242, + 506, 494, 0, 451, 509, 424, 441, 517, 442, 445, + 482, 409, 464, 165, 439, 0, 428, 404, 435, 405, + 426, 453, 111, 457, 423, 496, 467, 508, 137, 429, + 515, 139, 473, 0, 211, 153, 0, 0, 455, 498, + 462, 491, 450, 483, 414, 472, 510, 440, 480, 511, + 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, + 0, 0, 101, 0, 477, 505, 437, 479, 481, 403, + 474, 0, 407, 410, 516, 501, 432, 433, 0, 0, + 0, 0, 0, 0, 0, 454, 463, 488, 448, 0, + 0, 0, 0, 0, 0, 0, 0, 430, 0, 471, + 0, 0, 0, 411, 408, 0, 0, 452, 0, 0, + 0, 413, 0, 431, 489, 0, 401, 119, 493, 500, + 449, 267, 504, 447, 446, 507, 184, 0, 215, 122, + 136, 97, 83, 93, 0, 121, 162, 191, 195, 497, + 427, 436, 105, 434, 193, 172, 231, 470, 174, 192, + 140, 221, 185, 230, 240, 241, 218, 238, 245, 208, + 86, 217, 229, 102, 203, 88, 227, 214, 151, 131, + 132, 87, 0, 189, 110, 117, 107, 164, 224, 225, + 106, 248, 94, 237, 90, 399, 236, 158, 220, 228, + 152, 145, 89, 226, 150, 144, 135, 114, 124, 182, + 142, 183, 125, 155, 154, 156, 0, 406, 0, 212, + 234, 249, 99, 422, 219, 243, 244, 0, 0, 100, + 118, 113, 181, 400, 398, 127, 209, 134, 141, 188, + 247, 171, 194, 103, 233, 210, 418, 421, 416, 417, + 465, 466, 512, 513, 514, 490, 412, 0, 419, 420, + 0, 495, 502, 503, 469, 82, 91, 138, 246, 186, + 116, 235, 402, 415, 109, 425, 0, 0, 438, 443, + 444, 456, 458, 459, 460, 461, 468, 475, 476, 478, + 484, 485, 486, 487, 492, 499, 518, 84, 85, 92, + 98, 104, 108, 112, 115, 120, 123, 126, 128, 129, + 130, 133, 143, 146, 147, 148, 149, 159, 160, 161, + 163, 166, 167, 168, 169, 170, 173, 175, 176, 177, + 178, 179, 180, 187, 190, 196, 197, 198, 199, 200, + 201, 202, 204, 205, 206, 207, 213, 216, 222, 223, + 232, 239, 242, 506, 494, 0, 451, 509, 424, 441, + 517, 442, 445, 482, 409, 464, 165, 439, 0, 428, + 404, 435, 405, 426, 453, 111, 457, 423, 496, 467, + 508, 137, 429, 515, 139, 473, 0, 211, 153, 0, + 0, 455, 498, 462, 491, 450, 483, 414, 472, 510, + 440, 480, 511, 0, 0, 0, 265, 0, 0, 0, + 0, 0, 0, 0, 0, 101, 0, 477, 505, 437, + 479, 481, 403, 474, 0, 407, 410, 516, 501, 432, + 433, 0, 0, 0, 0, 0, 0, 0, 454, 463, + 488, 448, 0, 0, 0, 0, 0, 0, 0, 0, + 430, 0, 471, 0, 0, 0, 411, 408, 0, 0, + 452, 0, 0, 0, 413, 0, 431, 489, 0, 401, + 119, 493, 500, 449, 267, 504, 447, 446, 507, 184, 0, 215, 122, 136, 97, 83, 93, 0, 121, 162, - 191, 195, 493, 424, 432, 105, 430, 193, 172, 231, - 466, 174, 192, 140, 221, 185, 230, 240, 241, 218, + 191, 195, 497, 427, 436, 105, 434, 193, 172, 231, + 470, 174, 192, 140, 221, 185, 230, 240, 241, 218, 238, 245, 208, 86, 217, 229, 102, 203, 88, 227, 214, 151, 131, 132, 87, 0, 189, 110, 117, 107, 164, 224, 225, 106, 248, 94, 237, 90, 95, 236, 158, 220, 228, 152, 145, 89, 226, 150, 144, 135, 114, 124, 182, 142, 183, 125, 155, 154, 156, 0, - 403, 0, 212, 234, 249, 99, 419, 219, 243, 244, + 406, 0, 212, 234, 249, 99, 422, 219, 243, 244, 0, 0, 100, 118, 113, 181, 157, 96, 127, 209, - 134, 141, 188, 247, 171, 194, 103, 233, 210, 415, - 418, 413, 414, 461, 462, 508, 509, 510, 486, 409, - 0, 416, 417, 0, 491, 498, 499, 465, 82, 91, - 138, 246, 186, 116, 235, 399, 412, 109, 422, 0, - 0, 434, 439, 440, 452, 454, 455, 456, 457, 464, - 471, 472, 474, 480, 481, 482, 483, 488, 495, 514, + 134, 141, 188, 247, 171, 194, 103, 233, 210, 418, + 421, 416, 417, 465, 466, 512, 513, 514, 490, 412, + 0, 419, 420, 0, 495, 502, 503, 469, 82, 91, + 138, 246, 186, 116, 235, 402, 415, 109, 425, 0, + 0, 438, 443, 444, 456, 458, 459, 460, 461, 468, + 475, 476, 478, 484, 485, 486, 487, 492, 499, 518, 84, 85, 92, 98, 104, 108, 112, 115, 120, 123, 126, 128, 129, 130, 133, 143, 146, 147, 148, 149, 159, 160, 161, 163, 166, 167, 168, 169, 170, 173, 175, 176, 177, 178, 179, 180, 187, 190, 196, 197, 198, 199, 200, 201, 202, 204, 205, 206, 207, 213, - 216, 222, 223, 232, 239, 242, 502, 490, 0, 447, - 505, 421, 437, 513, 438, 441, 478, 406, 460, 165, - 435, 0, 425, 401, 431, 402, 423, 449, 111, 453, - 420, 492, 463, 504, 137, 511, 139, 469, 0, 211, - 153, 0, 0, 451, 494, 458, 487, 446, 479, 411, - 468, 506, 436, 476, 507, 0, 0, 0, 263, 0, - 0, 0, 0, 0, 0, 0, 0, 101, 0, 473, - 501, 433, 475, 477, 400, 470, 0, 404, 407, 512, - 497, 428, 429, 0, 0, 0, 0, 0, 0, 0, - 450, 459, 484, 444, 0, 0, 0, 0, 0, 0, - 939, 0, 426, 0, 467, 0, 0, 0, 408, 405, - 0, 0, 448, 0, 0, 0, 410, 0, 427, 485, - 0, 398, 119, 489, 496, 445, 265, 500, 443, 442, - 503, 184, 0, 215, 122, 136, 97, 83, 93, 0, - 121, 162, 191, 195, 493, 424, 432, 105, 430, 193, - 172, 231, 466, 174, 192, 140, 221, 185, 230, 240, - 241, 218, 238, 245, 208, 86, 217, 229, 102, 203, - 88, 227, 214, 151, 131, 132, 87, 0, 189, 110, - 117, 107, 164, 224, 225, 106, 248, 94, 237, 90, - 95, 236, 158, 220, 228, 152, 145, 89, 226, 150, - 144, 135, 114, 124, 182, 142, 183, 125, 155, 154, - 156, 0, 403, 0, 212, 234, 249, 99, 419, 219, - 243, 244, 0, 0, 100, 118, 113, 181, 157, 96, - 127, 209, 134, 141, 188, 247, 171, 194, 103, 233, - 210, 415, 418, 413, 414, 461, 462, 508, 509, 510, - 486, 409, 0, 416, 417, 0, 491, 498, 499, 465, - 82, 91, 138, 246, 186, 116, 235, 399, 412, 109, - 422, 0, 0, 434, 439, 440, 452, 454, 455, 456, - 457, 464, 471, 472, 474, 480, 481, 482, 483, 488, - 495, 514, 84, 85, 92, 98, 104, 108, 112, 115, - 120, 123, 126, 128, 129, 130, 133, 143, 146, 147, - 148, 149, 159, 160, 161, 163, 166, 167, 168, 169, - 170, 173, 175, 176, 177, 178, 179, 180, 187, 190, - 196, 197, 198, 199, 200, 201, 202, 204, 205, 206, - 207, 213, 216, 222, 223, 232, 239, 242, 502, 490, - 0, 447, 505, 421, 437, 513, 438, 441, 478, 406, - 460, 165, 435, 0, 425, 401, 431, 402, 423, 449, - 111, 453, 420, 492, 463, 504, 137, 511, 139, 469, - 0, 211, 153, 0, 0, 451, 494, 458, 487, 446, - 479, 411, 468, 506, 436, 476, 507, 0, 0, 0, - 320, 0, 0, 0, 0, 0, 0, 0, 0, 101, - 0, 473, 501, 433, 475, 477, 400, 470, 0, 404, - 407, 512, 497, 428, 429, 0, 0, 0, 0, 0, - 0, 0, 450, 459, 484, 444, 0, 0, 0, 0, - 0, 0, 837, 0, 426, 0, 467, 0, 0, 0, - 408, 405, 0, 0, 448, 0, 0, 0, 410, 0, - 427, 485, 0, 398, 119, 489, 496, 445, 265, 500, - 443, 442, 503, 184, 0, 215, 122, 136, 97, 83, - 93, 0, 121, 162, 191, 195, 493, 424, 432, 105, - 430, 193, 172, 231, 466, 174, 192, 140, 221, 185, - 230, 240, 241, 218, 238, 245, 208, 86, 217, 229, - 102, 203, 88, 227, 214, 151, 131, 132, 87, 0, - 189, 110, 117, 107, 164, 224, 225, 106, 248, 94, - 237, 90, 95, 236, 158, 220, 228, 152, 145, 89, - 226, 150, 144, 135, 114, 124, 182, 142, 183, 125, - 155, 154, 156, 0, 403, 0, 212, 234, 249, 99, - 419, 219, 243, 244, 0, 0, 100, 118, 113, 181, - 157, 96, 127, 209, 134, 141, 188, 247, 171, 194, - 103, 233, 210, 415, 418, 413, 414, 461, 462, 508, - 509, 510, 486, 409, 0, 416, 417, 0, 491, 498, - 499, 465, 82, 91, 138, 246, 186, 116, 235, 399, - 412, 109, 422, 0, 0, 434, 439, 440, 452, 454, - 455, 456, 457, 464, 471, 472, 474, 480, 481, 482, - 483, 488, 495, 514, 84, 85, 92, 98, 104, 108, - 112, 115, 120, 123, 126, 128, 129, 130, 133, 143, - 146, 147, 148, 149, 159, 160, 161, 163, 166, 167, - 168, 169, 170, 173, 175, 176, 177, 178, 179, 180, - 187, 190, 196, 197, 198, 199, 200, 201, 202, 204, - 205, 206, 207, 213, 216, 222, 223, 232, 239, 242, - 502, 490, 0, 447, 505, 421, 437, 513, 438, 441, - 478, 406, 460, 165, 435, 0, 425, 401, 431, 402, - 423, 449, 111, 453, 420, 492, 463, 504, 137, 511, - 139, 469, 0, 211, 153, 0, 0, 451, 494, 458, - 487, 446, 479, 411, 468, 506, 436, 476, 507, 0, + 216, 222, 223, 232, 239, 242, 506, 494, 0, 451, + 509, 424, 441, 517, 442, 445, 482, 409, 464, 165, + 439, 0, 428, 404, 435, 405, 426, 453, 111, 457, + 423, 496, 467, 508, 137, 429, 515, 139, 473, 0, + 211, 153, 0, 0, 455, 498, 462, 491, 450, 483, + 414, 472, 510, 440, 480, 511, 0, 0, 0, 80, + 0, 0, 0, 0, 0, 0, 0, 0, 101, 0, + 477, 505, 437, 479, 481, 403, 474, 0, 407, 410, + 516, 501, 432, 433, 0, 0, 0, 0, 0, 0, + 0, 454, 463, 488, 448, 0, 0, 0, 0, 0, + 0, 0, 0, 430, 0, 471, 0, 0, 0, 411, + 408, 0, 0, 452, 0, 0, 0, 413, 0, 431, + 489, 0, 401, 119, 493, 500, 449, 267, 504, 447, + 446, 507, 184, 0, 215, 122, 136, 97, 83, 93, + 0, 121, 162, 191, 195, 497, 427, 436, 105, 434, + 193, 172, 231, 470, 174, 192, 140, 221, 185, 230, + 240, 241, 218, 238, 245, 208, 86, 217, 713, 102, + 203, 88, 227, 214, 151, 131, 132, 87, 0, 189, + 110, 117, 107, 164, 224, 225, 106, 248, 94, 237, + 90, 399, 236, 158, 220, 228, 152, 145, 89, 226, + 150, 144, 135, 114, 124, 182, 142, 183, 125, 155, + 154, 156, 0, 406, 0, 212, 234, 249, 99, 422, + 219, 243, 244, 0, 0, 100, 118, 113, 181, 400, + 398, 127, 209, 134, 141, 188, 247, 171, 194, 103, + 233, 210, 418, 421, 416, 417, 465, 466, 512, 513, + 514, 490, 412, 0, 419, 420, 0, 495, 502, 503, + 469, 82, 91, 138, 246, 186, 116, 235, 402, 415, + 109, 425, 0, 0, 438, 443, 444, 456, 458, 459, + 460, 461, 468, 475, 476, 478, 484, 485, 486, 487, + 492, 499, 518, 84, 85, 92, 98, 104, 108, 112, + 115, 120, 123, 126, 128, 129, 130, 133, 143, 146, + 147, 148, 149, 159, 160, 161, 163, 166, 167, 168, + 169, 170, 173, 175, 176, 177, 178, 179, 180, 187, + 190, 196, 197, 198, 199, 200, 201, 202, 204, 205, + 206, 207, 213, 216, 222, 223, 232, 239, 242, 506, + 494, 0, 451, 509, 424, 441, 517, 442, 445, 482, + 409, 464, 165, 439, 0, 428, 404, 435, 405, 426, + 453, 111, 457, 423, 496, 467, 508, 137, 429, 515, + 139, 473, 0, 211, 153, 0, 0, 455, 498, 462, + 491, 450, 483, 414, 472, 510, 440, 480, 511, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, - 0, 101, 0, 473, 501, 433, 475, 477, 400, 470, - 0, 404, 407, 512, 497, 428, 429, 0, 0, 0, - 0, 0, 0, 0, 450, 459, 484, 444, 0, 0, - 0, 0, 0, 0, 0, 0, 426, 0, 467, 0, - 0, 0, 408, 405, 0, 0, 448, 0, 0, 0, - 410, 0, 427, 485, 0, 398, 119, 489, 496, 445, - 265, 500, 443, 442, 503, 184, 0, 215, 122, 136, - 97, 83, 93, 0, 121, 162, 191, 195, 493, 424, - 432, 105, 430, 193, 172, 231, 466, 174, 192, 140, + 0, 101, 0, 477, 505, 437, 479, 481, 403, 474, + 0, 407, 410, 516, 501, 432, 433, 0, 0, 0, + 0, 0, 0, 0, 454, 463, 488, 448, 0, 0, + 0, 0, 0, 0, 0, 0, 430, 0, 471, 0, + 0, 0, 411, 408, 0, 0, 452, 0, 0, 0, + 413, 0, 431, 489, 0, 401, 119, 493, 500, 449, + 267, 504, 447, 446, 507, 184, 0, 215, 122, 136, + 97, 83, 93, 0, 121, 162, 191, 195, 497, 427, + 436, 105, 434, 193, 172, 231, 470, 174, 192, 140, + 221, 185, 230, 240, 241, 218, 238, 245, 208, 86, + 217, 390, 102, 203, 88, 227, 214, 151, 131, 132, + 87, 0, 189, 110, 117, 107, 164, 224, 225, 106, + 248, 94, 237, 90, 399, 236, 158, 220, 228, 152, + 145, 89, 226, 150, 144, 135, 114, 124, 182, 142, + 183, 125, 155, 154, 156, 0, 406, 0, 212, 234, + 249, 99, 422, 219, 243, 244, 0, 0, 100, 118, + 113, 181, 400, 398, 393, 392, 134, 141, 188, 247, + 171, 194, 103, 233, 210, 418, 421, 416, 417, 465, + 466, 512, 513, 514, 490, 412, 0, 419, 420, 0, + 495, 502, 503, 469, 82, 91, 138, 246, 186, 116, + 235, 402, 415, 109, 425, 0, 0, 438, 443, 444, + 456, 458, 459, 460, 461, 468, 475, 476, 478, 484, + 485, 486, 487, 492, 499, 518, 84, 85, 92, 98, + 104, 108, 112, 115, 120, 123, 126, 128, 129, 130, + 133, 143, 146, 147, 148, 149, 159, 160, 161, 163, + 166, 167, 168, 169, 170, 173, 175, 176, 177, 178, + 179, 180, 187, 190, 196, 197, 198, 199, 200, 201, + 202, 204, 205, 206, 207, 213, 216, 222, 223, 232, + 239, 242, 165, 0, 0, 887, 0, 324, 0, 0, + 0, 111, 0, 321, 0, 0, 0, 137, 888, 364, + 139, 0, 0, 211, 153, 0, 0, 0, 0, 355, + 356, 0, 0, 0, 0, 0, 0, 0, 0, 54, + 0, 0, 322, 343, 342, 345, 346, 347, 348, 0, + 0, 101, 344, 349, 350, 351, 0, 0, 0, 319, + 336, 0, 363, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 333, 334, 315, 0, 0, 0, 378, 0, + 335, 0, 0, 330, 331, 332, 337, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 119, 377, 0, 0, + 267, 0, 0, 375, 0, 184, 0, 215, 122, 136, + 97, 83, 93, 0, 121, 162, 191, 195, 0, 0, + 0, 105, 0, 193, 172, 231, 0, 174, 192, 140, + 221, 185, 230, 240, 241, 218, 238, 245, 208, 86, + 217, 229, 102, 203, 88, 227, 214, 151, 131, 132, + 87, 0, 189, 110, 117, 107, 164, 224, 225, 106, + 248, 94, 237, 90, 95, 236, 158, 220, 228, 152, + 145, 89, 226, 150, 144, 135, 114, 124, 182, 142, + 183, 125, 155, 154, 156, 0, 0, 0, 212, 234, + 249, 99, 0, 219, 243, 244, 0, 0, 100, 118, + 113, 181, 157, 96, 127, 209, 134, 141, 188, 247, + 171, 194, 103, 233, 210, 365, 376, 371, 372, 369, + 370, 368, 367, 366, 379, 357, 358, 359, 360, 362, + 0, 373, 374, 361, 82, 91, 138, 246, 186, 116, + 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 84, 85, 92, 98, + 104, 108, 112, 115, 120, 123, 126, 128, 129, 130, + 133, 143, 146, 147, 148, 149, 159, 160, 161, 163, + 166, 167, 168, 169, 170, 173, 175, 176, 177, 178, + 179, 180, 187, 190, 196, 197, 198, 199, 200, 201, + 202, 204, 205, 206, 207, 213, 216, 222, 223, 232, + 239, 242, 165, 0, 0, 0, 0, 324, 0, 0, + 0, 111, 0, 321, 0, 0, 0, 137, 0, 364, + 139, 0, 0, 211, 153, 0, 0, 0, 0, 355, + 356, 0, 0, 0, 0, 0, 0, 962, 0, 54, + 0, 0, 322, 343, 342, 345, 346, 347, 348, 0, + 0, 101, 344, 349, 350, 351, 963, 0, 0, 319, + 336, 0, 363, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 333, 334, 0, 0, 0, 0, 378, 0, + 335, 0, 0, 330, 331, 332, 337, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 119, 377, 0, 0, + 267, 0, 0, 375, 0, 184, 0, 215, 122, 136, + 97, 83, 93, 0, 121, 162, 191, 195, 0, 0, + 0, 105, 0, 193, 172, 231, 0, 174, 192, 140, + 221, 185, 230, 240, 241, 218, 238, 245, 208, 86, + 217, 229, 102, 203, 88, 227, 214, 151, 131, 132, + 87, 0, 189, 110, 117, 107, 164, 224, 225, 106, + 248, 94, 237, 90, 95, 236, 158, 220, 228, 152, + 145, 89, 226, 150, 144, 135, 114, 124, 182, 142, + 183, 125, 155, 154, 156, 0, 0, 0, 212, 234, + 249, 99, 0, 219, 243, 244, 0, 0, 100, 118, + 113, 181, 157, 96, 127, 209, 134, 141, 188, 247, + 171, 194, 103, 233, 210, 365, 376, 371, 372, 369, + 370, 368, 367, 366, 379, 357, 358, 359, 360, 362, + 0, 373, 374, 361, 82, 91, 138, 246, 186, 116, + 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 84, 85, 92, 98, + 104, 108, 112, 115, 120, 123, 126, 128, 129, 130, + 133, 143, 146, 147, 148, 149, 159, 160, 161, 163, + 166, 167, 168, 169, 170, 173, 175, 176, 177, 178, + 179, 180, 187, 190, 196, 197, 198, 199, 200, 201, + 202, 204, 205, 206, 207, 213, 216, 222, 223, 232, + 239, 242, 165, 0, 0, 0, 0, 324, 0, 0, + 0, 111, 0, 321, 0, 0, 0, 137, 0, 364, + 139, 0, 0, 211, 153, 0, 0, 0, 0, 355, + 356, 0, 0, 0, 0, 0, 0, 0, 0, 54, + 0, 584, 322, 343, 342, 345, 346, 347, 348, 0, + 0, 101, 344, 349, 350, 351, 0, 0, 0, 319, + 336, 0, 363, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 333, 334, 0, 0, 0, 0, 378, 0, + 335, 0, 0, 330, 331, 332, 337, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 119, 377, 0, 0, + 267, 0, 0, 375, 0, 184, 0, 215, 122, 136, + 97, 83, 93, 0, 121, 162, 191, 195, 0, 0, + 0, 105, 0, 193, 172, 231, 0, 174, 192, 140, + 221, 185, 230, 240, 241, 218, 238, 245, 208, 86, + 217, 229, 102, 203, 88, 227, 214, 151, 131, 132, + 87, 0, 189, 110, 117, 107, 164, 224, 225, 106, + 248, 94, 237, 90, 95, 236, 158, 220, 228, 152, + 145, 89, 226, 150, 144, 135, 114, 124, 182, 142, + 183, 125, 155, 154, 156, 0, 0, 0, 212, 234, + 249, 99, 0, 219, 243, 244, 0, 0, 100, 118, + 113, 181, 157, 96, 127, 209, 134, 141, 188, 247, + 171, 194, 103, 233, 210, 365, 376, 371, 372, 369, + 370, 368, 367, 366, 379, 357, 358, 359, 360, 362, + 0, 373, 374, 361, 82, 91, 138, 246, 186, 116, + 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 84, 85, 92, 98, + 104, 108, 112, 115, 120, 123, 126, 128, 129, 130, + 133, 143, 146, 147, 148, 149, 159, 160, 161, 163, + 166, 167, 168, 169, 170, 173, 175, 176, 177, 178, + 179, 180, 187, 190, 196, 197, 198, 199, 200, 201, + 202, 204, 205, 206, 207, 213, 216, 222, 223, 232, + 239, 242, 165, 0, 0, 0, 0, 324, 0, 0, + 0, 111, 0, 321, 0, 0, 0, 137, 0, 364, + 139, 0, 0, 211, 153, 0, 0, 0, 0, 355, + 356, 0, 0, 0, 0, 0, 0, 0, 0, 54, + 0, 0, 322, 343, 342, 345, 346, 347, 348, 0, + 0, 101, 344, 349, 350, 351, 0, 0, 0, 319, + 336, 0, 363, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 333, 334, 315, 0, 0, 0, 378, 0, + 335, 0, 0, 330, 331, 332, 337, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 119, 377, 0, 0, + 267, 0, 0, 375, 0, 184, 0, 215, 122, 136, + 97, 83, 93, 0, 121, 162, 191, 195, 0, 0, + 0, 105, 0, 193, 172, 231, 0, 174, 192, 140, + 221, 185, 230, 240, 241, 218, 238, 245, 208, 86, + 217, 229, 102, 203, 88, 227, 214, 151, 131, 132, + 87, 0, 189, 110, 117, 107, 164, 224, 225, 106, + 248, 94, 237, 90, 95, 236, 158, 220, 228, 152, + 145, 89, 226, 150, 144, 135, 114, 124, 182, 142, + 183, 125, 155, 154, 156, 0, 0, 0, 212, 234, + 249, 99, 0, 219, 243, 244, 0, 0, 100, 118, + 113, 181, 157, 96, 127, 209, 134, 141, 188, 247, + 171, 194, 103, 233, 210, 365, 376, 371, 372, 369, + 370, 368, 367, 366, 379, 357, 358, 359, 360, 362, + 0, 373, 374, 361, 82, 91, 138, 246, 186, 116, + 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 84, 85, 92, 98, + 104, 108, 112, 115, 120, 123, 126, 128, 129, 130, + 133, 143, 146, 147, 148, 149, 159, 160, 161, 163, + 166, 167, 168, 169, 170, 173, 175, 176, 177, 178, + 179, 180, 187, 190, 196, 197, 198, 199, 200, 201, + 202, 204, 205, 206, 207, 213, 216, 222, 223, 232, + 239, 242, 165, 0, 0, 0, 0, 324, 0, 0, + 0, 111, 0, 321, 0, 0, 0, 137, 0, 364, + 139, 0, 0, 211, 153, 0, 0, 0, 0, 355, + 356, 0, 0, 0, 0, 0, 0, 0, 0, 54, + 0, 0, 322, 343, 903, 345, 346, 347, 348, 0, + 0, 101, 344, 349, 350, 351, 0, 0, 0, 319, + 336, 0, 363, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 333, 334, 315, 0, 0, 0, 378, 0, + 335, 0, 0, 330, 331, 332, 337, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 119, 377, 0, 0, + 267, 0, 0, 375, 0, 184, 0, 215, 122, 136, + 97, 83, 93, 0, 121, 162, 191, 195, 0, 0, + 0, 105, 0, 193, 172, 231, 0, 174, 192, 140, + 221, 185, 230, 240, 241, 218, 238, 245, 208, 86, + 217, 229, 102, 203, 88, 227, 214, 151, 131, 132, + 87, 0, 189, 110, 117, 107, 164, 224, 225, 106, + 248, 94, 237, 90, 95, 236, 158, 220, 228, 152, + 145, 89, 226, 150, 144, 135, 114, 124, 182, 142, + 183, 125, 155, 154, 156, 0, 0, 0, 212, 234, + 249, 99, 0, 219, 243, 244, 0, 0, 100, 118, + 113, 181, 157, 96, 127, 209, 134, 141, 188, 247, + 171, 194, 103, 233, 210, 365, 376, 371, 372, 369, + 370, 368, 367, 366, 379, 357, 358, 359, 360, 362, + 0, 373, 374, 361, 82, 91, 138, 246, 186, 116, + 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 84, 85, 92, 98, + 104, 108, 112, 115, 120, 123, 126, 128, 129, 130, + 133, 143, 146, 147, 148, 149, 159, 160, 161, 163, + 166, 167, 168, 169, 170, 173, 175, 176, 177, 178, + 179, 180, 187, 190, 196, 197, 198, 199, 200, 201, + 202, 204, 205, 206, 207, 213, 216, 222, 223, 232, + 239, 242, 165, 0, 0, 0, 0, 324, 0, 0, + 0, 111, 0, 321, 0, 0, 0, 137, 0, 364, + 139, 0, 0, 211, 153, 0, 0, 0, 0, 355, + 356, 0, 0, 0, 0, 0, 0, 0, 0, 54, + 0, 0, 322, 343, 900, 345, 346, 347, 348, 0, + 0, 101, 344, 349, 350, 351, 0, 0, 0, 319, + 336, 0, 363, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 333, 334, 315, 0, 0, 0, 378, 0, + 335, 0, 0, 330, 331, 332, 337, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 119, 377, 0, 0, + 267, 0, 0, 375, 0, 184, 0, 215, 122, 136, + 97, 83, 93, 0, 121, 162, 191, 195, 0, 0, + 0, 105, 0, 193, 172, 231, 0, 174, 192, 140, 221, 185, 230, 240, 241, 218, 238, 245, 208, 86, 217, 229, 102, 203, 88, 227, 214, 151, 131, 132, 87, 0, 189, 110, 117, 107, 164, 224, 225, 106, 248, 94, 237, 90, 95, 236, 158, 220, 228, 152, 145, 89, 226, 150, 144, 135, 114, 124, 182, 142, - 183, 125, 155, 154, 156, 0, 403, 0, 212, 234, - 249, 99, 419, 219, 243, 244, 0, 0, 100, 118, + 183, 125, 155, 154, 156, 0, 0, 0, 212, 234, + 249, 99, 0, 219, 243, 244, 0, 0, 100, 118, 113, 181, 157, 96, 127, 209, 134, 141, 188, 247, - 171, 194, 103, 233, 210, 415, 418, 413, 414, 461, - 462, 508, 509, 510, 486, 409, 0, 416, 417, 0, - 491, 498, 499, 465, 82, 91, 138, 246, 186, 116, - 235, 399, 412, 109, 422, 0, 0, 434, 439, 440, - 452, 454, 455, 456, 457, 464, 471, 472, 474, 480, - 481, 482, 483, 488, 495, 514, 84, 85, 92, 98, + 171, 194, 103, 233, 210, 365, 376, 371, 372, 369, + 370, 368, 367, 366, 379, 357, 358, 359, 360, 362, + 0, 373, 374, 361, 82, 91, 138, 246, 186, 116, + 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 84, 85, 92, 98, 104, 108, 112, 115, 120, 123, 126, 128, 129, 130, 133, 143, 146, 147, 148, 149, 159, 160, 161, 163, 166, 167, 168, 169, 170, 173, 175, 176, 177, 178, 179, 180, 187, 190, 196, 197, 198, 199, 200, 201, 202, 204, 205, 206, 207, 213, 216, 222, 223, 232, - 239, 242, 502, 490, 0, 447, 505, 421, 437, 513, - 438, 441, 478, 406, 460, 165, 435, 0, 425, 401, - 431, 402, 423, 449, 111, 453, 420, 492, 463, 504, - 137, 511, 139, 469, 0, 211, 153, 0, 0, 451, - 494, 458, 487, 446, 479, 411, 468, 506, 436, 476, - 507, 0, 0, 0, 320, 0, 0, 0, 0, 0, - 0, 0, 0, 101, 0, 473, 501, 433, 475, 477, - 400, 470, 0, 404, 407, 512, 497, 428, 429, 0, - 0, 0, 0, 0, 0, 0, 450, 459, 484, 444, - 0, 0, 0, 0, 0, 0, 0, 0, 426, 0, - 467, 0, 0, 0, 408, 405, 0, 0, 448, 0, - 0, 0, 410, 0, 427, 485, 0, 398, 119, 489, - 496, 445, 265, 500, 443, 442, 503, 184, 0, 215, + 239, 242, 24, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 165, 0, 0, 0, 0, 324, + 0, 0, 0, 111, 0, 321, 0, 0, 0, 137, + 0, 364, 139, 0, 0, 211, 153, 0, 0, 0, + 0, 355, 356, 0, 0, 0, 0, 0, 0, 0, + 0, 54, 0, 0, 322, 343, 342, 345, 346, 347, + 348, 0, 0, 101, 344, 349, 350, 351, 0, 0, + 0, 319, 336, 0, 363, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 333, 334, 0, 0, 0, 0, + 378, 0, 335, 0, 0, 330, 331, 332, 337, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 119, 377, + 0, 0, 267, 0, 0, 375, 0, 184, 0, 215, 122, 136, 97, 83, 93, 0, 121, 162, 191, 195, - 493, 424, 432, 105, 430, 193, 172, 231, 466, 174, + 0, 0, 0, 105, 0, 193, 172, 231, 0, 174, 192, 140, 221, 185, 230, 240, 241, 218, 238, 245, 208, 86, 217, 229, 102, 203, 88, 227, 214, 151, 131, 132, 87, 0, 189, 110, 117, 107, 164, 224, 225, 106, 248, 94, 237, 90, 95, 236, 158, 220, 228, 152, 145, 89, 226, 150, 144, 135, 114, 124, - 182, 142, 183, 125, 155, 154, 156, 0, 403, 0, - 212, 234, 249, 99, 419, 219, 243, 244, 0, 0, + 182, 142, 183, 125, 155, 154, 156, 0, 0, 0, + 212, 234, 249, 99, 0, 219, 243, 244, 0, 0, 100, 118, 113, 181, 157, 96, 127, 209, 134, 141, - 188, 247, 171, 194, 103, 233, 210, 415, 418, 413, - 414, 461, 462, 508, 509, 510, 486, 409, 0, 416, - 417, 0, 491, 498, 499, 465, 82, 91, 138, 246, - 186, 116, 235, 399, 412, 109, 422, 0, 0, 434, - 439, 440, 452, 454, 455, 456, 457, 464, 471, 472, - 474, 480, 481, 482, 483, 488, 495, 514, 84, 85, + 188, 247, 171, 194, 103, 233, 210, 365, 376, 371, + 372, 369, 370, 368, 367, 366, 379, 357, 358, 359, + 360, 362, 0, 373, 374, 361, 82, 91, 138, 246, + 186, 116, 235, 0, 0, 109, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 84, 85, 92, 98, 104, 108, 112, 115, 120, 123, 126, 128, 129, 130, 133, 143, 146, 147, 148, 149, 159, 160, 161, 163, 166, 167, 168, 169, 170, 173, 175, 176, 177, 178, 179, 180, 187, 190, 196, 197, 198, 199, 200, 201, 202, 204, 205, 206, 207, 213, 216, 222, - 223, 232, 239, 242, 502, 490, 0, 447, 505, 421, - 437, 513, 438, 441, 478, 406, 460, 165, 435, 0, - 425, 401, 431, 402, 423, 449, 111, 453, 420, 492, - 463, 504, 137, 511, 139, 469, 0, 211, 153, 0, - 0, 451, 494, 458, 487, 446, 479, 411, 468, 506, - 436, 476, 507, 0, 0, 0, 80, 0, 0, 0, - 0, 0, 0, 0, 0, 101, 0, 473, 501, 433, - 475, 477, 400, 470, 0, 404, 407, 512, 497, 428, - 429, 0, 0, 0, 0, 0, 0, 0, 450, 459, - 484, 444, 0, 0, 0, 0, 0, 0, 0, 0, - 426, 0, 467, 0, 0, 0, 408, 405, 0, 0, - 448, 0, 0, 0, 410, 0, 427, 485, 0, 398, - 119, 489, 496, 445, 265, 500, 443, 442, 503, 184, - 0, 215, 122, 136, 97, 83, 93, 0, 121, 162, - 191, 195, 493, 424, 432, 105, 430, 193, 172, 231, - 466, 174, 192, 140, 221, 185, 230, 240, 241, 218, - 238, 245, 208, 86, 217, 229, 102, 203, 88, 227, - 214, 151, 131, 132, 87, 0, 189, 110, 117, 107, - 164, 224, 225, 106, 248, 94, 237, 90, 396, 236, - 158, 220, 228, 152, 145, 89, 226, 150, 144, 135, - 114, 124, 182, 142, 183, 125, 155, 154, 156, 0, - 403, 0, 212, 234, 249, 99, 419, 219, 243, 244, - 0, 0, 100, 118, 113, 181, 397, 395, 127, 209, - 134, 141, 188, 247, 171, 194, 103, 233, 210, 415, - 418, 413, 414, 461, 462, 508, 509, 510, 486, 409, - 0, 416, 417, 0, 491, 498, 499, 465, 82, 91, - 138, 246, 186, 116, 235, 399, 412, 109, 422, 0, - 0, 434, 439, 440, 452, 454, 455, 456, 457, 464, - 471, 472, 474, 480, 481, 482, 483, 488, 495, 514, - 84, 85, 92, 98, 104, 108, 112, 115, 120, 123, - 126, 128, 129, 130, 133, 143, 146, 147, 148, 149, - 159, 160, 161, 163, 166, 167, 168, 169, 170, 173, - 175, 176, 177, 178, 179, 180, 187, 190, 196, 197, - 198, 199, 200, 201, 202, 204, 205, 206, 207, 213, - 216, 222, 223, 232, 239, 242, 502, 490, 0, 447, - 505, 421, 437, 513, 438, 441, 478, 406, 460, 165, - 435, 0, 425, 401, 431, 402, 423, 449, 111, 453, - 420, 492, 463, 504, 137, 511, 139, 469, 0, 211, - 153, 0, 0, 451, 494, 458, 487, 446, 479, 411, - 468, 506, 436, 476, 507, 0, 0, 0, 263, 0, - 0, 0, 0, 0, 0, 0, 0, 101, 0, 473, - 501, 433, 475, 477, 400, 470, 0, 404, 407, 512, - 497, 428, 429, 0, 0, 0, 0, 0, 0, 0, - 450, 459, 484, 444, 0, 0, 0, 0, 0, 0, - 0, 0, 426, 0, 467, 0, 0, 0, 408, 405, - 0, 0, 448, 0, 0, 0, 410, 0, 427, 485, - 0, 398, 119, 489, 496, 445, 265, 500, 443, 442, - 503, 184, 0, 215, 122, 136, 97, 83, 93, 0, - 121, 162, 191, 195, 493, 424, 432, 105, 430, 193, - 172, 231, 466, 174, 192, 140, 221, 185, 230, 240, - 241, 218, 238, 245, 208, 86, 217, 229, 102, 203, - 88, 227, 214, 151, 131, 132, 87, 0, 189, 110, - 117, 107, 164, 224, 225, 106, 248, 94, 237, 90, - 95, 236, 158, 220, 228, 152, 145, 89, 226, 150, - 144, 135, 114, 124, 182, 142, 183, 125, 155, 154, - 156, 0, 403, 0, 212, 234, 249, 99, 419, 219, - 243, 244, 0, 0, 100, 118, 113, 181, 157, 96, - 127, 209, 134, 141, 188, 247, 171, 194, 103, 233, - 210, 415, 418, 413, 414, 461, 462, 508, 509, 510, - 486, 409, 0, 416, 417, 0, 491, 498, 499, 465, - 82, 91, 138, 246, 186, 116, 235, 399, 412, 109, - 422, 0, 0, 434, 439, 440, 452, 454, 455, 456, - 457, 464, 471, 472, 474, 480, 481, 482, 483, 488, - 495, 514, 84, 85, 92, 98, 104, 108, 112, 115, - 120, 123, 126, 128, 129, 130, 133, 143, 146, 147, - 148, 149, 159, 160, 161, 163, 166, 167, 168, 169, - 170, 173, 175, 176, 177, 178, 179, 180, 187, 190, - 196, 197, 198, 199, 200, 201, 202, 204, 205, 206, - 207, 213, 216, 222, 223, 232, 239, 242, 502, 490, - 0, 447, 505, 421, 437, 513, 438, 441, 478, 406, - 460, 165, 435, 0, 425, 401, 431, 402, 423, 449, - 111, 453, 420, 492, 463, 504, 137, 511, 139, 469, - 0, 211, 153, 0, 0, 451, 494, 458, 487, 446, - 479, 411, 468, 506, 436, 476, 507, 0, 0, 0, - 80, 0, 0, 0, 0, 0, 0, 0, 0, 101, - 0, 473, 501, 433, 475, 477, 400, 470, 0, 404, - 407, 512, 497, 428, 429, 0, 0, 0, 0, 0, - 0, 0, 450, 459, 484, 444, 0, 0, 0, 0, - 0, 0, 0, 0, 426, 0, 467, 0, 0, 0, - 408, 405, 0, 0, 448, 0, 0, 0, 410, 0, - 427, 485, 0, 398, 119, 489, 496, 445, 265, 500, - 443, 442, 503, 184, 0, 215, 122, 136, 97, 83, - 93, 0, 121, 162, 191, 195, 493, 424, 432, 105, - 430, 193, 172, 231, 466, 174, 192, 140, 221, 185, - 230, 240, 241, 218, 238, 245, 208, 86, 217, 703, - 102, 203, 88, 227, 214, 151, 131, 132, 87, 0, - 189, 110, 117, 107, 164, 224, 225, 106, 248, 94, - 237, 90, 396, 236, 158, 220, 228, 152, 145, 89, - 226, 150, 144, 135, 114, 124, 182, 142, 183, 125, - 155, 154, 156, 0, 403, 0, 212, 234, 249, 99, - 419, 219, 243, 244, 0, 0, 100, 118, 113, 181, - 397, 395, 127, 209, 134, 141, 188, 247, 171, 194, - 103, 233, 210, 415, 418, 413, 414, 461, 462, 508, - 509, 510, 486, 409, 0, 416, 417, 0, 491, 498, - 499, 465, 82, 91, 138, 246, 186, 116, 235, 399, - 412, 109, 422, 0, 0, 434, 439, 440, 452, 454, - 455, 456, 457, 464, 471, 472, 474, 480, 481, 482, - 483, 488, 495, 514, 84, 85, 92, 98, 104, 108, - 112, 115, 120, 123, 126, 128, 129, 130, 133, 143, - 146, 147, 148, 149, 159, 160, 161, 163, 166, 167, - 168, 169, 170, 173, 175, 176, 177, 178, 179, 180, - 187, 190, 196, 197, 198, 199, 200, 201, 202, 204, - 205, 206, 207, 213, 216, 222, 223, 232, 239, 242, - 502, 490, 0, 447, 505, 421, 437, 513, 438, 441, - 478, 406, 460, 165, 435, 0, 425, 401, 431, 402, - 423, 449, 111, 453, 420, 492, 463, 504, 137, 511, - 139, 469, 0, 211, 153, 0, 0, 451, 494, 458, - 487, 446, 479, 411, 468, 506, 436, 476, 507, 0, - 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, - 0, 101, 0, 473, 501, 433, 475, 477, 400, 470, - 0, 404, 407, 512, 497, 428, 429, 0, 0, 0, - 0, 0, 0, 0, 450, 459, 484, 444, 0, 0, - 0, 0, 0, 0, 0, 0, 426, 0, 467, 0, - 0, 0, 408, 405, 0, 0, 448, 0, 0, 0, - 410, 0, 427, 485, 0, 398, 119, 489, 496, 445, - 265, 500, 443, 442, 503, 184, 0, 215, 122, 136, - 97, 83, 93, 0, 121, 162, 191, 195, 493, 424, - 432, 105, 430, 193, 172, 231, 466, 174, 192, 140, - 221, 185, 230, 240, 241, 218, 238, 245, 208, 86, - 217, 387, 102, 203, 88, 227, 214, 151, 131, 132, - 87, 0, 189, 110, 117, 107, 164, 224, 225, 106, - 248, 94, 237, 90, 396, 236, 158, 220, 228, 152, - 145, 89, 226, 150, 144, 135, 114, 124, 182, 142, - 183, 125, 155, 154, 156, 0, 403, 0, 212, 234, - 249, 99, 419, 219, 243, 244, 0, 0, 100, 118, - 113, 181, 397, 395, 390, 389, 134, 141, 188, 247, - 171, 194, 103, 233, 210, 415, 418, 413, 414, 461, - 462, 508, 509, 510, 486, 409, 0, 416, 417, 0, - 491, 498, 499, 465, 82, 91, 138, 246, 186, 116, - 235, 399, 412, 109, 422, 0, 0, 434, 439, 440, - 452, 454, 455, 456, 457, 464, 471, 472, 474, 480, - 481, 482, 483, 488, 495, 514, 84, 85, 92, 98, - 104, 108, 112, 115, 120, 123, 126, 128, 129, 130, - 133, 143, 146, 147, 148, 149, 159, 160, 161, 163, - 166, 167, 168, 169, 170, 173, 175, 176, 177, 178, - 179, 180, 187, 190, 196, 197, 198, 199, 200, 201, - 202, 204, 205, 206, 207, 213, 216, 222, 223, 232, - 239, 242, 165, 0, 0, 0, 0, 322, 0, 0, - 0, 111, 0, 319, 0, 0, 0, 137, 362, 139, - 0, 0, 211, 153, 0, 0, 0, 0, 353, 354, - 0, 0, 0, 0, 0, 0, 946, 0, 54, 0, - 0, 320, 341, 340, 343, 344, 345, 346, 0, 0, - 101, 342, 347, 348, 349, 947, 0, 0, 317, 334, - 0, 361, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 331, 332, 0, 0, 0, 0, 375, 0, 333, - 0, 0, 328, 329, 330, 335, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 119, 0, 0, 0, 265, - 0, 0, 373, 0, 184, 0, 215, 122, 136, 97, - 83, 93, 0, 121, 162, 191, 195, 0, 0, 0, - 105, 0, 193, 172, 231, 0, 174, 192, 140, 221, - 185, 230, 240, 241, 218, 238, 245, 208, 86, 217, - 229, 102, 203, 88, 227, 214, 151, 131, 132, 87, - 0, 189, 110, 117, 107, 164, 224, 225, 106, 248, - 94, 237, 90, 95, 236, 158, 220, 228, 152, 145, - 89, 226, 150, 144, 135, 114, 124, 182, 142, 183, - 125, 155, 154, 156, 0, 0, 0, 212, 234, 249, - 99, 0, 219, 243, 244, 0, 0, 100, 118, 113, - 181, 157, 96, 127, 209, 134, 141, 188, 247, 171, - 194, 103, 233, 210, 363, 374, 369, 370, 367, 368, - 366, 365, 364, 376, 355, 356, 357, 358, 360, 0, - 371, 372, 359, 82, 91, 138, 246, 186, 116, 235, - 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 84, 85, 92, 98, 104, - 108, 112, 115, 120, 123, 126, 128, 129, 130, 133, - 143, 146, 147, 148, 149, 159, 160, 161, 163, 166, - 167, 168, 169, 170, 173, 175, 176, 177, 178, 179, - 180, 187, 190, 196, 197, 198, 199, 200, 201, 202, - 204, 205, 206, 207, 213, 216, 222, 223, 232, 239, - 242, 165, 0, 0, 873, 0, 322, 0, 0, 0, - 111, 0, 319, 0, 0, 0, 137, 362, 139, 0, - 0, 211, 153, 0, 0, 0, 0, 353, 354, 0, - 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, - 320, 341, 340, 343, 344, 345, 346, 0, 0, 101, - 342, 347, 348, 349, 0, 0, 0, 317, 334, 0, - 361, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 331, 332, 313, 0, 0, 0, 375, 0, 333, 0, - 0, 328, 329, 330, 335, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 119, 0, 0, 0, 265, 0, - 0, 373, 0, 184, 0, 215, 122, 136, 97, 83, - 93, 0, 121, 162, 191, 195, 0, 0, 0, 105, - 0, 193, 172, 231, 0, 174, 192, 140, 221, 185, - 230, 240, 241, 218, 238, 245, 208, 86, 217, 229, - 102, 203, 88, 227, 214, 151, 131, 132, 87, 0, - 189, 110, 117, 107, 164, 224, 225, 106, 248, 94, - 237, 90, 95, 236, 158, 220, 228, 152, 145, 89, - 226, 150, 144, 135, 114, 124, 182, 142, 183, 125, - 155, 154, 156, 0, 0, 0, 212, 234, 249, 99, - 0, 219, 243, 244, 0, 0, 100, 118, 113, 181, - 157, 96, 127, 209, 134, 141, 188, 247, 171, 194, - 103, 233, 210, 363, 374, 369, 370, 367, 368, 366, - 365, 364, 376, 355, 356, 357, 358, 360, 0, 371, - 372, 359, 82, 91, 138, 246, 186, 116, 235, 0, - 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 84, 85, 92, 98, 104, 108, - 112, 115, 120, 123, 126, 128, 129, 130, 133, 143, - 146, 147, 148, 149, 159, 160, 161, 163, 166, 167, - 168, 169, 170, 173, 175, 176, 177, 178, 179, 180, - 187, 190, 196, 197, 198, 199, 200, 201, 202, 204, - 205, 206, 207, 213, 216, 222, 223, 232, 239, 242, - 165, 0, 0, 0, 0, 322, 0, 0, 0, 111, - 0, 319, 0, 0, 0, 137, 362, 139, 0, 0, - 211, 153, 0, 0, 0, 0, 353, 354, 0, 0, - 0, 0, 0, 0, 0, 0, 54, 0, 576, 320, - 341, 340, 343, 344, 345, 346, 0, 0, 101, 342, - 347, 348, 349, 0, 0, 0, 317, 334, 0, 361, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 331, - 332, 0, 0, 0, 0, 375, 0, 333, 0, 0, - 328, 329, 330, 335, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 119, 0, 0, 0, 265, 0, 0, - 373, 0, 184, 0, 215, 122, 136, 97, 83, 93, - 0, 121, 162, 191, 195, 0, 0, 0, 105, 0, - 193, 172, 231, 0, 174, 192, 140, 221, 185, 230, - 240, 241, 218, 238, 245, 208, 86, 217, 229, 102, - 203, 88, 227, 214, 151, 131, 132, 87, 0, 189, - 110, 117, 107, 164, 224, 225, 106, 248, 94, 237, - 90, 95, 236, 158, 220, 228, 152, 145, 89, 226, - 150, 144, 135, 114, 124, 182, 142, 183, 125, 155, - 154, 156, 0, 0, 0, 212, 234, 249, 99, 0, - 219, 243, 244, 0, 0, 100, 118, 113, 181, 157, - 96, 127, 209, 134, 141, 188, 247, 171, 194, 103, - 233, 210, 363, 374, 369, 370, 367, 368, 366, 365, - 364, 376, 355, 356, 357, 358, 360, 0, 371, 372, - 359, 82, 91, 138, 246, 186, 116, 235, 0, 0, - 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 223, 232, 239, 242, 165, 0, 0, 0, 0, 324, + 0, 0, 0, 111, 0, 321, 0, 0, 0, 137, + 0, 364, 139, 0, 0, 211, 153, 0, 0, 0, + 0, 355, 356, 0, 0, 0, 0, 0, 0, 0, + 0, 54, 0, 0, 322, 343, 342, 345, 346, 347, + 348, 0, 0, 101, 344, 349, 350, 351, 0, 0, + 0, 319, 336, 0, 363, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 333, 334, 0, 0, 0, 0, + 378, 0, 335, 0, 0, 330, 331, 332, 337, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 119, 377, + 0, 0, 267, 0, 0, 375, 0, 184, 0, 215, + 122, 136, 97, 83, 93, 0, 121, 162, 191, 195, + 0, 0, 0, 105, 0, 193, 172, 231, 0, 174, + 192, 140, 221, 185, 230, 240, 241, 218, 238, 245, + 208, 86, 217, 229, 102, 203, 88, 227, 214, 151, + 131, 132, 87, 0, 189, 110, 117, 107, 164, 224, + 225, 106, 248, 94, 237, 90, 95, 236, 158, 220, + 228, 152, 145, 89, 226, 150, 144, 135, 114, 124, + 182, 142, 183, 125, 155, 154, 156, 0, 0, 0, + 212, 234, 249, 99, 0, 219, 243, 244, 0, 0, + 100, 118, 113, 181, 157, 96, 127, 209, 134, 141, + 188, 247, 171, 194, 103, 233, 210, 365, 376, 371, + 372, 369, 370, 368, 367, 366, 379, 357, 358, 359, + 360, 362, 0, 373, 374, 361, 82, 91, 138, 246, + 186, 116, 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 84, 85, 92, 98, 104, 108, 112, - 115, 120, 123, 126, 128, 129, 130, 133, 143, 146, - 147, 148, 149, 159, 160, 161, 163, 166, 167, 168, - 169, 170, 173, 175, 176, 177, 178, 179, 180, 187, - 190, 196, 197, 198, 199, 200, 201, 202, 204, 205, - 206, 207, 213, 216, 222, 223, 232, 239, 242, 165, - 0, 0, 0, 0, 322, 0, 0, 0, 111, 0, - 319, 0, 0, 0, 137, 362, 139, 0, 0, 211, - 153, 0, 0, 0, 0, 353, 354, 0, 0, 0, - 0, 0, 0, 0, 0, 54, 0, 0, 320, 341, - 340, 343, 344, 345, 346, 0, 0, 101, 342, 347, - 348, 349, 0, 0, 0, 317, 334, 0, 361, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 331, 332, - 313, 0, 0, 0, 375, 0, 333, 0, 0, 328, - 329, 330, 335, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 119, 0, 0, 0, 265, 0, 0, 373, - 0, 184, 0, 215, 122, 136, 97, 83, 93, 0, - 121, 162, 191, 195, 0, 0, 0, 105, 0, 193, - 172, 231, 0, 174, 192, 140, 221, 185, 230, 240, - 241, 218, 238, 245, 208, 86, 217, 229, 102, 203, - 88, 227, 214, 151, 131, 132, 87, 0, 189, 110, - 117, 107, 164, 224, 225, 106, 248, 94, 237, 90, - 95, 236, 158, 220, 228, 152, 145, 89, 226, 150, - 144, 135, 114, 124, 182, 142, 183, 125, 155, 154, - 156, 0, 0, 0, 212, 234, 249, 99, 0, 219, - 243, 244, 0, 0, 100, 118, 113, 181, 157, 96, - 127, 209, 134, 141, 188, 247, 171, 194, 103, 233, - 210, 363, 374, 369, 370, 367, 368, 366, 365, 364, - 376, 355, 356, 357, 358, 360, 0, 371, 372, 359, - 82, 91, 138, 246, 186, 116, 235, 0, 0, 109, + 0, 0, 0, 0, 0, 0, 0, 0, 84, 85, + 92, 98, 104, 108, 112, 115, 120, 123, 126, 128, + 129, 130, 133, 143, 146, 147, 148, 149, 159, 160, + 161, 163, 166, 167, 168, 169, 170, 173, 175, 176, + 177, 178, 179, 180, 187, 190, 196, 197, 198, 199, + 200, 201, 202, 204, 205, 206, 207, 213, 216, 222, + 223, 232, 239, 242, 165, 0, 0, 0, 0, 0, + 0, 0, 0, 111, 0, 0, 0, 0, 0, 137, + 0, 364, 139, 0, 0, 211, 153, 0, 0, 0, + 0, 355, 356, 0, 0, 0, 0, 0, 0, 0, + 0, 54, 0, 0, 322, 343, 342, 345, 346, 347, + 348, 0, 0, 101, 344, 349, 350, 351, 0, 0, + 0, 0, 336, 0, 363, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 333, 334, 0, 0, 0, 0, + 378, 0, 335, 0, 0, 330, 331, 332, 337, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 119, 377, + 0, 0, 267, 0, 0, 375, 0, 184, 0, 215, + 122, 136, 97, 83, 93, 0, 121, 162, 191, 195, + 0, 0, 0, 105, 0, 193, 172, 231, 1525, 174, + 192, 140, 221, 185, 230, 240, 241, 218, 238, 245, + 208, 86, 217, 229, 102, 203, 88, 227, 214, 151, + 131, 132, 87, 0, 189, 110, 117, 107, 164, 224, + 225, 106, 248, 94, 237, 90, 95, 236, 158, 220, + 228, 152, 145, 89, 226, 150, 144, 135, 114, 124, + 182, 142, 183, 125, 155, 154, 156, 0, 0, 0, + 212, 234, 249, 99, 0, 219, 243, 244, 0, 0, + 100, 118, 113, 181, 157, 96, 127, 209, 134, 141, + 188, 247, 171, 194, 103, 233, 210, 365, 376, 371, + 372, 369, 370, 368, 367, 366, 379, 357, 358, 359, + 360, 362, 0, 373, 374, 361, 82, 91, 138, 246, + 186, 116, 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 84, 85, + 92, 98, 104, 108, 112, 115, 120, 123, 126, 128, + 129, 130, 133, 143, 146, 147, 148, 149, 159, 160, + 161, 163, 166, 167, 168, 169, 170, 173, 175, 176, + 177, 178, 179, 180, 187, 190, 196, 197, 198, 199, + 200, 201, 202, 204, 205, 206, 207, 213, 216, 222, + 223, 232, 239, 242, 165, 0, 0, 0, 0, 0, + 0, 0, 0, 111, 0, 0, 0, 0, 0, 137, + 0, 364, 139, 0, 0, 211, 153, 0, 0, 0, + 0, 355, 356, 0, 0, 0, 0, 0, 0, 0, + 0, 54, 0, 584, 322, 343, 342, 345, 346, 347, + 348, 0, 0, 101, 344, 349, 350, 351, 0, 0, + 0, 0, 336, 0, 363, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 333, 334, 0, 0, 0, 0, + 378, 0, 335, 0, 0, 330, 331, 332, 337, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 119, 377, + 0, 0, 267, 0, 0, 375, 0, 184, 0, 215, + 122, 136, 97, 83, 93, 0, 121, 162, 191, 195, + 0, 0, 0, 105, 0, 193, 172, 231, 0, 174, + 192, 140, 221, 185, 230, 240, 241, 218, 238, 245, + 208, 86, 217, 229, 102, 203, 88, 227, 214, 151, + 131, 132, 87, 0, 189, 110, 117, 107, 164, 224, + 225, 106, 248, 94, 237, 90, 95, 236, 158, 220, + 228, 152, 145, 89, 226, 150, 144, 135, 114, 124, + 182, 142, 183, 125, 155, 154, 156, 0, 0, 0, + 212, 234, 249, 99, 0, 219, 243, 244, 0, 0, + 100, 118, 113, 181, 157, 96, 127, 209, 134, 141, + 188, 247, 171, 194, 103, 233, 210, 365, 376, 371, + 372, 369, 370, 368, 367, 366, 379, 357, 358, 359, + 360, 362, 0, 373, 374, 361, 82, 91, 138, 246, + 186, 116, 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 84, 85, 92, 98, 104, 108, 112, 115, - 120, 123, 126, 128, 129, 130, 133, 143, 146, 147, - 148, 149, 159, 160, 161, 163, 166, 167, 168, 169, - 170, 173, 175, 176, 177, 178, 179, 180, 187, 190, - 196, 197, 198, 199, 200, 201, 202, 204, 205, 206, - 207, 213, 216, 222, 223, 232, 239, 242, 165, 0, - 0, 0, 0, 322, 0, 0, 0, 111, 0, 319, - 0, 0, 0, 137, 362, 139, 0, 0, 211, 153, - 0, 0, 0, 0, 353, 354, 0, 0, 0, 0, - 0, 0, 0, 0, 54, 0, 0, 320, 341, 888, - 343, 344, 345, 346, 0, 0, 101, 342, 347, 348, - 349, 0, 0, 0, 317, 334, 0, 361, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 331, 332, 313, - 0, 0, 0, 375, 0, 333, 0, 0, 328, 329, - 330, 335, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 119, 0, 0, 0, 265, 0, 0, 373, 0, - 184, 0, 215, 122, 136, 97, 83, 93, 0, 121, - 162, 191, 195, 0, 0, 0, 105, 0, 193, 172, - 231, 0, 174, 192, 140, 221, 185, 230, 240, 241, - 218, 238, 245, 208, 86, 217, 229, 102, 203, 88, - 227, 214, 151, 131, 132, 87, 0, 189, 110, 117, - 107, 164, 224, 225, 106, 248, 94, 237, 90, 95, - 236, 158, 220, 228, 152, 145, 89, 226, 150, 144, - 135, 114, 124, 182, 142, 183, 125, 155, 154, 156, - 0, 0, 0, 212, 234, 249, 99, 0, 219, 243, - 244, 0, 0, 100, 118, 113, 181, 157, 96, 127, - 209, 134, 141, 188, 247, 171, 194, 103, 233, 210, - 363, 374, 369, 370, 367, 368, 366, 365, 364, 376, - 355, 356, 357, 358, 360, 0, 371, 372, 359, 82, - 91, 138, 246, 186, 116, 235, 0, 0, 109, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 84, 85, + 92, 98, 104, 108, 112, 115, 120, 123, 126, 128, + 129, 130, 133, 143, 146, 147, 148, 149, 159, 160, + 161, 163, 166, 167, 168, 169, 170, 173, 175, 176, + 177, 178, 179, 180, 187, 190, 196, 197, 198, 199, + 200, 201, 202, 204, 205, 206, 207, 213, 216, 222, + 223, 232, 239, 242, 165, 0, 0, 0, 0, 0, + 0, 0, 0, 111, 0, 0, 0, 0, 0, 137, + 0, 364, 139, 0, 0, 211, 153, 0, 0, 0, + 0, 355, 356, 0, 0, 0, 0, 0, 0, 0, + 0, 54, 0, 0, 322, 343, 342, 345, 346, 347, + 348, 0, 0, 101, 344, 349, 350, 351, 0, 0, + 0, 0, 336, 0, 363, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 333, 334, 0, 0, 0, 0, + 378, 0, 335, 0, 0, 330, 331, 332, 337, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 119, 377, + 0, 0, 267, 0, 0, 375, 0, 184, 0, 215, + 122, 136, 97, 83, 93, 0, 121, 162, 191, 195, + 0, 0, 0, 105, 0, 193, 172, 231, 0, 174, + 192, 140, 221, 185, 230, 240, 241, 218, 238, 245, + 208, 86, 217, 229, 102, 203, 88, 227, 214, 151, + 131, 132, 87, 0, 189, 110, 117, 107, 164, 224, + 225, 106, 248, 94, 237, 90, 95, 236, 158, 220, + 228, 152, 145, 89, 226, 150, 144, 135, 114, 124, + 182, 142, 183, 125, 155, 154, 156, 0, 0, 0, + 212, 234, 249, 99, 0, 219, 243, 244, 0, 0, + 100, 118, 113, 181, 157, 96, 127, 209, 134, 141, + 188, 247, 171, 194, 103, 233, 210, 365, 376, 371, + 372, 369, 370, 368, 367, 366, 379, 357, 358, 359, + 360, 362, 0, 373, 374, 361, 82, 91, 138, 246, + 186, 116, 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 84, 85, + 92, 98, 104, 108, 112, 115, 120, 123, 126, 128, + 129, 130, 133, 143, 146, 147, 148, 149, 159, 160, + 161, 163, 166, 167, 168, 169, 170, 173, 175, 176, + 177, 178, 179, 180, 187, 190, 196, 197, 198, 199, + 200, 201, 202, 204, 205, 206, 207, 213, 216, 222, + 223, 232, 239, 242, 165, 0, 0, 0, 0, 0, + 0, 0, 0, 111, 0, 0, 0, 0, 0, 137, + 0, 0, 139, 0, 0, 211, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 84, 85, 92, 98, 104, 108, 112, 115, 120, - 123, 126, 128, 129, 130, 133, 143, 146, 147, 148, - 149, 159, 160, 161, 163, 166, 167, 168, 169, 170, - 173, 175, 176, 177, 178, 179, 180, 187, 190, 196, - 197, 198, 199, 200, 201, 202, 204, 205, 206, 207, - 213, 216, 222, 223, 232, 239, 242, 165, 0, 0, - 0, 0, 322, 0, 0, 0, 111, 0, 319, 0, - 0, 0, 137, 362, 139, 0, 0, 211, 153, 0, - 0, 0, 0, 353, 354, 0, 0, 0, 0, 0, - 0, 0, 0, 54, 0, 0, 320, 341, 885, 343, - 344, 345, 346, 0, 0, 101, 342, 347, 348, 349, - 0, 0, 0, 317, 334, 0, 361, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 331, 332, 313, 0, - 0, 0, 375, 0, 333, 0, 0, 328, 329, 330, - 335, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 119, 0, 0, 0, 265, 0, 0, 373, 0, 184, - 0, 215, 122, 136, 97, 83, 93, 0, 121, 162, - 191, 195, 0, 0, 0, 105, 0, 193, 172, 231, - 0, 174, 192, 140, 221, 185, 230, 240, 241, 218, - 238, 245, 208, 86, 217, 229, 102, 203, 88, 227, - 214, 151, 131, 132, 87, 0, 189, 110, 117, 107, - 164, 224, 225, 106, 248, 94, 237, 90, 95, 236, - 158, 220, 228, 152, 145, 89, 226, 150, 144, 135, - 114, 124, 182, 142, 183, 125, 155, 154, 156, 0, - 0, 0, 212, 234, 249, 99, 0, 219, 243, 244, - 0, 0, 100, 118, 113, 181, 157, 96, 127, 209, - 134, 141, 188, 247, 171, 194, 103, 233, 210, 363, - 374, 369, 370, 367, 368, 366, 365, 364, 376, 355, - 356, 357, 358, 360, 0, 371, 372, 359, 82, 91, - 138, 246, 186, 116, 235, 0, 0, 109, 0, 0, + 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, + 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 84, 85, 92, 98, 104, 108, 112, 115, 120, 123, - 126, 128, 129, 130, 133, 143, 146, 147, 148, 149, - 159, 160, 161, 163, 166, 167, 168, 169, 170, 173, - 175, 176, 177, 178, 179, 180, 187, 190, 196, 197, - 198, 199, 200, 201, 202, 204, 205, 206, 207, 213, - 216, 222, 223, 232, 239, 242, 24, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 165, 0, - 0, 0, 0, 322, 0, 0, 0, 111, 0, 319, - 0, 0, 0, 137, 362, 139, 0, 0, 211, 153, - 0, 0, 0, 0, 353, 354, 0, 0, 0, 0, - 0, 0, 0, 0, 54, 0, 0, 320, 341, 340, - 343, 344, 345, 346, 0, 0, 101, 342, 347, 348, - 349, 0, 0, 0, 317, 334, 0, 361, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 331, 332, 0, - 0, 0, 0, 375, 0, 333, 0, 0, 328, 329, - 330, 335, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 119, 0, 0, 0, 265, 0, 0, 373, 0, - 184, 0, 215, 122, 136, 97, 83, 93, 0, 121, - 162, 191, 195, 0, 0, 0, 105, 0, 193, 172, - 231, 0, 174, 192, 140, 221, 185, 230, 240, 241, - 218, 238, 245, 208, 86, 217, 229, 102, 203, 88, - 227, 214, 151, 131, 132, 87, 0, 189, 110, 117, - 107, 164, 224, 225, 106, 248, 94, 237, 90, 95, - 236, 158, 220, 228, 152, 145, 89, 226, 150, 144, - 135, 114, 124, 182, 142, 183, 125, 155, 154, 156, - 0, 0, 0, 212, 234, 249, 99, 0, 219, 243, - 244, 0, 0, 100, 118, 113, 181, 157, 96, 127, - 209, 134, 141, 188, 247, 171, 194, 103, 233, 210, - 363, 374, 369, 370, 367, 368, 366, 365, 364, 376, - 355, 356, 357, 358, 360, 0, 371, 372, 359, 82, - 91, 138, 246, 186, 116, 235, 0, 0, 109, 0, + 619, 618, 628, 629, 621, 622, 623, 624, 625, 626, + 627, 620, 0, 0, 630, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 119, 0, + 0, 0, 267, 0, 0, 0, 0, 184, 0, 215, + 122, 136, 97, 83, 93, 0, 121, 162, 191, 195, + 0, 0, 0, 105, 0, 193, 172, 231, 0, 174, + 192, 140, 221, 185, 230, 240, 241, 218, 238, 245, + 208, 86, 217, 229, 102, 203, 88, 227, 214, 151, + 131, 132, 87, 0, 189, 110, 117, 107, 164, 224, + 225, 106, 248, 94, 237, 90, 95, 236, 158, 220, + 228, 152, 145, 89, 226, 150, 144, 135, 114, 124, + 182, 142, 183, 125, 155, 154, 156, 0, 0, 0, + 212, 234, 249, 99, 0, 219, 243, 244, 0, 0, + 100, 118, 113, 181, 157, 96, 127, 209, 134, 141, + 188, 247, 171, 194, 103, 233, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 82, 91, 138, 246, + 186, 116, 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 84, 85, 92, 98, 104, 108, 112, 115, 120, - 123, 126, 128, 129, 130, 133, 143, 146, 147, 148, - 149, 159, 160, 161, 163, 166, 167, 168, 169, 170, - 173, 175, 176, 177, 178, 179, 180, 187, 190, 196, - 197, 198, 199, 200, 201, 202, 204, 205, 206, 207, - 213, 216, 222, 223, 232, 239, 242, 165, 0, 0, - 0, 0, 322, 0, 0, 0, 111, 0, 319, 0, - 0, 0, 137, 362, 139, 0, 0, 211, 153, 0, - 0, 0, 0, 353, 354, 0, 0, 0, 0, 0, - 0, 0, 0, 54, 0, 0, 320, 341, 340, 343, - 344, 345, 346, 0, 0, 101, 342, 347, 348, 349, - 0, 0, 0, 317, 334, 0, 361, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 331, 332, 0, 0, - 0, 0, 375, 0, 333, 0, 0, 328, 329, 330, - 335, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 119, 0, 0, 0, 265, 0, 0, 373, 0, 184, - 0, 215, 122, 136, 97, 83, 93, 0, 121, 162, - 191, 195, 0, 0, 0, 105, 0, 193, 172, 231, - 0, 174, 192, 140, 221, 185, 230, 240, 241, 218, - 238, 245, 208, 86, 217, 229, 102, 203, 88, 227, - 214, 151, 131, 132, 87, 0, 189, 110, 117, 107, - 164, 224, 225, 106, 248, 94, 237, 90, 95, 236, - 158, 220, 228, 152, 145, 89, 226, 150, 144, 135, - 114, 124, 182, 142, 183, 125, 155, 154, 156, 0, - 0, 0, 212, 234, 249, 99, 0, 219, 243, 244, - 0, 0, 100, 118, 113, 181, 157, 96, 127, 209, - 134, 141, 188, 247, 171, 194, 103, 233, 210, 363, - 374, 369, 370, 367, 368, 366, 365, 364, 376, 355, - 356, 357, 358, 360, 0, 371, 372, 359, 82, 91, - 138, 246, 186, 116, 235, 0, 0, 109, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 84, 85, + 92, 98, 104, 108, 112, 115, 120, 123, 126, 128, + 129, 130, 133, 143, 146, 147, 148, 149, 159, 160, + 161, 163, 166, 167, 168, 169, 170, 173, 175, 176, + 177, 178, 179, 180, 187, 190, 196, 197, 198, 199, + 200, 201, 202, 204, 205, 206, 207, 213, 216, 222, + 223, 232, 239, 242, 165, 0, 0, 0, 607, 0, + 0, 0, 0, 111, 0, 0, 0, 0, 0, 137, + 0, 0, 139, 0, 0, 211, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 80, 0, 609, 0, 0, 0, + 0, 0, 0, 101, 0, 0, 0, 0, 0, 604, + 603, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 605, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 84, 85, 92, 98, 104, 108, 112, 115, 120, 123, - 126, 128, 129, 130, 133, 143, 146, 147, 148, 149, - 159, 160, 161, 163, 166, 167, 168, 169, 170, 173, - 175, 176, 177, 178, 179, 180, 187, 190, 196, 197, - 198, 199, 200, 201, 202, 204, 205, 206, 207, 213, - 216, 222, 223, 232, 239, 242, 165, 0, 0, 0, - 0, 0, 0, 0, 0, 111, 0, 0, 0, 0, - 0, 137, 362, 139, 0, 0, 211, 153, 0, 0, - 0, 0, 353, 354, 0, 0, 0, 0, 0, 0, - 0, 0, 54, 0, 0, 320, 341, 340, 343, 344, - 345, 346, 0, 0, 101, 342, 347, 348, 349, 0, - 0, 0, 0, 334, 0, 361, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 331, 332, 0, 0, 0, - 0, 375, 0, 333, 0, 0, 328, 329, 330, 335, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, - 0, 0, 0, 265, 0, 0, 373, 0, 184, 0, - 215, 122, 136, 97, 83, 93, 0, 121, 162, 191, - 195, 0, 0, 0, 105, 0, 193, 172, 231, 1508, - 174, 192, 140, 221, 185, 230, 240, 241, 218, 238, - 245, 208, 86, 217, 229, 102, 203, 88, 227, 214, - 151, 131, 132, 87, 0, 189, 110, 117, 107, 164, - 224, 225, 106, 248, 94, 237, 90, 95, 236, 158, - 220, 228, 152, 145, 89, 226, 150, 144, 135, 114, - 124, 182, 142, 183, 125, 155, 154, 156, 0, 0, - 0, 212, 234, 249, 99, 0, 219, 243, 244, 0, - 0, 100, 118, 113, 181, 157, 96, 127, 209, 134, - 141, 188, 247, 171, 194, 103, 233, 210, 363, 374, - 369, 370, 367, 368, 366, 365, 364, 376, 355, 356, - 357, 358, 360, 0, 371, 372, 359, 82, 91, 138, - 246, 186, 116, 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, - 85, 92, 98, 104, 108, 112, 115, 120, 123, 126, - 128, 129, 130, 133, 143, 146, 147, 148, 149, 159, - 160, 161, 163, 166, 167, 168, 169, 170, 173, 175, - 176, 177, 178, 179, 180, 187, 190, 196, 197, 198, - 199, 200, 201, 202, 204, 205, 206, 207, 213, 216, - 222, 223, 232, 239, 242, 165, 0, 0, 0, 0, - 0, 0, 0, 0, 111, 0, 0, 0, 0, 0, - 137, 362, 139, 0, 0, 211, 153, 0, 0, 0, - 0, 353, 354, 0, 0, 0, 0, 0, 0, 0, - 0, 54, 0, 576, 320, 341, 340, 343, 344, 345, - 346, 0, 0, 101, 342, 347, 348, 349, 0, 0, - 0, 0, 334, 0, 361, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 331, 332, 0, 0, 0, 0, - 375, 0, 333, 0, 0, 328, 329, 330, 335, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 0, - 0, 0, 265, 0, 0, 373, 0, 184, 0, 215, + 0, 0, 267, 0, 0, 0, 0, 184, 0, 215, 122, 136, 97, 83, 93, 0, 121, 162, 191, 195, 0, 0, 0, 105, 0, 193, 172, 231, 0, 174, 192, 140, 221, 185, 230, 240, 241, 218, 238, 245, @@ -1893,9 +1999,9 @@ var yyAct = [...]int{ 182, 142, 183, 125, 155, 154, 156, 0, 0, 0, 212, 234, 249, 99, 0, 219, 243, 244, 0, 0, 100, 118, 113, 181, 157, 96, 127, 209, 134, 141, - 188, 247, 171, 194, 103, 233, 210, 363, 374, 369, - 370, 367, 368, 366, 365, 364, 376, 355, 356, 357, - 358, 360, 0, 371, 372, 359, 82, 91, 138, 246, + 188, 247, 171, 194, 103, 233, 210, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 82, 91, 138, 246, 186, 116, 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 85, @@ -1906,314 +2012,315 @@ var yyAct = [...]int{ 200, 201, 202, 204, 205, 206, 207, 213, 216, 222, 223, 232, 239, 242, 165, 0, 0, 0, 0, 0, 0, 0, 0, 111, 0, 0, 0, 0, 0, 137, - 362, 139, 0, 0, 211, 153, 0, 0, 0, 0, - 353, 354, 0, 0, 0, 0, 0, 0, 0, 0, - 54, 0, 0, 320, 341, 340, 343, 344, 345, 346, - 0, 0, 101, 342, 347, 348, 349, 0, 0, 0, - 0, 334, 0, 361, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 331, 332, 0, 0, 0, 0, 375, - 0, 333, 0, 0, 328, 329, 330, 335, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 119, 0, 0, - 0, 265, 0, 0, 373, 0, 184, 0, 215, 122, - 136, 97, 83, 93, 0, 121, 162, 191, 195, 0, - 0, 0, 105, 0, 193, 172, 231, 0, 174, 192, - 140, 221, 185, 230, 240, 241, 218, 238, 245, 208, - 86, 217, 229, 102, 203, 88, 227, 214, 151, 131, - 132, 87, 0, 189, 110, 117, 107, 164, 224, 225, - 106, 248, 94, 237, 90, 95, 236, 158, 220, 228, - 152, 145, 89, 226, 150, 144, 135, 114, 124, 182, - 142, 183, 125, 155, 154, 156, 0, 0, 0, 212, - 234, 249, 99, 0, 219, 243, 244, 0, 0, 100, - 118, 113, 181, 157, 96, 127, 209, 134, 141, 188, - 247, 171, 194, 103, 233, 210, 363, 374, 369, 370, - 367, 368, 366, 365, 364, 376, 355, 356, 357, 358, - 360, 0, 371, 372, 359, 82, 91, 138, 246, 186, - 116, 235, 0, 0, 109, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 84, 85, 92, - 98, 104, 108, 112, 115, 120, 123, 126, 128, 129, - 130, 133, 143, 146, 147, 148, 149, 159, 160, 161, - 163, 166, 167, 168, 169, 170, 173, 175, 176, 177, - 178, 179, 180, 187, 190, 196, 197, 198, 199, 200, - 201, 202, 204, 205, 206, 207, 213, 216, 222, 223, - 232, 239, 242, 165, 0, 0, 0, 0, 0, 0, - 0, 0, 111, 0, 0, 0, 0, 0, 137, 0, - 139, 0, 0, 211, 153, 0, 0, 0, 0, 0, + 0, 0, 139, 0, 0, 211, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, - 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, + 0, 0, 0, 101, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 610, 609, - 619, 620, 612, 613, 614, 615, 616, 617, 618, 611, - 0, 0, 621, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 119, 0, 0, 0, - 265, 0, 0, 0, 0, 184, 0, 215, 122, 136, - 97, 83, 93, 0, 121, 162, 191, 195, 0, 0, - 0, 105, 0, 193, 172, 231, 0, 174, 192, 140, - 221, 185, 230, 240, 241, 218, 238, 245, 208, 86, - 217, 229, 102, 203, 88, 227, 214, 151, 131, 132, - 87, 0, 189, 110, 117, 107, 164, 224, 225, 106, - 248, 94, 237, 90, 95, 236, 158, 220, 228, 152, - 145, 89, 226, 150, 144, 135, 114, 124, 182, 142, - 183, 125, 155, 154, 156, 0, 0, 0, 212, 234, - 249, 99, 0, 219, 243, 244, 0, 0, 100, 118, - 113, 181, 157, 96, 127, 209, 134, 141, 188, 247, - 171, 194, 103, 233, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 82, 91, 138, 246, 186, 116, - 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 84, 85, 92, 98, - 104, 108, 112, 115, 120, 123, 126, 128, 129, 130, - 133, 143, 146, 147, 148, 149, 159, 160, 161, 163, - 166, 167, 168, 169, 170, 173, 175, 176, 177, 178, - 179, 180, 187, 190, 196, 197, 198, 199, 200, 201, - 202, 204, 205, 206, 207, 213, 216, 222, 223, 232, - 239, 242, 165, 0, 0, 0, 598, 0, 0, 0, - 0, 111, 0, 0, 0, 0, 0, 137, 0, 139, - 0, 0, 211, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 80, 0, 600, 0, 0, 0, 0, 0, 0, - 101, 0, 0, 0, 0, 0, 595, 594, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 119, 76, + 77, 0, 73, 0, 0, 0, 78, 184, 0, 215, + 122, 136, 97, 83, 93, 0, 121, 162, 191, 195, + 0, 0, 0, 105, 0, 193, 172, 231, 0, 174, + 192, 140, 221, 185, 230, 240, 241, 218, 238, 245, + 208, 86, 217, 229, 102, 203, 88, 227, 214, 151, + 131, 132, 87, 0, 189, 110, 117, 107, 164, 224, + 225, 106, 248, 94, 237, 90, 95, 236, 158, 220, + 228, 152, 145, 89, 226, 150, 144, 135, 114, 124, + 182, 142, 183, 125, 155, 154, 156, 0, 0, 0, + 212, 234, 249, 99, 0, 219, 243, 244, 0, 0, + 100, 118, 113, 181, 157, 96, 127, 209, 134, 141, + 188, 247, 171, 194, 103, 233, 210, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 596, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 82, 91, 138, 246, + 186, 116, 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 84, 85, + 92, 98, 104, 108, 112, 115, 120, 123, 126, 128, + 129, 130, 133, 143, 146, 147, 148, 149, 159, 160, + 161, 163, 166, 167, 168, 169, 170, 173, 175, 176, + 177, 178, 179, 180, 187, 190, 196, 197, 198, 199, + 200, 201, 202, 204, 205, 206, 207, 213, 216, 222, + 223, 232, 239, 242, 165, 0, 0, 0, 945, 0, + 0, 0, 0, 111, 0, 0, 0, 0, 0, 137, + 0, 0, 139, 0, 0, 211, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 119, 0, 0, 0, 265, - 0, 0, 0, 0, 184, 0, 215, 122, 136, 97, - 83, 93, 0, 121, 162, 191, 195, 0, 0, 0, - 105, 0, 193, 172, 231, 0, 174, 192, 140, 221, - 185, 230, 240, 241, 218, 238, 245, 208, 86, 217, - 229, 102, 203, 88, 227, 214, 151, 131, 132, 87, - 0, 189, 110, 117, 107, 164, 224, 225, 106, 248, - 94, 237, 90, 95, 236, 158, 220, 228, 152, 145, - 89, 226, 150, 144, 135, 114, 124, 182, 142, 183, - 125, 155, 154, 156, 0, 0, 0, 212, 234, 249, - 99, 0, 219, 243, 244, 0, 0, 100, 118, 113, - 181, 157, 96, 127, 209, 134, 141, 188, 247, 171, - 194, 103, 233, 210, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 265, 0, 947, 0, 0, 0, + 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 82, 91, 138, 246, 186, 116, 235, - 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 84, 85, 92, 98, 104, - 108, 112, 115, 120, 123, 126, 128, 129, 130, 133, - 143, 146, 147, 148, 149, 159, 160, 161, 163, 166, - 167, 168, 169, 170, 173, 175, 176, 177, 178, 179, - 180, 187, 190, 196, 197, 198, 199, 200, 201, 202, - 204, 205, 206, 207, 213, 216, 222, 223, 232, 239, - 242, 165, 0, 0, 0, 0, 0, 0, 0, 0, - 111, 0, 0, 0, 0, 0, 137, 0, 139, 0, - 0, 211, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 80, 0, 0, 0, 0, 0, 0, 0, 0, 101, - 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 119, 0, + 0, 0, 267, 0, 0, 0, 0, 184, 0, 215, + 122, 136, 97, 83, 93, 0, 121, 162, 191, 195, + 0, 0, 0, 105, 0, 193, 172, 231, 0, 174, + 192, 140, 221, 185, 230, 240, 241, 218, 238, 245, + 208, 86, 217, 229, 102, 203, 88, 227, 214, 151, + 131, 132, 87, 0, 189, 110, 117, 107, 164, 224, + 225, 106, 248, 94, 237, 90, 95, 236, 158, 220, + 228, 152, 145, 89, 226, 150, 144, 135, 114, 124, + 182, 142, 183, 125, 155, 154, 156, 0, 0, 0, + 212, 234, 249, 99, 0, 219, 243, 244, 0, 0, + 100, 118, 113, 181, 157, 96, 127, 209, 134, 141, + 188, 247, 171, 194, 103, 233, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 82, 91, 138, 246, + 186, 116, 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 84, 85, + 92, 98, 104, 108, 112, 115, 120, 123, 126, 128, + 129, 130, 133, 143, 146, 147, 148, 149, 159, 160, + 161, 163, 166, 167, 168, 169, 170, 173, 175, 176, + 177, 178, 179, 180, 187, 190, 196, 197, 198, 199, + 200, 201, 202, 204, 205, 206, 207, 213, 216, 222, + 223, 232, 239, 242, 24, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 165, 0, 0, 0, + 0, 0, 0, 0, 0, 111, 0, 0, 0, 0, + 0, 137, 0, 0, 139, 0, 0, 211, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 119, 76, 77, 0, 73, 0, - 0, 0, 78, 184, 0, 215, 122, 136, 97, 83, - 93, 0, 121, 162, 191, 195, 0, 0, 0, 105, - 0, 193, 172, 231, 0, 174, 192, 140, 221, 185, - 230, 240, 241, 218, 238, 245, 208, 86, 217, 229, - 102, 203, 88, 227, 214, 151, 131, 132, 87, 0, - 189, 110, 117, 107, 164, 224, 225, 106, 248, 94, - 237, 90, 95, 236, 158, 220, 228, 152, 145, 89, - 226, 150, 144, 135, 114, 124, 182, 142, 183, 125, - 155, 154, 156, 0, 0, 0, 212, 234, 249, 99, - 0, 219, 243, 244, 0, 0, 100, 118, 113, 181, - 157, 96, 127, 209, 134, 141, 188, 247, 171, 194, - 103, 233, 210, 0, 75, 0, 0, 0, 0, 0, + 0, 0, 0, 54, 0, 0, 80, 0, 0, 0, + 0, 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 82, 91, 138, 246, 186, 116, 235, 0, - 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 84, 85, 92, 98, 104, 108, - 112, 115, 120, 123, 126, 128, 129, 130, 133, 143, - 146, 147, 148, 149, 159, 160, 161, 163, 166, 167, - 168, 169, 170, 173, 175, 176, 177, 178, 179, 180, - 187, 190, 196, 197, 198, 199, 200, 201, 202, 204, - 205, 206, 207, 213, 216, 222, 223, 232, 239, 242, - 165, 0, 0, 0, 929, 0, 0, 0, 0, 111, - 0, 0, 0, 0, 0, 137, 0, 139, 0, 0, - 211, 153, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 263, - 0, 931, 0, 0, 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 119, 0, 0, 0, 267, 0, 0, 0, 0, 184, + 0, 215, 122, 136, 97, 83, 93, 0, 121, 162, + 191, 195, 0, 0, 0, 105, 0, 193, 172, 231, + 0, 174, 192, 140, 221, 185, 230, 240, 241, 218, + 238, 245, 208, 86, 217, 229, 102, 203, 88, 227, + 214, 151, 131, 132, 87, 0, 189, 110, 117, 107, + 164, 224, 225, 106, 248, 94, 237, 90, 95, 236, + 158, 220, 228, 152, 145, 89, 226, 150, 144, 135, + 114, 124, 182, 142, 183, 125, 155, 154, 156, 0, + 0, 0, 212, 234, 249, 99, 0, 219, 243, 244, + 0, 0, 100, 118, 113, 181, 157, 96, 127, 209, + 134, 141, 188, 247, 171, 194, 103, 233, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 82, 91, + 138, 246, 186, 116, 235, 0, 0, 109, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 84, 85, 92, 98, 104, 108, 112, 115, 120, 123, + 126, 128, 129, 130, 133, 143, 146, 147, 148, 149, + 159, 160, 161, 163, 166, 167, 168, 169, 170, 173, + 175, 176, 177, 178, 179, 180, 187, 190, 196, 197, + 198, 199, 200, 201, 202, 204, 205, 206, 207, 213, + 216, 222, 223, 232, 239, 242, 24, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 165, 0, + 0, 0, 0, 0, 0, 0, 0, 111, 0, 0, + 0, 0, 0, 137, 0, 0, 139, 0, 0, 211, + 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 54, 0, 0, 265, 0, + 0, 0, 0, 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 119, 0, 0, 0, 265, 0, 0, - 0, 0, 184, 0, 215, 122, 136, 97, 83, 93, - 0, 121, 162, 191, 195, 0, 0, 0, 105, 0, - 193, 172, 231, 0, 174, 192, 140, 221, 185, 230, - 240, 241, 218, 238, 245, 208, 86, 217, 229, 102, - 203, 88, 227, 214, 151, 131, 132, 87, 0, 189, - 110, 117, 107, 164, 224, 225, 106, 248, 94, 237, - 90, 95, 236, 158, 220, 228, 152, 145, 89, 226, - 150, 144, 135, 114, 124, 182, 142, 183, 125, 155, - 154, 156, 0, 0, 0, 212, 234, 249, 99, 0, - 219, 243, 244, 0, 0, 100, 118, 113, 181, 157, - 96, 127, 209, 134, 141, 188, 247, 171, 194, 103, - 233, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 82, 91, 138, 246, 186, 116, 235, 0, 0, - 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 84, 85, 92, 98, 104, 108, 112, - 115, 120, 123, 126, 128, 129, 130, 133, 143, 146, - 147, 148, 149, 159, 160, 161, 163, 166, 167, 168, - 169, 170, 173, 175, 176, 177, 178, 179, 180, 187, - 190, 196, 197, 198, 199, 200, 201, 202, 204, 205, - 206, 207, 213, 216, 222, 223, 232, 239, 242, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 165, 0, 0, 0, 0, 0, 0, 0, 0, - 111, 0, 0, 0, 0, 0, 137, 0, 139, 0, - 0, 211, 153, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, - 80, 0, 0, 0, 0, 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 119, 0, 0, 0, 267, 0, 0, 0, + 0, 184, 0, 215, 122, 136, 97, 83, 93, 0, + 121, 162, 191, 195, 0, 0, 0, 105, 0, 193, + 172, 231, 0, 174, 192, 140, 221, 185, 230, 240, + 241, 218, 238, 245, 208, 86, 217, 229, 102, 203, + 88, 227, 214, 151, 131, 132, 87, 0, 189, 110, + 117, 107, 164, 224, 225, 106, 248, 94, 237, 90, + 95, 236, 158, 220, 228, 152, 145, 89, 226, 150, + 144, 135, 114, 124, 182, 142, 183, 125, 155, 154, + 156, 0, 0, 0, 212, 234, 249, 99, 0, 219, + 243, 244, 0, 0, 100, 118, 113, 181, 157, 96, + 127, 209, 134, 141, 188, 247, 171, 194, 103, 233, + 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 82, 91, 138, 246, 186, 116, 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 84, 85, 92, 98, 104, 108, 112, 115, + 120, 123, 126, 128, 129, 130, 133, 143, 146, 147, + 148, 149, 159, 160, 161, 163, 166, 167, 168, 169, + 170, 173, 175, 176, 177, 178, 179, 180, 187, 190, + 196, 197, 198, 199, 200, 201, 202, 204, 205, 206, + 207, 213, 216, 222, 223, 232, 239, 242, 165, 0, + 0, 0, 945, 0, 0, 0, 0, 111, 0, 0, + 0, 0, 0, 137, 0, 0, 139, 0, 0, 211, + 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 265, 0, + 947, 0, 0, 0, 0, 0, 0, 101, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 119, 0, 0, 0, 267, 0, 0, 0, + 0, 184, 0, 215, 122, 136, 97, 83, 93, 0, + 121, 162, 191, 195, 0, 0, 0, 105, 0, 193, + 172, 231, 0, 943, 192, 140, 221, 185, 230, 240, + 241, 218, 238, 245, 208, 86, 217, 229, 102, 203, + 88, 227, 214, 151, 131, 132, 87, 0, 189, 110, + 117, 107, 164, 224, 225, 106, 248, 94, 237, 90, + 95, 236, 158, 220, 228, 152, 145, 89, 226, 150, + 144, 135, 114, 124, 182, 142, 183, 125, 155, 154, + 156, 0, 0, 0, 212, 234, 249, 99, 0, 219, + 243, 244, 0, 0, 100, 118, 113, 181, 157, 96, + 127, 209, 134, 141, 188, 247, 171, 194, 103, 233, + 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 82, 91, 138, 246, 186, 116, 235, 0, 0, 109, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 84, 85, 92, 98, 104, 108, 112, 115, + 120, 123, 126, 128, 129, 130, 133, 143, 146, 147, + 148, 149, 159, 160, 161, 163, 166, 167, 168, 169, + 170, 173, 175, 176, 177, 178, 179, 180, 187, 190, + 196, 197, 198, 199, 200, 201, 202, 204, 205, 206, + 207, 213, 216, 222, 223, 232, 239, 242, 165, 0, + 0, 0, 0, 0, 0, 0, 0, 111, 0, 0, + 0, 0, 0, 137, 0, 0, 139, 0, 0, 211, + 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 80, 0, + 0, 838, 0, 0, 839, 0, 0, 101, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 119, 0, 0, 0, 267, 0, 0, 0, + 0, 184, 0, 215, 122, 136, 97, 83, 93, 0, + 121, 162, 191, 195, 0, 0, 0, 105, 0, 193, + 172, 231, 0, 174, 192, 140, 221, 185, 230, 240, + 241, 218, 238, 245, 208, 86, 217, 229, 102, 203, + 88, 227, 214, 151, 131, 132, 87, 0, 189, 110, + 117, 107, 164, 224, 225, 106, 248, 94, 237, 90, + 95, 236, 158, 220, 228, 152, 145, 89, 226, 150, + 144, 135, 114, 124, 182, 142, 183, 125, 155, 154, + 156, 0, 0, 0, 212, 234, 249, 99, 0, 219, + 243, 244, 0, 0, 100, 118, 113, 181, 157, 96, + 127, 209, 134, 141, 188, 247, 171, 194, 103, 233, + 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 82, 91, 138, 246, 186, 116, 235, 0, 0, 109, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 84, 85, 92, 98, 104, 108, 112, 115, + 120, 123, 126, 128, 129, 130, 133, 143, 146, 147, + 148, 149, 159, 160, 161, 163, 166, 167, 168, 169, + 170, 173, 175, 176, 177, 178, 179, 180, 187, 190, + 196, 197, 198, 199, 200, 201, 202, 204, 205, 206, + 207, 213, 216, 222, 223, 232, 239, 242, 165, 0, + 0, 0, 0, 0, 0, 0, 0, 111, 0, 722, + 0, 0, 0, 137, 0, 0, 139, 0, 0, 211, + 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 80, 0, + 721, 0, 0, 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 119, 0, 0, 0, 265, 0, - 0, 0, 0, 184, 0, 215, 122, 136, 97, 83, - 93, 0, 121, 162, 191, 195, 0, 0, 0, 105, - 0, 193, 172, 231, 0, 174, 192, 140, 221, 185, - 230, 240, 241, 218, 238, 245, 208, 86, 217, 229, - 102, 203, 88, 227, 214, 151, 131, 132, 87, 0, - 189, 110, 117, 107, 164, 224, 225, 106, 248, 94, - 237, 90, 95, 236, 158, 220, 228, 152, 145, 89, - 226, 150, 144, 135, 114, 124, 182, 142, 183, 125, - 155, 154, 156, 0, 0, 0, 212, 234, 249, 99, - 0, 219, 243, 244, 0, 0, 100, 118, 113, 181, - 157, 96, 127, 209, 134, 141, 188, 247, 171, 194, - 103, 233, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 82, 91, 138, 246, 186, 116, 235, 0, - 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 84, 85, 92, 98, 104, 108, - 112, 115, 120, 123, 126, 128, 129, 130, 133, 143, - 146, 147, 148, 149, 159, 160, 161, 163, 166, 167, - 168, 169, 170, 173, 175, 176, 177, 178, 179, 180, - 187, 190, 196, 197, 198, 199, 200, 201, 202, 204, - 205, 206, 207, 213, 216, 222, 223, 232, 239, 242, - 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 165, 0, 0, 0, 0, 0, 0, 0, - 0, 111, 0, 0, 0, 0, 0, 137, 0, 139, - 0, 0, 211, 153, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, - 0, 263, 0, 0, 0, 0, 0, 0, 0, 0, - 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 119, 0, 0, 0, 267, 0, 0, 0, + 0, 184, 0, 215, 122, 136, 97, 83, 93, 0, + 121, 162, 191, 195, 0, 0, 0, 105, 0, 193, + 172, 231, 0, 174, 192, 140, 221, 185, 230, 240, + 241, 218, 238, 245, 208, 86, 217, 229, 102, 203, + 88, 227, 214, 151, 131, 132, 87, 0, 189, 110, + 117, 107, 164, 224, 225, 106, 248, 94, 237, 90, + 95, 236, 158, 220, 228, 152, 145, 89, 226, 150, + 144, 135, 114, 124, 182, 142, 183, 125, 155, 154, + 156, 0, 0, 0, 212, 234, 249, 99, 0, 219, + 243, 244, 0, 0, 100, 118, 113, 181, 157, 96, + 127, 209, 134, 141, 188, 247, 171, 194, 103, 233, + 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 82, 91, 138, 246, 186, 116, 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 119, 0, 0, 0, 265, - 0, 0, 0, 0, 184, 0, 215, 122, 136, 97, - 83, 93, 0, 121, 162, 191, 195, 0, 0, 0, - 105, 0, 193, 172, 231, 0, 174, 192, 140, 221, - 185, 230, 240, 241, 218, 238, 245, 208, 86, 217, - 229, 102, 203, 88, 227, 214, 151, 131, 132, 87, - 0, 189, 110, 117, 107, 164, 224, 225, 106, 248, - 94, 237, 90, 95, 236, 158, 220, 228, 152, 145, - 89, 226, 150, 144, 135, 114, 124, 182, 142, 183, - 125, 155, 154, 156, 0, 0, 0, 212, 234, 249, - 99, 0, 219, 243, 244, 0, 0, 100, 118, 113, - 181, 157, 96, 127, 209, 134, 141, 188, 247, 171, - 194, 103, 233, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 82, 91, 138, 246, 186, 116, 235, - 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 84, 85, 92, 98, 104, 108, 112, 115, + 120, 123, 126, 128, 129, 130, 133, 143, 146, 147, + 148, 149, 159, 160, 161, 163, 166, 167, 168, 169, + 170, 173, 175, 176, 177, 178, 179, 180, 187, 190, + 196, 197, 198, 199, 200, 201, 202, 204, 205, 206, + 207, 213, 216, 222, 223, 232, 239, 242, 165, 0, + 0, 0, 0, 0, 0, 0, 0, 111, 0, 0, + 0, 0, 0, 137, 0, 0, 139, 0, 0, 211, + 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 584, 80, 0, + 0, 0, 0, 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 84, 85, 92, 98, 104, - 108, 112, 115, 120, 123, 126, 128, 129, 130, 133, - 143, 146, 147, 148, 149, 159, 160, 161, 163, 166, - 167, 168, 169, 170, 173, 175, 176, 177, 178, 179, - 180, 187, 190, 196, 197, 198, 199, 200, 201, 202, - 204, 205, 206, 207, 213, 216, 222, 223, 232, 239, - 242, 165, 0, 0, 0, 929, 0, 0, 0, 0, - 111, 0, 0, 0, 0, 0, 137, 0, 139, 0, - 0, 211, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 263, 0, 931, 0, 0, 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 119, 0, 0, 0, 267, 0, 0, 0, + 0, 184, 0, 215, 122, 136, 97, 83, 93, 0, + 121, 162, 191, 195, 0, 0, 0, 105, 0, 193, + 172, 231, 0, 174, 192, 140, 221, 185, 230, 240, + 241, 218, 238, 245, 208, 86, 217, 229, 102, 203, + 88, 227, 214, 151, 131, 132, 87, 0, 189, 110, + 117, 107, 164, 224, 225, 106, 248, 94, 237, 90, + 95, 236, 158, 220, 228, 152, 145, 89, 226, 150, + 144, 135, 114, 124, 182, 142, 183, 125, 155, 154, + 156, 0, 0, 0, 212, 234, 249, 99, 0, 219, + 243, 244, 0, 0, 100, 118, 113, 181, 157, 96, + 127, 209, 134, 141, 188, 247, 171, 194, 103, 233, + 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 82, 91, 138, 246, 186, 116, 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 119, 0, 0, 0, 265, 0, - 0, 0, 0, 184, 0, 215, 122, 136, 97, 83, - 93, 0, 121, 162, 191, 195, 0, 0, 0, 105, - 0, 193, 172, 231, 0, 927, 192, 140, 221, 185, - 230, 240, 241, 218, 238, 245, 208, 86, 217, 229, - 102, 203, 88, 227, 214, 151, 131, 132, 87, 0, - 189, 110, 117, 107, 164, 224, 225, 106, 248, 94, - 237, 90, 95, 236, 158, 220, 228, 152, 145, 89, - 226, 150, 144, 135, 114, 124, 182, 142, 183, 125, - 155, 154, 156, 0, 0, 0, 212, 234, 249, 99, - 0, 219, 243, 244, 0, 0, 100, 118, 113, 181, - 157, 96, 127, 209, 134, 141, 188, 247, 171, 194, - 103, 233, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 82, 91, 138, 246, 186, 116, 235, 0, - 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 84, 85, 92, 98, 104, 108, 112, 115, + 120, 123, 126, 128, 129, 130, 133, 143, 146, 147, + 148, 149, 159, 160, 161, 163, 166, 167, 168, 169, + 170, 173, 175, 176, 177, 178, 179, 180, 187, 190, + 196, 197, 198, 199, 200, 201, 202, 204, 205, 206, + 207, 213, 216, 222, 223, 232, 239, 242, 165, 0, + 0, 0, 0, 0, 0, 0, 0, 111, 0, 0, + 0, 0, 0, 137, 0, 0, 139, 0, 0, 211, + 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 54, 0, 0, 265, 0, + 0, 0, 0, 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 84, 85, 92, 98, 104, 108, - 112, 115, 120, 123, 126, 128, 129, 130, 133, 143, - 146, 147, 148, 149, 159, 160, 161, 163, 166, 167, - 168, 169, 170, 173, 175, 176, 177, 178, 179, 180, - 187, 190, 196, 197, 198, 199, 200, 201, 202, 204, - 205, 206, 207, 213, 216, 222, 223, 232, 239, 242, - 165, 0, 0, 0, 0, 0, 0, 0, 0, 111, - 0, 0, 0, 0, 0, 137, 0, 139, 0, 0, - 211, 153, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, - 0, 0, 824, 0, 0, 825, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 119, 0, 0, 0, 267, 0, 0, 0, + 0, 184, 0, 215, 122, 136, 97, 83, 93, 0, + 121, 162, 191, 195, 0, 0, 0, 105, 0, 193, + 172, 231, 0, 174, 192, 140, 221, 185, 230, 240, + 241, 218, 238, 245, 208, 86, 217, 229, 102, 203, + 88, 227, 214, 151, 131, 132, 87, 0, 189, 110, + 117, 107, 164, 224, 225, 106, 248, 94, 237, 90, + 95, 236, 158, 220, 228, 152, 145, 89, 226, 150, + 144, 135, 114, 124, 182, 142, 183, 125, 155, 154, + 156, 0, 0, 0, 212, 234, 249, 99, 0, 219, + 243, 244, 0, 0, 100, 118, 113, 181, 157, 96, + 127, 209, 134, 141, 188, 247, 171, 194, 103, 233, + 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 119, 0, 0, 0, 265, 0, 0, - 0, 0, 184, 0, 215, 122, 136, 97, 83, 93, - 0, 121, 162, 191, 195, 0, 0, 0, 105, 0, - 193, 172, 231, 0, 174, 192, 140, 221, 185, 230, - 240, 241, 218, 238, 245, 208, 86, 217, 229, 102, - 203, 88, 227, 214, 151, 131, 132, 87, 0, 189, - 110, 117, 107, 164, 224, 225, 106, 248, 94, 237, - 90, 95, 236, 158, 220, 228, 152, 145, 89, 226, - 150, 144, 135, 114, 124, 182, 142, 183, 125, 155, - 154, 156, 0, 0, 0, 212, 234, 249, 99, 0, - 219, 243, 244, 0, 0, 100, 118, 113, 181, 157, - 96, 127, 209, 134, 141, 188, 247, 171, 194, 103, - 233, 210, 0, 0, 0, 0, 0, 0, 0, 0, + 82, 91, 138, 246, 186, 116, 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 82, 91, 138, 246, 186, 116, 235, 0, 0, - 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 84, 85, 92, 98, 104, 108, 112, - 115, 120, 123, 126, 128, 129, 130, 133, 143, 146, - 147, 148, 149, 159, 160, 161, 163, 166, 167, 168, - 169, 170, 173, 175, 176, 177, 178, 179, 180, 187, - 190, 196, 197, 198, 199, 200, 201, 202, 204, 205, - 206, 207, 213, 216, 222, 223, 232, 239, 242, 165, - 0, 0, 0, 0, 0, 0, 0, 0, 111, 0, - 712, 0, 0, 0, 137, 0, 139, 0, 0, 211, + 0, 0, 84, 85, 92, 98, 104, 108, 112, 115, + 120, 123, 126, 128, 129, 130, 133, 143, 146, 147, + 148, 149, 159, 160, 161, 163, 166, 167, 168, 169, + 170, 173, 175, 176, 177, 178, 179, 180, 187, 190, + 196, 197, 198, 199, 200, 201, 202, 204, 205, 206, + 207, 213, 216, 222, 223, 232, 239, 242, 165, 0, + 0, 0, 0, 0, 0, 0, 0, 111, 0, 0, + 0, 0, 0, 137, 0, 0, 139, 0, 0, 211, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 80, 0, - 711, 0, 0, 0, 0, 0, 0, 101, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 265, 0, + 947, 0, 0, 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 119, 0, 0, 0, 265, 0, 0, 0, + 0, 0, 119, 0, 0, 0, 267, 0, 0, 0, 0, 184, 0, 215, 122, 136, 97, 83, 93, 0, 121, 162, 191, 195, 0, 0, 0, 105, 0, 193, 172, 231, 0, 174, 192, 140, 221, 185, 230, 240, @@ -2237,82 +2344,83 @@ var yyAct = [...]int{ 196, 197, 198, 199, 200, 201, 202, 204, 205, 206, 207, 213, 216, 222, 223, 232, 239, 242, 165, 0, 0, 0, 0, 0, 0, 0, 0, 111, 0, 0, - 0, 0, 0, 137, 0, 139, 0, 0, 211, 153, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 54, 0, 0, 263, 0, 0, - 0, 0, 0, 0, 0, 0, 101, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 137, 0, 0, 139, 0, 0, 211, + 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 80, 0, + 609, 0, 0, 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 119, 0, 0, 0, 265, 0, 0, 0, 0, - 184, 0, 215, 122, 136, 97, 83, 93, 0, 121, - 162, 191, 195, 0, 0, 0, 105, 0, 193, 172, - 231, 0, 174, 192, 140, 221, 185, 230, 240, 241, - 218, 238, 245, 208, 86, 217, 229, 102, 203, 88, - 227, 214, 151, 131, 132, 87, 0, 189, 110, 117, - 107, 164, 224, 225, 106, 248, 94, 237, 90, 95, - 236, 158, 220, 228, 152, 145, 89, 226, 150, 144, - 135, 114, 124, 182, 142, 183, 125, 155, 154, 156, - 0, 0, 0, 212, 234, 249, 99, 0, 219, 243, - 244, 0, 0, 100, 118, 113, 181, 157, 96, 127, - 209, 134, 141, 188, 247, 171, 194, 103, 233, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, - 91, 138, 246, 186, 116, 235, 0, 0, 109, 0, + 0, 0, 119, 0, 0, 0, 267, 0, 0, 0, + 0, 184, 0, 215, 122, 136, 97, 83, 93, 0, + 121, 162, 191, 195, 0, 0, 0, 105, 0, 193, + 172, 231, 0, 174, 192, 140, 221, 185, 230, 240, + 241, 218, 238, 245, 208, 86, 217, 229, 102, 203, + 88, 227, 214, 151, 131, 132, 87, 0, 189, 110, + 117, 107, 164, 224, 225, 106, 248, 94, 237, 90, + 95, 236, 158, 220, 228, 152, 145, 89, 226, 150, + 144, 135, 114, 124, 182, 142, 183, 125, 155, 154, + 156, 0, 0, 0, 212, 234, 249, 99, 0, 219, + 243, 244, 0, 0, 100, 118, 113, 181, 157, 96, + 127, 209, 134, 141, 188, 247, 171, 194, 103, 233, + 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 82, 91, 138, 246, 186, 116, 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 84, 85, 92, 98, 104, 108, 112, 115, 120, - 123, 126, 128, 129, 130, 133, 143, 146, 147, 148, - 149, 159, 160, 161, 163, 166, 167, 168, 169, 170, - 173, 175, 176, 177, 178, 179, 180, 187, 190, 196, - 197, 198, 199, 200, 201, 202, 204, 205, 206, 207, - 213, 216, 222, 223, 232, 239, 242, 165, 0, 0, - 0, 0, 0, 0, 0, 0, 111, 0, 0, 0, - 0, 0, 137, 0, 139, 0, 0, 211, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 263, 0, 931, 0, - 0, 0, 0, 0, 0, 101, 0, 0, 0, 0, + 0, 0, 84, 85, 92, 98, 104, 108, 112, 115, + 120, 123, 126, 128, 129, 130, 133, 143, 146, 147, + 148, 149, 159, 160, 161, 163, 166, 167, 168, 169, + 170, 173, 175, 176, 177, 178, 179, 180, 187, 190, + 196, 197, 198, 199, 200, 201, 202, 204, 205, 206, + 207, 213, 216, 222, 223, 232, 239, 242, 165, 0, + 0, 0, 0, 0, 0, 0, 692, 111, 0, 0, + 0, 0, 0, 137, 0, 0, 139, 0, 0, 211, + 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 265, 0, + 0, 0, 0, 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 119, 0, 0, 0, 265, 0, 0, 0, 0, 184, - 0, 215, 122, 136, 97, 83, 93, 0, 121, 162, - 191, 195, 0, 0, 0, 105, 0, 193, 172, 231, - 0, 174, 192, 140, 221, 185, 230, 240, 241, 218, - 238, 245, 208, 86, 217, 229, 102, 203, 88, 227, - 214, 151, 131, 132, 87, 0, 189, 110, 117, 107, - 164, 224, 225, 106, 248, 94, 237, 90, 95, 236, - 158, 220, 228, 152, 145, 89, 226, 150, 144, 135, - 114, 124, 182, 142, 183, 125, 155, 154, 156, 0, - 0, 0, 212, 234, 249, 99, 0, 219, 243, 244, - 0, 0, 100, 118, 113, 181, 157, 96, 127, 209, - 134, 141, 188, 247, 171, 194, 103, 233, 210, 0, + 0, 0, 119, 0, 0, 0, 267, 0, 0, 0, + 0, 184, 0, 215, 122, 136, 97, 83, 93, 0, + 121, 162, 191, 195, 0, 0, 0, 105, 0, 193, + 172, 231, 0, 174, 192, 140, 221, 185, 230, 240, + 241, 218, 238, 245, 208, 86, 217, 229, 102, 203, + 88, 227, 214, 151, 131, 132, 87, 0, 189, 110, + 117, 107, 164, 224, 225, 106, 248, 94, 237, 90, + 95, 236, 158, 220, 228, 152, 145, 89, 226, 150, + 144, 135, 114, 124, 182, 142, 183, 125, 155, 154, + 156, 0, 0, 0, 212, 234, 249, 99, 0, 219, + 243, 244, 0, 0, 100, 118, 113, 181, 157, 96, + 127, 209, 134, 141, 188, 247, 171, 194, 103, 233, + 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 91, - 138, 246, 186, 116, 235, 0, 0, 109, 0, 0, + 82, 91, 138, 246, 186, 116, 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 84, 85, 92, 98, 104, 108, 112, 115, 120, 123, - 126, 128, 129, 130, 133, 143, 146, 147, 148, 149, - 159, 160, 161, 163, 166, 167, 168, 169, 170, 173, - 175, 176, 177, 178, 179, 180, 187, 190, 196, 197, - 198, 199, 200, 201, 202, 204, 205, 206, 207, 213, - 216, 222, 223, 232, 239, 242, 165, 0, 0, 0, - 0, 0, 0, 0, 0, 111, 0, 0, 0, 0, - 0, 137, 0, 139, 0, 0, 211, 153, 0, 0, + 0, 0, 84, 85, 92, 98, 104, 108, 112, 115, + 120, 123, 126, 128, 129, 130, 133, 143, 146, 147, + 148, 149, 159, 160, 161, 163, 166, 167, 168, 169, + 170, 173, 175, 176, 177, 178, 179, 180, 187, 190, + 196, 197, 198, 199, 200, 201, 202, 204, 205, 206, + 207, 213, 216, 222, 223, 232, 239, 242, 382, 0, + 0, 0, 0, 0, 0, 165, 0, 0, 0, 0, + 0, 0, 0, 0, 111, 0, 0, 0, 0, 0, + 137, 0, 0, 139, 0, 0, 211, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 80, 0, 600, 0, 0, + 0, 0, 0, 0, 0, 265, 0, 0, 0, 0, 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, - 0, 0, 0, 265, 0, 0, 0, 0, 184, 0, + 0, 0, 0, 267, 0, 0, 0, 0, 184, 0, 215, 122, 136, 97, 83, 93, 0, 121, 162, 191, 195, 0, 0, 0, 105, 0, 193, 172, 231, 0, 174, 192, 140, 221, 185, 230, 240, 241, 218, 238, @@ -2332,218 +2440,152 @@ var yyAct = [...]int{ 85, 92, 98, 104, 108, 112, 115, 120, 123, 126, 128, 129, 130, 133, 143, 146, 147, 148, 149, 159, 160, 161, 163, 166, 167, 168, 169, 170, 173, 175, - 176, 177, 178, 179, 180, 187, 190, 196, 197, 198, - 199, 200, 201, 202, 204, 205, 206, 207, 213, 216, - 222, 223, 232, 239, 242, 165, 0, 0, 0, 0, - 0, 0, 0, 682, 111, 0, 0, 0, 0, 0, - 137, 0, 139, 0, 0, 211, 153, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 263, 0, 0, 0, 0, 0, - 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 119, 0, - 0, 0, 265, 0, 0, 0, 0, 184, 0, 215, - 122, 136, 97, 83, 93, 0, 121, 162, 191, 195, - 0, 0, 0, 105, 0, 193, 172, 231, 0, 174, - 192, 140, 221, 185, 230, 240, 241, 218, 238, 245, - 208, 86, 217, 229, 102, 203, 88, 227, 214, 151, - 131, 132, 87, 0, 189, 110, 117, 107, 164, 224, - 225, 106, 248, 94, 237, 90, 95, 236, 158, 220, - 228, 152, 145, 89, 226, 150, 144, 135, 114, 124, - 182, 142, 183, 125, 155, 154, 156, 0, 0, 0, - 212, 234, 249, 99, 0, 219, 243, 244, 0, 0, - 100, 118, 113, 181, 157, 96, 127, 209, 134, 141, - 188, 247, 171, 194, 103, 233, 210, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 82, 91, 138, 246, - 186, 116, 235, 0, 0, 109, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 84, 85, - 92, 98, 104, 108, 112, 115, 120, 123, 126, 128, - 129, 130, 133, 143, 146, 147, 148, 149, 159, 160, - 161, 163, 166, 167, 168, 169, 170, 173, 175, 176, - 177, 178, 179, 180, 187, 190, 196, 197, 198, 199, - 200, 201, 202, 204, 205, 206, 207, 213, 216, 222, - 223, 232, 239, 242, 379, 0, 0, 0, 0, 0, - 0, 165, 0, 0, 0, 0, 0, 0, 0, 0, - 111, 0, 0, 0, 0, 0, 137, 0, 139, 0, - 0, 211, 153, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 263, 0, 0, 0, 0, 0, 0, 0, 0, 101, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 119, 0, 0, 0, 265, 0, - 0, 0, 0, 184, 0, 215, 122, 136, 97, 83, - 93, 0, 121, 162, 191, 195, 0, 0, 0, 105, - 0, 193, 172, 231, 0, 174, 192, 140, 221, 185, - 230, 240, 241, 218, 238, 245, 208, 86, 217, 229, - 102, 203, 88, 227, 214, 151, 131, 132, 87, 0, - 189, 110, 117, 107, 164, 224, 225, 106, 248, 94, - 237, 90, 95, 236, 158, 220, 228, 152, 145, 89, - 226, 150, 144, 135, 114, 124, 182, 142, 183, 125, - 155, 154, 156, 0, 0, 0, 212, 234, 249, 99, - 0, 219, 243, 244, 0, 0, 100, 118, 113, 181, - 157, 96, 127, 209, 134, 141, 188, 247, 171, 194, - 103, 233, 210, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 82, 91, 138, 246, 186, 116, 235, 0, - 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 84, 85, 92, 98, 104, 108, - 112, 115, 120, 123, 126, 128, 129, 130, 133, 143, - 146, 147, 148, 149, 159, 160, 161, 163, 166, 167, - 168, 169, 170, 173, 175, 176, 177, 178, 179, 180, - 187, 190, 196, 197, 198, 199, 200, 201, 202, 204, - 205, 206, 207, 213, 216, 222, 223, 232, 239, 242, - 165, 0, 0, 0, 0, 0, 0, 0, 0, 111, - 0, 0, 0, 0, 0, 137, 0, 139, 0, 0, - 211, 153, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 263, - 0, 0, 0, 0, 0, 0, 0, 0, 101, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 119, 0, 260, 0, 265, 0, 0, - 0, 0, 184, 0, 215, 122, 136, 97, 83, 93, - 0, 121, 162, 191, 195, 0, 0, 0, 105, 0, - 193, 172, 231, 0, 174, 192, 140, 221, 185, 230, - 240, 241, 218, 238, 245, 208, 86, 217, 229, 102, - 203, 88, 227, 214, 151, 131, 132, 87, 0, 189, - 110, 117, 107, 164, 224, 225, 106, 248, 94, 237, - 90, 95, 236, 158, 220, 228, 152, 145, 89, 226, - 150, 144, 135, 114, 124, 182, 142, 183, 125, 155, - 154, 156, 0, 0, 0, 212, 234, 249, 99, 0, - 219, 243, 244, 0, 0, 100, 118, 113, 181, 157, - 96, 127, 209, 134, 141, 188, 247, 171, 194, 103, - 233, 210, 0, 0, 0, 0, 0, 0, 0, 0, + 176, 177, 178, 179, 180, 187, 190, 196, 197, 198, + 199, 200, 201, 202, 204, 205, 206, 207, 213, 216, + 222, 223, 232, 239, 242, 165, 0, 0, 0, 0, + 0, 0, 0, 0, 111, 0, 0, 0, 0, 0, + 137, 0, 0, 139, 0, 0, 211, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 82, 91, 138, 246, 186, 116, 235, 0, 0, - 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 265, 0, 0, 0, 0, + 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 84, 85, 92, 98, 104, 108, 112, - 115, 120, 123, 126, 128, 129, 130, 133, 143, 146, - 147, 148, 149, 159, 160, 161, 163, 166, 167, 168, - 169, 170, 173, 175, 176, 177, 178, 179, 180, 187, - 190, 196, 197, 198, 199, 200, 201, 202, 204, 205, - 206, 207, 213, 216, 222, 223, 232, 239, 242, 165, - 0, 0, 0, 0, 0, 0, 0, 0, 111, 0, - 0, 0, 0, 0, 137, 0, 139, 0, 0, 211, - 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 80, 0, - 0, 0, 0, 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, + 0, 262, 0, 267, 0, 0, 0, 0, 184, 0, + 215, 122, 136, 97, 83, 93, 0, 121, 162, 191, + 195, 0, 0, 0, 105, 0, 193, 172, 231, 0, + 174, 192, 140, 221, 185, 230, 240, 241, 218, 238, + 245, 208, 86, 217, 229, 102, 203, 88, 227, 214, + 151, 131, 132, 87, 0, 189, 110, 117, 107, 164, + 224, 225, 106, 248, 94, 237, 90, 95, 236, 158, + 220, 228, 152, 145, 89, 226, 150, 144, 135, 114, + 124, 182, 142, 183, 125, 155, 154, 156, 0, 0, + 0, 212, 234, 249, 99, 0, 219, 243, 244, 0, + 0, 100, 118, 113, 181, 157, 96, 127, 209, 134, + 141, 188, 247, 171, 194, 103, 233, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 82, 91, 138, + 246, 186, 116, 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 119, 0, 0, 0, 265, 0, 0, 0, - 0, 184, 0, 215, 122, 136, 97, 83, 93, 0, - 121, 162, 191, 195, 0, 0, 0, 105, 0, 193, - 172, 231, 0, 174, 192, 140, 221, 185, 230, 240, - 241, 218, 238, 245, 208, 86, 217, 229, 102, 203, - 88, 227, 214, 151, 131, 132, 87, 0, 189, 110, - 117, 107, 164, 224, 225, 106, 248, 94, 237, 90, - 95, 236, 158, 220, 228, 152, 145, 89, 226, 150, - 144, 135, 114, 124, 182, 142, 183, 125, 155, 154, - 156, 0, 0, 0, 212, 234, 249, 99, 0, 219, - 243, 244, 0, 0, 100, 118, 113, 181, 157, 96, - 127, 209, 134, 141, 188, 247, 171, 194, 103, 233, - 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, + 85, 92, 98, 104, 108, 112, 115, 120, 123, 126, + 128, 129, 130, 133, 143, 146, 147, 148, 149, 159, + 160, 161, 163, 166, 167, 168, 169, 170, 173, 175, + 176, 177, 178, 179, 180, 187, 190, 196, 197, 198, + 199, 200, 201, 202, 204, 205, 206, 207, 213, 216, + 222, 223, 232, 239, 242, 165, 0, 0, 0, 0, + 0, 0, 0, 0, 111, 0, 0, 0, 0, 0, + 137, 0, 0, 139, 0, 0, 211, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 82, 91, 138, 246, 186, 116, 235, 0, 0, 109, + 0, 0, 0, 0, 0, 80, 0, 0, 0, 0, + 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 84, 85, 92, 98, 104, 108, 112, 115, - 120, 123, 126, 128, 129, 130, 133, 143, 146, 147, - 148, 149, 159, 160, 161, 163, 166, 167, 168, 169, - 170, 173, 175, 176, 177, 178, 179, 180, 187, 190, - 196, 197, 198, 199, 200, 201, 202, 204, 205, 206, - 207, 213, 216, 222, 223, 232, 239, 242, 165, 0, - 0, 0, 0, 0, 0, 0, 0, 111, 0, 0, - 0, 0, 0, 137, 0, 139, 0, 0, 211, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 263, 0, 0, - 0, 0, 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, + 0, 0, 0, 267, 0, 0, 0, 0, 184, 0, + 215, 122, 136, 97, 83, 93, 0, 121, 162, 191, + 195, 0, 0, 0, 105, 0, 193, 172, 231, 0, + 174, 192, 140, 221, 185, 230, 240, 241, 218, 238, + 245, 208, 86, 217, 229, 102, 203, 88, 227, 214, + 151, 131, 132, 87, 0, 189, 110, 117, 107, 164, + 224, 225, 106, 248, 94, 237, 90, 95, 236, 158, + 220, 228, 152, 145, 89, 226, 150, 144, 135, 114, + 124, 182, 142, 183, 125, 155, 154, 156, 0, 0, + 0, 212, 234, 249, 99, 0, 219, 243, 244, 0, + 0, 100, 118, 113, 181, 157, 96, 127, 209, 134, + 141, 188, 247, 171, 194, 103, 233, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 82, 91, 138, + 246, 186, 116, 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, + 85, 92, 98, 104, 108, 112, 115, 120, 123, 126, + 128, 129, 130, 133, 143, 146, 147, 148, 149, 159, + 160, 161, 163, 166, 167, 168, 169, 170, 173, 175, + 176, 177, 178, 179, 180, 187, 190, 196, 197, 198, + 199, 200, 201, 202, 204, 205, 206, 207, 213, 216, + 222, 223, 232, 239, 242, 165, 0, 0, 0, 0, + 0, 0, 0, 0, 111, 0, 0, 0, 0, 0, + 137, 0, 0, 139, 0, 0, 211, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 265, 0, 0, 0, 0, + 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 119, 0, 0, 0, 265, 0, 0, 0, 0, - 184, 0, 215, 122, 136, 97, 83, 93, 0, 121, - 162, 191, 195, 0, 0, 0, 105, 0, 193, 172, - 231, 0, 174, 192, 140, 221, 185, 230, 240, 241, - 218, 238, 245, 208, 86, 217, 229, 102, 203, 88, - 227, 214, 151, 131, 132, 87, 0, 189, 110, 117, - 107, 164, 224, 225, 106, 248, 94, 237, 90, 95, - 236, 158, 220, 228, 152, 145, 89, 226, 150, 144, - 135, 114, 124, 182, 142, 183, 125, 155, 154, 156, - 0, 0, 0, 212, 234, 249, 99, 0, 219, 243, - 244, 0, 0, 100, 118, 113, 181, 157, 96, 127, - 209, 134, 141, 188, 247, 171, 194, 103, 233, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, - 91, 138, 246, 186, 116, 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 84, 85, 92, 98, 104, 108, 112, 115, 120, - 123, 126, 128, 129, 130, 133, 143, 146, 147, 148, - 149, 159, 160, 161, 163, 166, 167, 168, 169, 170, - 173, 175, 176, 177, 178, 179, 180, 187, 190, 196, - 197, 198, 199, 200, 201, 202, 204, 205, 206, 207, - 213, 216, 222, 223, 232, 239, 242, 165, 0, 0, - 0, 0, 0, 0, 0, 0, 111, 0, 0, 0, - 0, 0, 137, 0, 139, 0, 0, 211, 153, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, + 0, 0, 0, 267, 0, 0, 0, 0, 184, 0, + 215, 122, 136, 97, 83, 93, 0, 121, 162, 191, + 195, 0, 0, 0, 105, 0, 193, 172, 231, 0, + 174, 192, 140, 221, 185, 230, 240, 241, 218, 238, + 245, 208, 86, 217, 229, 102, 203, 88, 227, 214, + 151, 131, 132, 87, 0, 189, 110, 117, 107, 164, + 224, 225, 106, 248, 94, 237, 90, 95, 236, 158, + 220, 228, 152, 145, 89, 226, 150, 144, 135, 114, + 124, 182, 142, 183, 125, 155, 154, 156, 0, 0, + 0, 212, 234, 249, 99, 0, 219, 243, 244, 0, + 0, 100, 118, 113, 181, 157, 96, 127, 209, 134, + 141, 188, 247, 171, 194, 103, 233, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 320, 0, 0, 0, - 0, 0, 0, 0, 0, 101, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 82, 91, 138, + 246, 186, 116, 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, + 85, 92, 98, 104, 108, 112, 115, 120, 123, 126, + 128, 129, 130, 133, 143, 146, 147, 148, 149, 159, + 160, 161, 163, 166, 167, 168, 169, 170, 173, 175, + 176, 177, 178, 179, 180, 187, 190, 196, 197, 198, + 199, 200, 201, 202, 204, 205, 206, 207, 213, 216, + 222, 223, 232, 239, 242, 165, 0, 0, 0, 0, + 0, 0, 0, 0, 111, 0, 0, 0, 0, 0, + 137, 0, 0, 139, 0, 0, 211, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 322, 0, 0, 0, 0, + 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 119, 0, 0, 0, 265, 0, 0, 0, 0, 184, - 0, 215, 122, 136, 97, 83, 93, 0, 121, 162, - 191, 195, 0, 0, 0, 105, 0, 193, 172, 231, - 0, 174, 192, 140, 221, 185, 230, 240, 241, 218, - 238, 245, 208, 86, 217, 229, 102, 203, 88, 227, - 214, 151, 131, 132, 87, 0, 189, 110, 117, 107, - 164, 224, 225, 106, 248, 94, 237, 90, 95, 236, - 158, 220, 228, 152, 145, 89, 226, 150, 144, 135, - 114, 124, 182, 142, 183, 125, 155, 154, 156, 0, - 0, 0, 212, 234, 249, 99, 0, 219, 243, 244, - 0, 0, 100, 118, 113, 181, 157, 96, 127, 209, - 134, 141, 188, 247, 171, 194, 103, 233, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 82, 91, - 138, 246, 186, 116, 235, 0, 0, 109, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, + 0, 0, 0, 267, 0, 0, 0, 0, 184, 0, + 215, 122, 136, 97, 83, 93, 0, 121, 162, 191, + 195, 0, 0, 0, 105, 0, 193, 172, 231, 0, + 174, 192, 140, 221, 185, 230, 240, 241, 218, 238, + 245, 208, 86, 217, 229, 102, 203, 88, 227, 214, + 151, 131, 132, 87, 0, 189, 110, 117, 107, 164, + 224, 225, 106, 248, 94, 237, 90, 95, 236, 158, + 220, 228, 152, 145, 89, 226, 150, 144, 135, 114, + 124, 182, 142, 183, 125, 155, 154, 156, 0, 0, + 0, 212, 234, 249, 99, 0, 219, 243, 244, 0, + 0, 100, 118, 113, 181, 157, 96, 127, 209, 134, + 141, 188, 247, 171, 194, 103, 233, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 82, 91, 138, + 246, 186, 116, 235, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 84, 85, 92, 98, 104, 108, 112, 115, 120, 123, - 126, 128, 129, 130, 133, 143, 146, 147, 148, 149, - 159, 160, 161, 163, 166, 167, 168, 169, 170, 173, - 175, 176, 177, 178, 179, 180, 187, 190, 196, 197, - 198, 199, 200, 201, 202, 204, 205, 206, 207, 213, - 216, 222, 223, 232, 239, 242, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, + 85, 92, 98, 104, 108, 112, 115, 120, 123, 126, + 128, 129, 130, 133, 143, 146, 147, 148, 149, 159, + 160, 161, 163, 166, 167, 168, 169, 170, 173, 175, + 176, 177, 178, 179, 180, 187, 190, 196, 197, 198, + 199, 200, 201, 202, 204, 205, 206, 207, 213, 216, + 222, 223, 232, 239, 242, } var yyPact = [...]int{ - 1877, -1000, -267, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 258, -1000, -270, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 940, 995, -1000, -1000, -1000, -1000, -1000, -1000, - 255, 11283, 36, 110, -5, 15262, 109, 1522, 15920, -1000, - 13, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -80, -91, - -1000, 687, -1000, -1000, -1000, -1000, -1000, 914, 938, 778, - 907, 822, -1000, 7981, 77, 77, 14933, 6665, -1000, -1000, - 212, 15920, 101, 15920, -147, 80, 80, 80, -1000, -1000, + -1000, -1000, 879, 942, -1000, -1000, -1000, -1000, -1000, -1000, + 252, 11336, 49, 107, 33, 15657, 97, 275, 16317, -1000, + 11, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -57, -66, + -1000, 694, -1000, -1000, -1000, -1000, -1000, 873, 876, 741, + 868, 803, -1000, 8024, 75, 75, 15327, 6704, -1000, -1000, + 240, 16317, 91, 16317, -145, 73, 73, 73, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, @@ -2561,22 +2603,21 @@ var yyPact = [...]int{ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 107, 15920, 186, -1000, 15920, 75, 531, 75, 75, 75, - 15920, -1000, 141, -1000, -1000, -1000, 15920, 525, 873, 3587, - 55, 3587, -1000, 3587, 3587, -1000, 3587, 24, 3587, -83, - 955, 25, -44, -1000, 3587, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 538, 885, - 9309, 9309, 940, -1000, 687, -1000, -1000, -1000, 862, -1000, - -1000, 274, 972, -1000, 10954, 139, -1000, 9309, 1633, 634, - -1000, -1000, 634, -1000, -1000, 128, -1000, -1000, 10296, 10296, - 10296, 10296, 10296, 10296, 10296, 10296, -1000, -1000, -1000, -1000, + 96, 16317, 536, 534, 176, -1000, 16317, 71, 531, 71, + 71, 71, 16317, -1000, 141, -1000, -1000, -1000, 16317, 526, + 834, 288, 70, 3617, -1000, 3617, 3617, -1000, 3617, 20, + 3617, -59, 900, 18, -8, -1000, 3617, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 634, -1000, 8980, 634, 634, 634, 634, 634, 634, 634, - 634, 9309, 634, 634, 634, 634, 634, 634, 634, 634, - 634, 634, 634, 634, 634, 634, 634, 14597, 13610, 15920, - 743, 702, -1000, -1000, 138, 689, 6323, -97, -1000, -1000, - -1000, 206, 13281, -1000, -1000, -1000, 870, -1000, -1000, -1000, + 546, 844, 9356, 9356, 879, -1000, 694, -1000, -1000, -1000, + 831, -1000, -1000, 306, 924, -1000, 11006, 140, -1000, 9356, + 2043, 700, -1000, -1000, 700, -1000, -1000, 119, -1000, -1000, + 10346, 10346, 10346, 10346, 10346, 10346, 10346, 10346, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 700, -1000, 9026, 700, 700, 700, 700, 700, + 700, 700, 700, 9356, 700, 700, 700, 700, 700, 700, + 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, + 14990, 14000, 16317, 673, 666, -1000, -1000, 138, 692, 6361, + -98, -1000, -1000, -1000, 219, 13340, -1000, -1000, -1000, 829, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, @@ -2587,130 +2628,133 @@ var yyPact = [...]int{ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 619, 15920, -1000, 2291, -1000, - 516, 3587, 92, 490, 244, 487, 15920, 15920, 3587, 31, - 64, 60, 15920, 693, 90, 15920, 901, 785, 15920, 477, - 473, -1000, 5981, -1000, 3587, 3587, -1000, -1000, -1000, 3587, - 3587, 3587, 15920, 3587, 3587, -1000, -1000, -1000, -1000, 3587, - 3587, -1000, 966, 262, -1000, -1000, -1000, -1000, 9309, 176, - -1000, 784, -1000, -1000, -1000, -1000, -1000, -1000, 988, 172, - 446, 136, 692, -1000, 384, 914, 538, 822, 12952, 787, - -1000, -1000, 15920, -1000, 9309, 9309, 494, -1000, 14268, -1000, - -1000, 4613, 179, 10296, 346, 272, 10296, 10296, 10296, 10296, - 10296, 10296, 10296, 10296, 10296, 10296, 10296, 10296, 10296, 10296, - 10296, 382, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 466, -1000, 687, 574, 574, 151, 151, 151, 151, 151, - 151, 151, 10625, 7323, 538, 617, 322, 8980, 7981, 7981, - 9309, 9309, 8639, 8310, 7981, 908, 215, 322, 16249, -1000, - -1000, 9967, -1000, -1000, -1000, -1000, -1000, 538, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 15591, 15591, 7981, 7981, 7981, - 7981, 46, 15920, -1000, 652, 961, -1000, -1000, -1000, 903, - 12294, 12623, 46, 655, 13610, 15920, -1000, -1000, 13610, 15920, - 4271, 5639, 689, -97, 657, -1000, -126, -103, 6994, 147, - -1000, -1000, -1000, -1000, 3245, 253, 558, 293, -58, -1000, - -1000, -1000, 737, -1000, 737, 737, 737, 737, -27, -27, - -27, -27, -1000, -1000, -1000, -1000, -1000, 757, 755, -1000, - 737, 737, 737, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 754, 754, 754, 740, 740, 759, -1000, 15920, 3587, - 898, 3587, -1000, 76, -1000, 15920, 15920, 15920, 15920, 15920, - 117, 15920, 15920, 688, -1000, 15920, 3587, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 624, + 16317, -1000, 2399, -1000, 523, 3617, 82, 521, 244, 519, + 16317, 16317, 3617, 3617, 3617, 26, 59, 55, 16317, 698, + 79, 16317, 861, 756, 16317, 507, 504, -1000, 6018, -1000, + 3617, 288, -1000, 440, 9356, 3617, 3617, 3617, 16317, 3617, + 3617, -1000, -1000, -1000, -1000, -1000, -1000, 3617, 3617, -1000, + 912, 293, -1000, -1000, -1000, -1000, 9356, 204, -1000, 754, + -1000, -1000, -1000, -1000, -1000, -1000, 936, 187, 522, 136, + 697, -1000, 474, 873, 546, 803, 13010, 770, -1000, -1000, + -1000, 16317, -1000, 9356, 9356, 388, -1000, 14660, -1000, -1000, + 4646, 203, 10346, 279, 255, 10346, 10346, 10346, 10346, 10346, + 10346, 10346, 10346, 10346, 10346, 10346, 10346, 10346, 10346, 10346, + 373, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 494, + -1000, 694, 594, 594, 152, 152, 152, 152, 152, 152, + 152, 10676, 7034, 546, 619, 451, 9026, 8024, 8024, 9356, + 9356, 8684, 8354, 8024, 839, 242, 451, 16647, -1000, -1000, + 10016, -1000, -1000, -1000, -1000, -1000, 546, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 15987, 15987, 8024, 8024, 8024, 8024, + 8024, 42, 16317, -1000, 689, 858, -1000, -1000, -1000, 864, + 12350, 12680, 42, 683, 14000, 16317, -1000, -1000, 14000, 16317, + 4303, 5675, 692, -98, 675, -1000, -82, -86, 7364, 148, + -1000, -1000, -1000, -1000, 3274, 397, 567, 319, -47, -1000, + -1000, -1000, 703, -1000, 703, 703, 703, 703, -17, -17, + -17, -17, -1000, -1000, -1000, -1000, -1000, 721, 716, -1000, + 703, 703, 703, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 15920, 313, 15920, 15920, 322, -1000, 425, 15920, - -1000, 835, 9309, 9309, 5297, 9309, -1000, -1000, -1000, 885, - -1000, 908, 945, -1000, 860, 847, 7981, -1000, -1000, 179, - 227, -1000, -1000, 329, -1000, -1000, -1000, -1000, 135, 634, - -1000, 2130, -1000, -1000, -1000, -1000, 346, 10296, 10296, 10296, - 409, 2130, 2088, 789, 722, 151, 269, 269, 155, 155, - 155, 155, 155, 393, 393, -1000, -1000, -1000, 538, -1000, - -1000, -1000, 538, 7981, 668, -1000, -1000, 9309, -1000, 538, - 611, 611, 514, 459, 238, 960, 611, 229, 959, 611, - 611, 7981, 254, -1000, 9309, 538, -1000, 134, -1000, 633, - 664, 661, 611, 538, 611, 611, 684, 634, -1000, 16249, - 13610, 13610, 13610, 13610, 13610, -1000, 814, 813, -1000, 804, - 798, 805, 15920, -1000, 615, 12294, 163, 634, -1000, 13939, - -1000, -1000, 954, 13610, 632, -1000, 632, -1000, 133, -1000, - -1000, 657, -97, -125, -1000, -1000, -1000, -1000, 322, -1000, - 402, 656, 2903, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 748, 463, -1000, 889, 199, 203, 458, 882, -1000, -1000, - -1000, 876, -1000, 260, -105, -1000, -1000, 391, -27, -27, - -1000, -1000, 147, 869, 147, 147, 147, 424, 424, -1000, - -1000, -1000, -1000, 363, -1000, -1000, -1000, 341, -1000, 783, - 15591, 3587, -1000, -1000, -1000, -1000, 347, 347, 198, -1000, + -1000, 714, 714, 714, 708, 708, 723, -1000, 16317, 3617, + 859, 3617, -1000, 72, -1000, -1000, -1000, 16317, 16317, 16317, + 16317, 16317, 114, 16317, 16317, 687, -1000, 16317, 3617, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 451, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 16317, 288, 16317, 16317, + 451, -1000, 424, 16317, -1000, 789, 9356, 9356, 5332, 9356, + -1000, -1000, -1000, 844, -1000, 839, 880, -1000, 821, 820, + 8024, -1000, -1000, 203, 295, -1000, -1000, 517, -1000, -1000, + -1000, -1000, 134, 700, -1000, 1602, -1000, -1000, -1000, -1000, + 279, 10346, 10346, 10346, 262, 1602, 1783, 1240, 1657, 152, + 386, 386, 153, 153, 153, 153, 153, 313, 313, -1000, + -1000, -1000, 546, -1000, -1000, -1000, 546, 8024, 8024, 685, + -1000, -1000, 9356, -1000, 546, 610, 610, 281, 346, 227, + 909, 610, 225, 903, 610, 610, 8024, 314, -1000, 9356, + 546, -1000, 133, -1000, 372, 682, 679, 610, 546, 546, + 610, 610, 691, 700, -1000, 16647, 14000, 14000, 14000, 14000, + 14000, -1000, 790, 788, -1000, 768, 767, 780, 16317, -1000, + 612, 12350, 158, 700, -1000, 14330, -1000, -1000, 899, 14000, + 684, -1000, 684, -1000, 131, -1000, -1000, 675, -98, -105, + -1000, -1000, -1000, -1000, 451, -1000, 381, 668, 2931, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 712, 488, -1000, 850, + 185, 220, 480, 849, -1000, -1000, -1000, 832, -1000, 261, + -53, -1000, -1000, 369, -17, -17, -1000, -1000, 148, 828, + 148, 148, 148, 422, 422, -1000, -1000, -1000, -1000, 361, + -1000, -1000, -1000, 345, -1000, 753, 15987, 3617, -1000, -1000, + -1000, -1000, 785, 785, 202, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 39, 596, -1000, -1000, + -1000, -1000, 10, 25, 74, -1000, 3617, -1000, 293, -1000, + -1000, -1000, -1000, -1000, 801, 451, 451, 129, -1000, -1000, + 16317, -1000, -1000, -1000, -1000, 659, -1000, -1000, -1000, 3960, + 8024, -1000, 262, 1602, 1643, -1000, 10346, 10346, -1000, -1000, + 610, 610, 8024, 451, -1000, -1000, -1000, 58, 373, 58, + 10346, 10346, -1000, 10346, 10346, -1000, -160, 667, 232, -1000, + 9356, 493, -1000, 5332, -1000, 10346, 10346, -1000, -1000, -1000, + -1000, -1000, 744, 16647, 700, -1000, 12008, 15987, 695, -1000, + 218, 858, 720, 740, 645, -1000, -1000, -1000, -1000, 779, + -1000, 778, -1000, -1000, -1000, -1000, -1000, 90, 89, 87, + 15987, -1000, 879, 9356, 684, -1000, -1000, 171, -1000, -1000, + -109, -91, -1000, -1000, -1000, 3274, -1000, 3274, 15987, 57, + -1000, 480, 480, -1000, -1000, -1000, 711, 728, 10346, -1000, + -1000, -1000, 560, 148, 148, -1000, 197, -1000, -1000, -1000, + 608, -1000, 590, 662, 573, 16317, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 45, 576, -1000, -1000, -1000, -1000, -1, 30, 83, -1000, - 3587, -1000, 262, -1000, 416, 9309, -1000, -1000, -1000, -1000, - 827, 322, 322, 131, -1000, -1000, 15920, -1000, -1000, -1000, - -1000, 669, -1000, -1000, -1000, 3929, 7981, -1000, 409, 2130, - 2055, -1000, 10296, 10296, -1000, -1000, 611, 7981, 322, -1000, - -1000, -1000, 98, 382, 98, 10296, 10296, -1000, 10296, 10296, - -1000, -165, 691, 210, -1000, 9309, 317, -1000, 5297, -1000, - 10296, 10296, -1000, -1000, -1000, -1000, 782, 16249, 634, -1000, - 11953, 15591, 643, -1000, 204, 961, 747, 776, 604, -1000, - -1000, -1000, -1000, 812, -1000, 796, -1000, -1000, -1000, -1000, - -1000, 100, 97, 94, 15591, -1000, 940, 9309, 632, -1000, - -1000, 164, -1000, -1000, -130, -108, -1000, -1000, -1000, 3245, - -1000, 3245, 15591, 61, -1000, 458, 458, -1000, -1000, -1000, - 741, 761, 10296, -1000, -1000, -1000, 554, 147, 147, -1000, - 200, -1000, -1000, -1000, 583, -1000, 571, 642, 545, 15920, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 15920, -1000, -1000, - -1000, -1000, -1000, 15591, -173, 457, 15591, 15591, 15591, 15920, - -1000, 313, -1000, 322, -1000, 4955, -1000, 954, 13610, -1000, - -1000, 538, -1000, 10296, 2130, 2130, -1000, -1000, 538, 737, - 737, -1000, 737, 740, -1000, 737, 3, 737, 2, 538, - 538, 2040, 1999, 1869, 1843, 634, -160, -1000, 322, 9309, - -1000, 1705, 1118, -1000, 892, 553, 596, -1000, -1000, 7652, - 538, 541, 127, 536, -1000, 940, 16249, 9309, -1000, -1000, - 9309, 739, -1000, 9309, -1000, -1000, -1000, 634, 634, 634, - 536, 914, 322, -1000, -1000, -1000, -1000, 2903, -1000, 529, - -1000, 737, -1000, -1000, -1000, 15591, -51, 981, 2130, -1000, - -1000, -1000, -1000, -1000, -27, 415, -27, 326, -1000, 305, - 3587, -1000, -1000, -1000, -1000, 894, -1000, 4955, -1000, -1000, - 731, 744, -1000, -1000, -1000, 952, 631, -1000, 2130, -1000, - -1000, 118, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 10296, 10296, 10296, 10296, 10296, 538, 410, 322, 10296, 10296, - 881, -1000, 634, -1000, -1000, 711, 15591, 15591, -1000, 15591, - 914, -1000, 322, 322, 15591, 322, 15591, 15591, 15591, 11612, - -1000, 149, 15591, -1000, 523, -1000, 191, -1000, -75, 147, - -1000, 147, 546, 542, -1000, 634, 626, -1000, 194, 15591, - 15920, 943, 916, -1000, -1000, 633, 633, 633, 633, 51, - -1000, -1000, 633, 633, 979, -1000, 634, -1000, 687, 123, - -1000, -1000, -1000, 521, 503, 503, 503, 163, 149, -1000, - 441, 189, 404, -1000, 58, 15591, 271, 880, -1000, 879, - -1000, -1000, -1000, -1000, -1000, 43, 4955, 3245, 485, -1000, - -1000, 9309, 9309, -1000, -1000, -1000, -1000, 538, 44, -177, - -1000, -1000, 16249, 596, 538, 15591, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 298, -1000, -1000, 15920, -1000, -1000, 395, - -1000, -1000, 482, -1000, 15591, -1000, -1000, 576, 322, 575, - -1000, 826, -171, -181, 562, -1000, -1000, -1000, 704, -1000, - -1000, 43, 843, -173, -1000, 825, -1000, 15591, -1000, 37, - -1000, -175, 432, 35, -178, 749, 634, -182, 690, -1000, - 984, 9638, -1000, -1000, 977, 177, 177, 633, 538, -1000, - -1000, -1000, 65, 345, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 16317, -1000, -1000, -1000, -1000, -1000, 15987, + -173, 471, 15987, 15987, 15987, 16317, -1000, 288, -1000, 4989, + -1000, 899, 14000, -1000, -1000, 546, -1000, 10346, 1602, 1602, + -1000, -1000, -1000, 546, 703, 703, -1000, 703, 708, -1000, + 703, 1, 703, -1, 546, 546, 1578, 1132, 997, 415, + 700, -152, -1000, 451, 9356, -1000, 1478, 537, -1000, 852, + 595, 627, -1000, -1000, 7694, 546, 570, 127, 566, -1000, + 879, 16647, 9356, -1000, -1000, 9356, 707, -1000, 9356, -1000, + -1000, -1000, 700, 700, 700, 566, 873, 451, -1000, -1000, + -1000, -1000, 2931, -1000, 557, -1000, 703, -1000, -1000, -1000, + 15987, -42, 931, 1602, -1000, -1000, -1000, -1000, -1000, -17, + 421, -17, 337, -1000, 326, 3617, -1000, -1000, -1000, -1000, + 854, -1000, 4989, -1000, -1000, 702, 696, -1000, -1000, -1000, + 896, 652, -1000, 1602, -1000, -1000, 113, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 10346, 10346, 10346, 10346, 10346, + 873, 404, 451, 10346, 10346, 846, -1000, 700, -1000, -1000, + 681, 15987, 15987, -1000, 15987, 873, -1000, 451, 451, 15987, + 451, 13670, 15987, 15987, 11666, -1000, 150, 15987, -1000, 549, + -1000, 195, -1000, -103, 148, -1000, 148, 553, 550, -1000, + 700, 647, -1000, 216, 15987, 16317, 883, 865, -1000, -1000, + 372, 372, 372, 372, 19, 546, -1000, 372, 372, 928, + -1000, 700, -1000, 694, 124, -1000, -1000, -1000, 543, 518, + -1000, 518, 518, 158, 150, -1000, 449, 213, 400, -1000, + 56, 15987, 257, 841, -1000, 838, -1000, -1000, -1000, -1000, + -1000, 35, 4989, 3274, 515, -1000, -1000, 9356, 9356, -1000, + -1000, -1000, -1000, 546, 44, -176, -1000, -1000, -1000, 16647, + 627, 546, 15987, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 312, -1000, -1000, 16317, -1000, -1000, 375, -1000, -1000, 498, + -1000, 15987, -1000, -1000, 596, 451, 604, -1000, 799, -170, + -185, 587, -1000, -1000, -1000, 701, -1000, -1000, 35, 811, + -173, -1000, 797, -1000, 15987, -1000, 32, -1000, -174, 487, + 30, -180, 725, 700, -186, 722, -1000, 923, 9686, -1000, + -1000, 925, 177, 177, 372, 546, -1000, -1000, -1000, 62, + 368, -1000, -1000, -1000, -1000, -1000, -1000, } var yyPgo = [...]int{ - 0, 1202, 55, 407, 1201, 1196, 1195, 1192, 1190, 1187, - 1186, 1185, 1184, 1183, 1182, 1181, 1169, 1168, 1167, 1164, - 1163, 1161, 1159, 1157, 1155, 1153, 96, 1151, 1150, 1149, - 66, 1147, 81, 1138, 1137, 40, 918, 41, 45, 827, - 1136, 26, 71, 46, 1135, 35, 1134, 1133, 88, 1131, - 1130, 57, 1126, 1124, 92, 1122, 73, 1121, 11, 43, - 1120, 1119, 1118, 1117, 70, 329, 1116, 1115, 16, 1114, - 1108, 84, 1107, 50, 7, 14, 13, 22, 1106, 906, - 25, 1105, 58, 1104, 1100, 1097, 1096, 27, 1095, 64, - 1094, 18, 59, 1093, 9, 78, 33, 21, 5, 75, - 63, 1089, 24, 60, 49, 1087, 1086, 460, 1085, 1084, - 42, 1083, 1082, 28, 1081, 97, 388, 1080, 1079, 1077, - 1076, 52, 0, 489, 137, 69, 1074, 1073, 1072, 1521, - 38, 54, 17, 1071, 53, 20, 37, 1070, 1069, 34, - 1068, 1067, 1061, 1060, 1058, 1057, 1055, 116, 1054, 1053, - 1048, 19, 79, 1046, 1045, 51, 23, 1042, 1038, 1037, - 47, 65, 1033, 1032, 48, 29, 1030, 1029, 1028, 1027, - 1026, 31, 10, 1025, 12, 1024, 15, 1023, 30, 1021, - 4, 1020, 8, 1019, 3, 1017, 6, 44, 1, 1016, - 2, 1015, 1012, 61, 623, 76, 1008, 77, + 0, 1206, 85, 503, 1203, 1201, 1200, 1199, 1198, 1196, + 1193, 1185, 1184, 1183, 1181, 1178, 1173, 1169, 1168, 1167, + 1166, 1162, 1157, 1155, 1149, 1148, 81, 1147, 1146, 1144, + 65, 1143, 63, 1140, 1139, 46, 609, 45, 42, 1289, + 1138, 23, 82, 75, 1136, 35, 1135, 1134, 69, 1133, + 1132, 64, 1131, 1128, 59, 1115, 58, 1112, 21, 73, + 1108, 1107, 1106, 1090, 70, 1103, 1085, 1084, 13, 1083, + 1082, 83, 1081, 52, 5, 12, 11, 18, 1080, 103, + 10, 1078, 50, 1077, 1076, 1075, 1074, 31, 1072, 55, + 1071, 34, 53, 1069, 7, 61, 30, 25, 9, 71, + 56, 1068, 22, 60, 48, 1066, 1065, 550, 1064, 1063, + 40, 1060, 1059, 24, 1058, 91, 401, 1057, 1056, 1055, + 1054, 33, 0, 553, 93, 66, 1052, 1051, 1050, 1555, + 38, 54, 16, 1048, 51, 1510, 41, 1046, 1044, 37, + 1043, 1042, 1041, 1040, 1039, 1038, 1037, 49, 1036, 1035, + 1025, 19, 20, 1020, 1013, 62, 27, 1010, 1005, 971, + 44, 57, 970, 968, 47, 28, 967, 966, 965, 963, + 962, 26, 14, 961, 15, 960, 17, 959, 29, 957, + 4, 956, 6, 955, 3, 954, 8, 43, 1, 953, + 2, 952, 951, 619, 570, 77, 948, 76, } var yyR1 = [...]int{ @@ -2737,48 +2781,48 @@ var yyR1 = [...]int{ 190, 188, 188, 188, 188, 188, 170, 170, 170, 171, 171, 171, 172, 172, 172, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - 187, 187, 181, 179, 179, 180, 180, 13, 18, 18, - 14, 14, 14, 14, 14, 15, 15, 19, 20, 20, + 12, 12, 187, 187, 187, 187, 187, 187, 187, 187, + 187, 187, 187, 187, 181, 179, 179, 180, 180, 13, + 18, 18, 14, 14, 14, 14, 14, 15, 15, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 111, 111, 109, 109, - 112, 112, 110, 110, 110, 113, 113, 113, 114, 114, - 138, 138, 138, 21, 21, 23, 23, 24, 25, 22, - 22, 22, 22, 22, 22, 22, 16, 196, 26, 27, - 27, 28, 28, 28, 32, 32, 32, 30, 30, 31, - 31, 37, 37, 36, 36, 38, 38, 38, 38, 126, - 126, 126, 125, 125, 40, 40, 41, 41, 42, 42, - 43, 43, 43, 43, 57, 57, 94, 94, 96, 96, - 44, 44, 44, 44, 45, 45, 46, 46, 47, 47, - 133, 133, 132, 132, 132, 131, 131, 50, 50, 50, - 52, 51, 51, 51, 51, 53, 53, 55, 55, 54, - 54, 56, 58, 58, 58, 58, 59, 59, 39, 39, - 39, 39, 39, 39, 39, 108, 108, 61, 61, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 72, - 72, 72, 72, 72, 72, 62, 62, 62, 62, 62, - 62, 62, 35, 35, 73, 73, 73, 79, 74, 74, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 20, 20, 20, 20, 20, 20, 20, 20, 111, 111, + 109, 109, 112, 112, 110, 110, 110, 113, 113, 113, + 114, 114, 138, 138, 138, 21, 21, 23, 23, 24, + 25, 22, 22, 22, 22, 22, 22, 22, 16, 196, + 26, 27, 27, 28, 28, 28, 32, 32, 32, 30, + 30, 30, 31, 31, 37, 37, 36, 36, 38, 38, + 38, 38, 126, 126, 126, 125, 125, 40, 40, 41, + 41, 42, 42, 43, 43, 43, 43, 57, 57, 94, + 94, 96, 96, 44, 44, 44, 44, 45, 45, 46, + 46, 47, 47, 133, 133, 132, 132, 132, 131, 131, + 50, 50, 50, 52, 51, 51, 51, 51, 53, 53, + 55, 55, 54, 54, 56, 58, 58, 58, 58, 58, + 59, 59, 39, 39, 39, 39, 39, 39, 39, 108, + 108, 61, 61, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 72, 72, 72, 72, 72, 72, 62, + 62, 62, 62, 62, 62, 62, 35, 35, 73, 73, + 73, 79, 74, 74, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 69, 69, 69, 67, 67, 67, 67, 67, - 67, 67, 67, 67, 67, 67, 67, 67, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 197, 197, 71, 70, 70, 70, - 70, 70, 70, 33, 33, 33, 33, 33, 136, 136, - 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, - 139, 139, 139, 83, 83, 34, 34, 81, 81, 82, - 84, 84, 80, 80, 80, 64, 64, 64, 64, 64, - 64, 64, 64, 66, 66, 66, 85, 85, 86, 86, - 87, 87, 88, 88, 89, 90, 90, 90, 91, 91, - 91, 91, 92, 92, 92, 63, 63, 63, 63, 63, - 63, 93, 93, 93, 93, 97, 97, 75, 75, 77, - 77, 76, 78, 98, 98, 102, 99, 99, 103, 103, - 103, 103, 101, 101, 101, 128, 128, 128, 106, 106, - 115, 115, 116, 116, 107, 107, 117, 117, 117, 117, - 117, 117, 117, 117, 117, 117, 118, 118, 118, 119, - 119, 120, 120, 120, 127, 127, 123, 123, 124, 124, - 129, 129, 130, 130, 121, 121, 121, 121, 121, 121, + 65, 65, 65, 65, 65, 65, 69, 69, 69, 69, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 197, + 197, 71, 70, 70, 70, 70, 70, 70, 70, 33, + 33, 33, 33, 33, 136, 136, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 83, + 83, 34, 34, 81, 81, 82, 84, 84, 80, 80, + 80, 64, 64, 64, 64, 64, 64, 64, 64, 66, + 66, 66, 85, 85, 86, 86, 87, 87, 88, 88, + 89, 90, 90, 90, 91, 91, 91, 91, 92, 92, + 92, 63, 63, 63, 63, 63, 63, 93, 93, 93, + 93, 97, 97, 75, 75, 77, 77, 76, 78, 98, + 98, 102, 99, 99, 103, 103, 103, 103, 101, 101, + 101, 128, 128, 128, 106, 106, 115, 115, 116, 116, + 107, 107, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 118, 118, 118, 119, 119, 120, 120, 120, + 127, 127, 123, 123, 124, 124, 129, 129, 130, 130, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, @@ -2790,7 +2834,7 @@ var yyR1 = [...]int{ 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 121, 121, 121, 121, 121, 121, 121, 121, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, @@ -2807,7 +2851,8 @@ var yyR1 = [...]int{ 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, - 193, 194, 134, 135, 135, 135, + 122, 122, 122, 122, 122, 122, 122, 193, 194, 134, + 135, 135, 135, } var yyR2 = [...]int{ @@ -2833,49 +2878,49 @@ var yyR2 = [...]int{ 1, 3, 2, 3, 1, 10, 11, 11, 12, 3, 3, 1, 1, 2, 2, 2, 0, 1, 3, 1, 2, 3, 1, 1, 1, 6, 7, 7, 7, 7, - 4, 5, 7, 5, 5, 5, 12, 7, 5, 9, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 7, 1, 3, 8, 8, 3, 3, 5, - 4, 6, 5, 4, 4, 3, 2, 3, 4, 4, - 3, 4, 4, 4, 4, 4, 4, 3, 2, 3, - 3, 2, 3, 4, 3, 7, 5, 4, 2, 4, - 4, 3, 3, 5, 2, 3, 1, 1, 0, 1, - 1, 1, 0, 2, 2, 0, 2, 2, 0, 2, - 0, 1, 1, 2, 1, 1, 2, 1, 1, 2, - 2, 2, 2, 2, 3, 3, 2, 0, 2, 0, - 2, 1, 2, 2, 0, 1, 1, 0, 1, 0, - 1, 0, 1, 1, 3, 1, 2, 3, 5, 0, - 1, 2, 1, 1, 0, 2, 1, 3, 1, 1, - 1, 3, 1, 3, 3, 7, 1, 3, 1, 3, - 4, 4, 4, 3, 2, 4, 0, 1, 0, 2, - 0, 1, 0, 1, 2, 1, 1, 1, 2, 2, - 1, 2, 3, 2, 3, 2, 2, 2, 1, 1, - 3, 3, 0, 5, 5, 5, 0, 2, 1, 3, - 3, 2, 3, 1, 2, 0, 3, 1, 1, 3, - 3, 4, 4, 5, 3, 4, 5, 6, 2, 1, - 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, - 1, 1, 0, 2, 1, 1, 1, 3, 1, 3, - 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, + 4, 5, 4, 4, 7, 5, 5, 5, 12, 7, + 5, 9, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 7, 1, 3, 8, 8, 3, + 3, 5, 4, 6, 5, 4, 4, 3, 2, 3, + 4, 4, 3, 4, 4, 4, 4, 4, 4, 3, + 2, 3, 3, 2, 3, 4, 3, 7, 5, 4, + 2, 4, 4, 3, 3, 5, 2, 3, 1, 1, + 0, 1, 1, 1, 0, 2, 2, 0, 2, 2, + 0, 2, 0, 1, 1, 2, 1, 1, 2, 1, + 1, 2, 2, 2, 2, 2, 3, 3, 2, 0, + 2, 0, 2, 1, 2, 2, 0, 1, 1, 0, + 1, 1, 0, 1, 0, 1, 1, 3, 1, 2, + 3, 5, 0, 1, 2, 1, 1, 0, 2, 1, + 3, 1, 1, 1, 3, 1, 3, 3, 7, 1, + 3, 1, 3, 4, 4, 4, 3, 2, 4, 0, + 1, 0, 2, 0, 1, 0, 1, 2, 1, 1, + 1, 2, 2, 1, 2, 3, 2, 3, 2, 2, + 2, 1, 1, 3, 3, 0, 5, 4, 5, 5, + 0, 2, 1, 3, 3, 2, 3, 1, 2, 0, + 3, 1, 1, 3, 3, 4, 4, 5, 3, 4, + 5, 6, 2, 1, 2, 1, 2, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 0, 2, 1, 1, + 1, 3, 1, 3, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 3, 1, 1, - 1, 1, 4, 5, 6, 4, 4, 6, 6, 6, - 8, 8, 8, 8, 9, 7, 5, 4, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 8, 8, 0, 2, 3, 4, 4, 4, - 4, 4, 4, 0, 3, 4, 7, 3, 1, 1, - 2, 3, 3, 1, 2, 2, 1, 2, 1, 2, - 2, 1, 2, 0, 1, 0, 2, 1, 2, 4, - 0, 2, 1, 3, 5, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 2, 2, 0, 3, 0, 2, - 0, 3, 1, 3, 2, 0, 1, 1, 0, 2, - 4, 4, 0, 2, 4, 2, 1, 3, 5, 4, - 6, 1, 3, 3, 5, 0, 5, 1, 3, 1, - 2, 3, 1, 1, 3, 3, 1, 3, 3, 3, - 3, 3, 1, 2, 1, 1, 1, 1, 1, 1, - 0, 2, 0, 3, 0, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, - 1, 0, 1, 1, 0, 2, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, + 2, 3, 1, 1, 1, 1, 4, 5, 5, 6, + 4, 4, 6, 6, 6, 8, 8, 8, 8, 9, + 8, 5, 4, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 8, 8, 0, + 2, 3, 4, 4, 4, 4, 4, 4, 4, 0, + 3, 4, 7, 3, 1, 1, 2, 3, 3, 1, + 2, 2, 1, 2, 1, 2, 2, 1, 2, 0, + 1, 0, 2, 1, 2, 4, 0, 2, 1, 3, + 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 0, 3, 0, 2, 0, 3, 1, 3, + 2, 0, 1, 1, 0, 2, 4, 4, 0, 2, + 4, 2, 1, 3, 5, 4, 6, 1, 3, 3, + 5, 0, 5, 1, 3, 1, 2, 3, 1, 1, + 3, 3, 1, 3, 3, 3, 3, 3, 1, 2, + 1, 1, 1, 1, 1, 1, 0, 2, 0, 3, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, + 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -2904,333 +2949,338 @@ var yyR2 = [...]int{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, } var yyChk = [...]int{ -1000, -191, -1, -2, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -19, -20, -21, -23, -24, -25, -22, -16, -3, -4, 6, 7, -29, 9, 10, 30, - -17, 115, 116, 118, 117, 150, 119, 143, 50, 164, - 165, 167, 168, 25, 144, 145, 148, 149, 31, 32, - 121, -193, 8, 249, 54, -192, 347, -87, 15, -28, + -17, 116, 117, 119, 118, 151, 120, 144, 51, 165, + 166, 168, 169, 25, 145, 146, 149, 150, 31, 32, + 122, -193, 8, 250, 55, -192, 348, -87, 15, -28, 5, -26, -196, -26, -26, -26, -26, -26, -167, -169, - 54, 90, -120, 125, 72, 241, 122, 123, 129, -123, - 57, -122, 259, 136, 291, 292, 164, 175, 169, 196, - 188, 260, 293, 137, 186, 189, 228, 135, 294, 216, - 223, 66, 167, 237, 295, 146, 184, 180, 296, 268, - 178, 27, 297, 225, 201, 298, 264, 179, 224, 121, - 299, 139, 133, 300, 202, 206, 301, 229, 302, 303, - 304, 173, 174, 305, 231, 200, 134, 33, 261, 35, - 154, 232, 204, 306, 199, 195, 307, 308, 309, 310, - 198, 172, 194, 39, 208, 207, 209, 227, 191, 311, - 312, 313, 140, 314, 181, 18, 315, 316, 317, 318, - 319, 235, 149, 320, 152, 321, 322, 323, 324, 325, - 326, 226, 203, 205, 130, 156, 263, 327, 233, 177, - 328, 141, 153, 148, 236, 142, 329, 330, 331, 332, - 333, 334, 335, 168, 336, 337, 338, 339, 163, 230, - 239, 38, 213, 340, 171, 132, 341, 165, 160, 218, - 192, 155, 342, 343, 182, 183, 197, 170, 193, 166, - 157, 150, 344, 238, 214, 265, 190, 187, 161, 345, - 158, 159, 346, 219, 220, 162, 262, 234, 185, 215, - -107, 125, 220, 127, 123, 123, 124, 125, 241, 122, - 123, -54, -129, 57, -122, 125, 123, 108, 189, 228, - 115, 217, 225, 124, 33, 226, 156, -138, 123, -109, - 216, 219, 220, 162, 57, 230, 229, 221, -129, 166, - -134, -134, -134, -134, -134, 218, 218, -134, -2, -91, - 17, 16, -5, -3, -193, 6, 20, 21, -32, 40, - 41, -27, -38, 99, -39, -129, -60, 74, -65, 29, - 57, -122, 23, -64, -61, -80, -78, -79, 108, 109, - 110, 97, 98, 105, 75, 111, -69, -67, -68, -70, - 59, 58, 67, 60, 61, 62, 63, 68, 69, 70, - -123, -76, -193, 44, 45, 250, 251, 252, 253, 258, - 254, 77, 34, 240, 248, 247, 246, 244, 245, 242, - 243, 256, 257, 128, 241, 103, 249, -107, -107, 11, - -48, -49, -54, -56, -129, -99, -137, 166, -103, 230, - 229, -124, -101, -123, -121, 228, 189, 227, 120, 266, - 73, 22, 24, 211, 76, 108, 16, 77, 107, 250, - 115, 48, 267, 242, 243, 240, 252, 253, 241, 217, - 29, 10, 269, 25, 144, 21, 101, 117, 80, 81, - 147, 23, 145, 70, 272, 19, 51, 11, 13, 273, - 274, 14, 128, 127, 92, 124, 46, 8, 111, 26, - 89, 42, 275, 28, 276, 277, 278, 279, 44, 90, - 17, 244, 245, 31, 280, 258, 151, 103, 49, 36, - 74, 281, 282, 68, 283, 71, 52, 72, 15, 47, - 284, 285, 286, 287, 91, 118, 249, 45, 288, 122, - 6, 255, 30, 143, 43, 289, 123, 79, 256, 257, - 126, 69, 5, 129, 32, 9, 50, 53, 246, 247, - 248, 34, 78, 12, 290, -168, 90, -161, 57, -54, - 124, -54, 249, -116, 128, -116, -116, 123, -54, 115, - 117, 120, 52, -18, -54, -115, 128, 57, -115, -115, - -115, -54, 112, -54, 57, 30, -135, -193, -124, 241, - 57, 156, 123, 157, 125, -135, -135, -135, -135, 160, - 161, -135, -112, -111, 223, 224, 218, 222, 12, 161, - 218, 159, -135, -134, -134, -194, 56, -92, 19, 31, - -39, -129, -88, -89, -39, -87, -2, -26, 36, -30, - 21, 65, 11, -126, 73, 72, 89, -125, 22, -123, - 59, 112, -39, -62, 92, 74, 90, 91, 76, 94, - 93, 104, 97, 98, 99, 100, 101, 102, 103, 95, - 96, 107, 82, 83, 84, 85, 86, 87, 88, -108, - -193, -79, -193, 113, 114, -65, -65, -65, -65, -65, - -65, -65, -65, -193, -2, -74, -39, -193, -193, -193, - -193, -193, -193, -193, -193, -193, -83, -39, -193, -197, - -71, -193, -197, -71, -197, -71, -197, -193, -197, -71, - -197, -71, -197, -197, -71, -193, -193, -193, -193, -193, + 55, 91, -120, 126, 73, 242, 123, 124, 130, -123, + 58, -122, 260, 137, 292, 293, 165, 176, 170, 197, + 189, 261, 294, 138, 187, 190, 229, 136, 295, 217, + 224, 67, 168, 238, 296, 147, 185, 181, 297, 269, + 179, 27, 298, 226, 202, 299, 265, 180, 225, 122, + 300, 140, 134, 301, 203, 207, 302, 230, 303, 304, + 305, 174, 175, 306, 232, 201, 135, 33, 262, 36, + 155, 233, 205, 307, 200, 196, 308, 309, 310, 311, + 199, 173, 195, 40, 209, 208, 210, 228, 192, 312, + 313, 314, 141, 315, 182, 18, 316, 317, 318, 319, + 320, 236, 150, 321, 153, 322, 323, 324, 325, 326, + 327, 227, 204, 206, 131, 157, 264, 328, 234, 178, + 329, 142, 154, 149, 237, 143, 330, 331, 332, 333, + 334, 335, 336, 169, 337, 338, 339, 340, 164, 231, + 240, 39, 214, 341, 172, 133, 342, 166, 161, 219, + 193, 156, 343, 344, 183, 184, 198, 171, 194, 167, + 158, 151, 345, 239, 215, 266, 191, 188, 162, 346, + 159, 160, 347, 220, 221, 163, 263, 235, 186, 216, + -107, 126, 242, 123, 221, 128, 124, 124, 125, 126, + 242, 123, 124, -54, -129, 58, -122, 126, 124, 109, + 190, 229, 116, 218, 226, 125, 33, 227, 157, -138, + 124, -109, 217, 220, 221, 163, 58, 231, 230, 222, + -129, 167, -134, -134, -134, -134, -134, 219, 219, -134, + -2, -91, 17, 16, -5, -3, -193, 6, 20, 21, + -32, 41, 42, -27, -38, 100, -39, -129, -60, 75, + -65, 29, 58, -122, 23, -64, -61, -80, -78, -79, + 109, 110, 111, 98, 99, 106, 76, 112, -69, -67, + -68, -70, 60, 59, 68, 61, 62, 63, 64, 69, + 70, 71, -123, -76, -193, 45, 46, 251, 252, 253, + 254, 259, 255, 78, 35, 241, 249, 248, 247, 245, + 246, 243, 244, 257, 258, 129, 242, 123, 104, 250, + -107, -107, 11, -48, -49, -54, -56, -129, -99, -137, + 167, -103, 231, 230, -124, -101, -123, -121, 229, 190, + 228, 121, 267, 74, 22, 24, 212, 77, 109, 16, + 78, 108, 251, 116, 49, 268, 243, 244, 241, 253, + 254, 242, 218, 29, 10, 270, 25, 145, 21, 34, + 102, 118, 81, 82, 148, 23, 146, 71, 273, 19, + 52, 11, 13, 274, 275, 14, 129, 128, 93, 125, + 47, 8, 112, 26, 90, 43, 276, 28, 277, 278, + 279, 280, 45, 91, 17, 245, 246, 31, 281, 259, + 152, 104, 50, 37, 75, 282, 283, 69, 284, 72, + 53, 73, 15, 48, 285, 286, 287, 288, 92, 119, + 250, 46, 289, 123, 6, 256, 30, 144, 44, 290, + 124, 80, 257, 258, 127, 70, 5, 130, 32, 9, + 51, 54, 247, 248, 249, 35, 79, 12, 291, -168, + 91, -161, 58, -54, 125, -54, 250, -116, 129, -116, + -116, 124, -54, 58, 58, 116, 118, 121, 53, -18, + -54, -115, 129, 58, -115, -115, -115, -54, 113, -54, + 58, 30, -113, 91, 12, 242, 58, 157, 124, 158, + 126, -135, -193, -124, -135, -135, -135, 161, 162, -135, + -112, -111, 224, 225, 219, 223, 12, 162, 219, 160, + -135, -134, -134, -194, 57, -92, 19, 31, -39, -129, + -88, -89, -39, -87, -2, -26, 37, -30, 21, 34, + 66, 11, -126, 74, 73, 90, -125, 22, -123, 60, + 113, -39, -62, 93, 75, 91, 92, 77, 95, 94, + 105, 98, 99, 100, 101, 102, 103, 104, 96, 97, + 108, 83, 84, 85, 86, 87, 88, 89, -108, -193, + -79, -193, 114, 115, -65, -65, -65, -65, -65, -65, + -65, -65, -193, -2, -74, -39, -193, -193, -193, -193, + -193, -193, -193, -193, -193, -83, -39, -193, -197, -71, + -193, -197, -71, -197, -71, -197, -193, -197, -71, -197, + -71, -197, -197, -71, -193, -193, -193, -193, -193, -193, -193, -55, 26, -54, -41, -42, -43, -44, -57, -79, - -193, -54, -54, -48, -195, 55, 11, 53, -195, 55, - 112, 55, -99, 166, -100, -104, 231, 233, 82, -128, - -123, 59, 29, 30, 56, 55, -54, -140, -143, -145, - -144, -146, -141, -142, 186, 187, 108, 190, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 201, 30, 146, - 182, 183, 184, 185, 202, 203, 204, 205, 206, 207, - 208, 209, 169, 188, 260, 170, 171, 172, 173, 174, - 175, 177, 178, 179, 180, 181, 57, -135, 125, 57, - 74, 57, -54, -54, -135, 158, 158, 123, 123, 163, - -54, 55, 126, -48, 23, 52, -54, 57, 57, -130, - -129, -121, -135, -135, -135, -135, -135, -54, -135, -135, - -135, -135, 11, -110, 11, 92, -39, -114, 90, 52, - 9, 92, 55, 18, 112, 55, -90, 24, 25, -91, - -194, -32, -66, -123, 60, 63, -31, 43, -54, -39, - -39, -72, 68, 74, 69, 70, -125, 99, -130, -124, - -121, -65, -73, -76, -79, 64, 92, 90, 91, 76, - -65, -65, -65, -65, -65, -65, -65, -65, -65, -65, - -65, -65, -65, -65, -65, -136, 57, 59, 57, -64, - -64, -123, -37, 21, -36, -38, -194, 55, -194, -2, - -36, -36, -39, -39, -80, 59, -36, -80, 59, -36, - -36, -30, -81, -82, 78, -80, -123, -129, -194, -65, - -123, -123, -36, -37, -36, -36, -95, 152, -54, 30, - 55, -50, -52, -51, -53, 42, 46, 48, 43, 44, - 45, 49, -133, 22, -41, -193, -132, 152, -131, 22, - -129, 59, -95, 53, -41, -54, -41, -56, -129, 99, - -103, -100, 55, 232, 234, 235, 52, 71, -39, -152, - 107, -170, -171, -172, -124, 59, 60, -161, -162, -163, - -173, 138, -178, 130, 132, 129, -164, 139, 124, 28, - 56, -157, 68, 74, -153, 214, -147, 54, -147, -147, - -147, -147, -151, 189, -151, -151, -151, 54, 54, -147, - -147, -147, -155, 54, -155, -155, -156, 54, -156, -127, - 53, -54, -135, 23, -135, -117, 120, 117, 118, -181, - 116, 211, 189, 66, 29, 15, 250, 152, 265, 57, - 153, -54, -54, -54, -54, -54, 120, 117, -54, -54, - -54, -135, -54, -113, 90, 12, -129, -129, 59, -54, - 38, -39, -39, -130, -89, -92, -106, 19, 11, 34, - 34, -36, 68, 69, 70, 112, -193, -73, -65, -65, - -65, -35, 147, 73, -194, -194, -36, 55, -39, -194, - -194, -194, 55, 53, 22, 11, 11, -194, 11, 11, - -194, -194, -36, -84, -82, 80, -39, -194, 112, -194, - 55, 55, -194, -194, -194, -194, -63, 30, 34, -2, - -193, -193, -98, -102, -80, -42, -43, -43, -42, -43, - 42, 42, 42, 47, 42, 47, 42, -51, -129, -194, - -58, 50, 127, 51, -193, -131, -59, 12, -41, -59, - -59, 112, -104, -105, 236, 233, 239, 57, 59, 55, - -172, 82, 54, 57, 28, -164, -164, -165, 57, -165, - 28, -149, 29, 68, -154, 215, 60, -151, -151, -152, - 30, -152, -152, -152, -160, 59, -160, 60, 60, 52, - -123, -135, -134, -187, 135, 131, 138, 139, 133, 57, - 124, 28, 130, 132, 152, 129, -187, -118, -119, 126, - 22, 124, 28, 152, -186, 53, 158, 211, 158, 126, - -135, -110, 59, -39, 39, 112, -54, -40, 11, 99, - -124, -37, -35, 73, -65, -65, -194, -38, -139, 108, - 186, 146, 184, 180, 200, 191, 213, 182, 214, -136, - -139, -65, -65, -65, -65, 259, -87, 81, -39, 79, - -124, -65, -65, -97, 52, -98, -75, -77, -76, -193, - -2, -93, -123, -96, -123, -59, 55, 82, -46, -45, - 52, 53, -47, 52, -45, 42, 42, 124, 124, 124, - -96, -87, -39, -59, 233, 237, 238, -171, -172, -175, - -174, -123, -178, -165, -165, 54, -150, 52, -65, 56, - -152, -152, 57, 108, 56, 55, 56, 55, 56, 55, - -54, -134, -134, -54, -134, -123, -184, 262, -185, 57, - -123, -123, -123, -54, -113, -59, -41, -194, -65, -194, - -147, -147, -147, -156, -147, 174, -147, 174, -194, -194, - 19, 19, 19, 19, -193, -34, 255, -39, 55, 55, - 27, -97, 55, -194, -194, -194, 55, 112, -194, 55, - -87, -102, -39, -39, 54, -39, -193, -193, -193, -194, - -91, 56, 55, -147, -94, -123, -158, 211, 9, -151, - 59, -151, 60, 60, -135, 26, -183, -182, -124, 54, - 53, -85, 13, -151, 57, -65, -65, -65, -65, -65, - -194, 59, -65, -65, 28, -77, 34, -2, -193, -123, - -123, -123, -91, -94, -94, -94, -94, -132, -177, -176, - 53, 134, 66, -174, 56, 55, -159, 130, 28, 129, - -68, -152, -152, 56, 56, -193, 55, 82, -94, -54, - -86, 14, 16, -194, -194, -194, -194, -33, 92, 262, - -194, -194, 9, -75, -2, 112, 56, -194, -194, -194, - -58, -176, 57, -166, 82, 59, 141, -123, -148, 66, - 28, 28, -179, -180, 152, -182, -172, 56, -39, -74, - -194, 260, 49, 263, -98, -194, -123, 60, -54, 59, - -194, 55, -123, -186, 39, 261, 264, 54, -180, 34, - -184, 39, -94, 154, 262, 56, 155, 263, -189, -190, - 52, -193, 264, -190, 52, 10, 9, -65, 151, -188, - 142, 137, 140, 30, -188, -194, -194, 136, 29, 68, + -193, -54, -54, -48, -195, 56, 11, 54, -195, 56, + 113, 56, -99, 167, -100, -104, 232, 234, 83, -128, + -123, 60, 29, 30, 57, 56, -54, -140, -143, -145, + -144, -146, -141, -142, 187, 188, 109, 191, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 202, 30, 147, + 183, 184, 185, 186, 203, 204, 205, 206, 207, 208, + 209, 210, 170, 189, 261, 171, 172, 173, 174, 175, + 176, 178, 179, 180, 181, 182, 58, -135, 126, 58, + 75, 58, -54, -54, -135, -135, -135, 159, 159, 124, + 124, 164, -54, 56, 127, -48, 23, 53, -54, 58, + 58, -130, -129, -121, -135, -113, 60, -39, -135, -135, + -135, -54, -135, -135, -135, -135, 11, -110, 11, 93, + -39, -114, 91, 53, 9, 93, 56, 18, 113, 56, + -90, 24, 25, -91, -194, -32, -66, -123, 61, 64, + -31, 44, -54, -39, -39, -72, 69, 75, 70, 71, + -125, 100, -130, -124, -121, -65, -73, -76, -79, 65, + 93, 91, 92, 77, -65, -65, -65, -65, -65, -65, + -65, -65, -65, -65, -65, -65, -65, -65, -65, -136, + 58, 60, 58, -64, -64, -123, -37, 21, 34, -36, + -38, -194, 56, -194, -2, -36, -36, -39, -39, -80, + 60, -36, -80, 60, -36, -36, -30, -81, -82, 79, + -80, -123, -129, -194, -65, -123, -123, -36, -37, -37, + -36, -36, -95, 153, -54, 30, 56, -50, -52, -51, + -53, 43, 47, 49, 44, 45, 46, 50, -133, 22, + -41, -193, -132, 153, -131, 22, -129, 60, -95, 54, + -41, -54, -41, -56, -129, 100, -103, -100, 56, 233, + 235, 236, 53, 72, -39, -152, 108, -170, -171, -172, + -124, 60, 61, -161, -162, -163, -173, 139, -178, 131, + 133, 130, -164, 140, 125, 28, 57, -157, 69, 75, + -153, 215, -147, 55, -147, -147, -147, -147, -151, 190, + -151, -151, -151, 55, 55, -147, -147, -147, -155, 55, + -155, -155, -156, 55, -156, -127, 54, -54, -135, 23, + -135, -117, 121, 118, 119, -181, 117, 212, 190, 67, + 29, 15, 251, 153, 266, 58, 154, -54, -54, -54, + -54, -54, 121, 118, -54, -54, -54, -135, -54, -113, + -129, -129, 60, -54, 39, -39, -39, -130, -89, -92, + -106, 19, 11, 35, 35, -36, 69, 70, 71, 113, + -193, -73, -65, -65, -65, -35, 148, 74, -194, -194, + -36, -36, 56, -39, -194, -194, -194, 56, 54, 22, + 11, 11, -194, 11, 11, -194, -194, -36, -84, -82, + 81, -39, -194, 113, -194, 56, 56, -194, -194, -194, + -194, -194, -63, 30, 35, -2, -193, -193, -98, -102, + -80, -42, -43, -43, -42, -43, 43, 43, 43, 48, + 43, 48, 43, -51, -129, -194, -58, 51, 128, 52, + -193, -131, -59, 12, -41, -59, -59, 113, -104, -105, + 237, 234, 240, 58, 60, 56, -172, 83, 55, 58, + 28, -164, -164, -165, 58, -165, 28, -149, 29, 69, + -154, 216, 61, -151, -151, -152, 30, -152, -152, -152, + -160, 60, -160, 61, 61, 53, -123, -135, -134, -187, + 136, 132, 139, 140, 134, 58, 125, 28, 131, 133, + 153, 130, -187, -118, -119, 127, 22, 125, 28, 153, + -186, 54, 159, 212, 159, 127, -135, -110, 40, 113, + -54, -40, 11, 100, -124, -37, -35, 74, -65, -65, + -194, -194, -38, -139, 109, 187, 147, 185, 181, 201, + 192, 214, 183, 215, -136, -139, -65, -65, -65, -65, + 260, -87, 82, -39, 80, -124, -65, -65, -97, 53, + -98, -75, -77, -76, -193, -2, -93, -123, -96, -123, + -59, 56, 83, -46, -45, 53, 54, -47, 53, -45, + 43, 43, 125, 125, 125, -96, -87, -39, -59, 234, + 238, 239, -171, -172, -175, -174, -123, -178, -165, -165, + 55, -150, 53, -65, 57, -152, -152, 58, 109, 57, + 56, 57, 56, 57, 56, -54, -134, -134, -54, -134, + -123, -184, 263, -185, 58, -123, -123, -123, -54, -113, + -59, -41, -194, -65, -194, -147, -147, -147, -156, -147, + 175, -147, 175, -194, -194, 19, 19, 19, 19, -193, + -34, 256, -39, 56, 56, 27, -97, 56, -194, -194, + -194, 56, 113, -194, 56, -87, -102, -39, -39, 55, + -39, -193, -193, -193, -194, -91, 57, 56, -147, -94, + -123, -158, 212, 9, -151, 60, -151, 61, 61, -135, + 26, -183, -182, -124, 55, 54, -85, 13, -151, 58, + -65, -65, -65, -65, -65, -91, 60, -65, -65, 28, + -77, 35, -2, -193, -123, -123, -123, -91, -94, -94, + -194, -94, -94, -132, -177, -176, 54, 135, 67, -174, + 57, 56, -159, 131, 28, 130, -68, -152, -152, 57, + 57, -193, 56, 83, -94, -54, -86, 14, 16, -194, + -194, -194, -194, -33, 93, 263, -194, -194, -194, 9, + -75, -2, 113, 57, -194, -194, -194, -58, -176, 58, + -166, 83, 60, 142, -123, -148, 67, 28, 28, -179, + -180, 153, -182, -172, 57, -39, -74, -194, 261, 50, + 264, -98, -194, -123, 61, -54, 60, -194, 56, -123, + -186, 40, 262, 265, 55, -180, 35, -184, 40, -94, + 155, 263, 57, 156, 264, -189, -190, 53, -193, 265, + -190, 53, 10, 9, -65, 152, -188, 143, 138, 141, + 30, -188, -194, -194, 137, 29, 69, } var yyDef = [...]int{ 23, -2, 2, -2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 560, 0, 317, 317, 317, 317, 317, 317, - 0, 631, 614, 0, 0, 0, 0, -2, 304, 305, - 0, 307, 308, 932, 932, 932, 932, 932, 0, 0, - 932, 0, 35, 36, 930, 1, 3, 568, 0, 0, - 321, 324, 319, 0, 614, 614, 0, 0, 65, 66, - 0, 0, 0, 919, 0, 612, 612, 612, 632, 633, - 636, 637, 761, 762, 763, 764, 765, 766, 767, 768, - 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, - 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, - 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, - 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, - 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, - 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, - 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, - 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, - 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, - 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, - 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, - 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, - 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, - 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, - 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, - 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, - 0, 0, 0, 615, 0, 610, 0, 610, 610, 610, - 0, 256, 389, 640, 641, 919, 0, 0, 0, 933, - 0, 933, 268, 933, 933, 271, 933, 0, 933, 0, - 278, 0, 0, 284, 933, 301, 302, 289, 303, 306, - 309, 310, 311, 312, 313, 932, 932, 316, 29, 572, - 0, 0, 560, 31, 0, 317, 322, 323, 327, 325, - 326, 318, 0, 335, 339, 0, 398, 0, 403, 405, - -2, -2, 0, 440, 441, 442, 443, 444, 0, 0, - 0, 0, 0, 0, 0, 0, 468, 469, 470, 471, - 545, 546, 547, 548, 549, 550, 551, 552, 407, 408, - 542, 592, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 533, 0, 504, 504, 504, 504, 504, 504, 504, - 504, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 44, 46, 389, 50, 0, 908, 596, -2, - -2, 0, 0, 638, 639, -2, 774, -2, 644, 645, - 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, - 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, - 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, - 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, - 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, - 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, - 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, - 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, - 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, - 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, - 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, - 756, 757, 758, 759, 760, 0, 0, 84, 0, 82, - 0, 933, 0, 0, 0, 0, 0, 0, 933, 0, - 0, 0, 0, 247, 0, 0, 0, 0, 0, 0, - 0, 255, 0, 257, 933, 933, 260, 934, 935, 933, - 933, 933, 0, 933, 933, 267, 269, 270, 272, 933, - 933, 274, 0, 292, 290, 291, 286, 287, 0, 298, - 281, 282, 285, 314, 315, 30, 931, 24, 0, 0, - 569, 0, 561, 562, 565, 568, 29, 324, 0, 329, - 328, 320, 0, 336, 0, 0, 0, 340, 0, 342, - 343, 0, 401, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 425, 426, 427, 428, 429, 430, 431, 404, - 0, 418, 0, 0, 0, 460, 461, 462, 463, 464, - 465, 466, 0, 331, 29, 0, 438, 0, 0, 0, - 0, 0, 0, 0, 0, 327, 0, 534, 0, 488, - 496, 0, 489, 497, 490, 498, 491, 0, 492, 499, - 493, 500, 494, 495, 501, 0, 0, 0, 331, 0, - 0, 48, 0, 388, 0, 346, 348, 349, 350, -2, - 0, 372, -2, 0, 0, 0, 42, 43, 0, 0, - 0, 0, 51, 908, 53, 54, 0, 0, 0, 162, - 605, 606, 607, 603, 206, 0, 0, 150, 146, 90, + 21, 22, 566, 0, 319, 319, 319, 319, 319, 319, + 0, 637, 620, 0, 0, 0, 0, -2, 306, 307, + 0, 309, 310, 939, 939, 939, 939, 939, 0, 0, + 939, 0, 35, 36, 937, 1, 3, 574, 0, 0, + 323, 326, 321, 0, 620, 620, 0, 0, 65, 66, + 0, 0, 0, 926, 0, 618, 618, 618, 638, 639, + 642, 643, 768, 769, 770, 771, 772, 773, 774, 775, + 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, + 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, + 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, + 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, + 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, + 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, + 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, + 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, + 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, + 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, + 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, + 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, + 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, + 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, + 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, + 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, + 0, 0, 0, 0, 0, 621, 0, 616, 0, 616, + 616, 616, 0, 258, 392, 646, 647, 926, 0, 0, + 0, 297, 0, 940, 270, 940, 940, 273, 940, 0, + 940, 0, 280, 0, 0, 286, 940, 303, 304, 291, + 305, 308, 311, 312, 313, 314, 315, 939, 939, 318, + 29, 578, 0, 0, 566, 31, 0, 319, 324, 325, + 329, 327, 328, 320, 0, 338, 342, 0, 402, 0, + 407, 409, -2, -2, 0, 444, 445, 446, 447, 448, + 0, 0, 0, 0, 0, 0, 0, 0, 472, 473, + 474, 475, 551, 552, 553, 554, 555, 556, 557, 558, + 411, 412, 548, 598, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 539, 0, 509, 509, 509, 509, 509, + 509, 509, 509, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 44, 46, 392, 50, 0, + 915, 602, -2, -2, 0, 0, 644, 645, -2, 781, + -2, 650, 651, 652, 653, 654, 655, 656, 657, 658, + 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, + 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, + 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, + 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, + 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, + 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, + 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, + 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, + 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, + 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, + 759, 760, 761, 762, 763, 764, 765, 766, 767, 0, + 0, 84, 0, 82, 0, 940, 0, 0, 0, 0, + 0, 0, 940, 940, 940, 0, 0, 0, 0, 249, + 0, 0, 0, 0, 0, 0, 0, 257, 0, 259, + 940, 297, 262, 0, 0, 940, 940, 940, 0, 940, + 940, 269, 941, 942, 271, 272, 274, 940, 940, 276, + 0, 294, 292, 293, 288, 289, 0, 300, 283, 284, + 287, 316, 317, 30, 938, 24, 0, 0, 575, 0, + 567, 568, 571, 574, 29, 326, 0, 332, 330, 331, + 322, 0, 339, 0, 0, 0, 343, 0, 345, 346, + 0, 405, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 429, 430, 431, 432, 433, 434, 435, 408, 0, + 422, 0, 0, 0, 464, 465, 466, 467, 468, 469, + 470, 0, 334, 29, 0, 442, 0, 0, 0, 0, + 0, 0, 0, 0, 329, 0, 540, 0, 493, 501, + 0, 494, 502, 495, 503, 496, 0, 497, 504, 498, + 505, 499, 500, 506, 0, 0, 0, 334, 334, 0, + 0, 48, 0, 391, 0, 349, 351, 352, 353, -2, + 0, 375, -2, 0, 0, 0, 42, 43, 0, 0, + 0, 0, 51, 915, 53, 54, 0, 0, 0, 162, + 611, 612, 613, 609, 206, 0, 0, 150, 146, 90, 91, 92, 139, 94, 139, 139, 139, 139, 159, 159, 159, 159, 122, 123, 124, 125, 126, 0, 0, 109, 139, 139, 139, 113, 129, 130, 131, 132, 133, 134, 135, 136, 95, 96, 97, 98, 99, 100, 101, 102, - 103, 141, 141, 141, 143, 143, 634, 68, 0, 933, - 0, 933, 80, 0, 220, 0, 0, 0, 0, 0, - 0, 0, 0, 250, 611, 0, 933, 253, 254, 390, - 642, 643, 258, 259, 261, 262, 263, 264, 265, 266, - 273, 277, 0, 295, 0, 0, 279, 280, 0, 0, - 573, 0, 0, 0, 0, 0, 564, 566, 567, 572, - 32, 327, 0, 553, 0, 0, 0, 330, 27, 399, - 400, 402, 419, 0, 421, 423, 341, 337, 0, 543, - -2, 409, 410, 434, 435, 436, 0, 0, 0, 0, - 432, 414, 0, 445, 446, 447, 448, 449, 450, 451, - 452, 453, 454, 455, 456, 459, 518, 519, 0, 457, - 458, 467, 0, 0, 332, 333, 437, 0, 591, 29, - 0, 0, 0, 0, 442, 545, 0, 442, 545, 0, - 0, 0, 540, 537, 0, 0, 542, 0, 505, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 387, 0, - 0, 0, 0, 0, 0, 377, 0, 0, 380, 0, - 0, 0, 0, 371, 0, 0, 392, 853, 373, 0, - 375, 376, 396, 0, 396, 45, 396, 47, 0, 391, - 597, 52, 0, 0, 57, 58, 598, 599, 600, 601, - 0, 81, 207, 209, 212, 213, 214, 85, 86, 87, - 0, 0, 194, 0, 0, 188, 188, 0, 186, 187, - 83, 153, 151, 0, 148, 147, 93, 0, 159, 159, - 116, 117, 162, 0, 162, 162, 162, 0, 0, 110, - 111, 112, 104, 0, 105, 106, 107, 0, 108, 0, - 0, 933, 70, 613, 71, 932, 0, 0, 626, 221, - 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, - 0, 72, 223, 225, 224, 228, 0, 0, 0, 248, - 933, 252, 292, 276, 0, 0, 293, 294, 299, 283, - 0, 570, 571, 0, 563, 25, 0, 608, 609, 554, - 555, 344, 420, 422, 424, 0, 331, 411, 432, 415, - 0, 412, 0, 0, 406, 472, 0, 0, 439, -2, - 475, 476, 0, 0, 0, 0, 0, 511, 0, 0, - 512, 0, 560, 0, 538, 0, 0, 487, 0, 506, - 0, 0, 507, 508, 509, 510, 585, 0, 0, -2, - 0, 0, 396, 593, 0, 347, 366, 368, 0, 363, - 378, 379, 381, 0, 383, 0, 385, 386, 351, 353, - 354, 0, 0, 0, 0, 374, 560, 0, 396, 40, - 41, 0, 55, 56, 0, 0, 62, 163, 164, 0, - 210, 0, 0, 0, 181, 188, 188, 184, 189, 185, - 0, 155, 0, 152, 89, 149, 0, 162, 162, 118, - 0, 119, 120, 121, 0, 137, 0, 0, 0, 0, - 635, 69, 215, 932, 230, 231, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 932, 0, 932, 627, - 628, 629, 630, 0, 75, 0, 0, 0, 0, 0, - 251, 295, 296, 297, 574, 0, 26, 396, 0, 338, - 544, 0, 413, 0, 433, 416, 473, 334, 0, 139, - 139, 523, 139, 143, 526, 139, 528, 139, 531, 0, - 0, 0, 0, 0, 0, 0, 535, 486, 541, 0, - 543, 0, 0, 33, 0, 585, 575, 587, 589, 0, - 29, 0, 581, 0, 358, 560, 0, 0, 360, 367, - 0, 0, 361, 0, 362, 382, 384, 0, 0, 0, - 0, 568, 397, 39, 59, 60, 61, 208, 211, 0, - 190, 139, 193, 182, 183, 0, 157, 0, 154, 140, - 114, 115, 160, 161, 159, 0, 159, 0, 144, 0, - 933, 216, 217, 218, 219, 0, 222, 0, 73, 74, - 0, 0, 227, 249, 275, 556, 345, 474, 417, 477, - 520, 159, 524, 525, 527, 529, 530, 532, 479, 478, - 0, 0, 0, 0, 0, 0, 0, 539, 0, 0, - 0, 34, 0, 590, -2, 0, 0, 0, 49, 0, - 568, 594, 595, 364, 0, 369, 0, 0, 0, 372, - 38, 173, 0, 192, 0, 356, 165, 158, 0, 162, - 138, 162, 0, 0, 67, 0, 76, 77, 0, 0, - 0, 558, 0, 521, 522, 0, 0, 0, 0, 513, - 485, 536, 0, 0, 0, 588, 0, -2, 0, 583, - 582, 359, 37, 0, 0, 0, 0, 392, 172, 174, - 0, 179, 0, 191, 0, 0, 170, 0, 167, 169, - 156, 127, 128, 142, 145, 0, 0, 0, 0, 229, - 28, 0, 0, 480, 482, 481, 483, 0, 0, 0, - 502, 503, 0, 578, 29, 0, 365, 393, 394, 395, - 355, 175, 176, 0, 180, 178, 0, 357, 88, 0, - 166, 168, 0, 243, 0, 78, 79, 72, 559, 557, - 484, 0, 0, 0, 586, -2, 584, 177, 0, 171, - 242, 0, 0, 75, 514, 0, 517, 0, 244, 0, - 226, 515, 0, 0, 0, 195, 0, 0, 196, 197, - 0, 0, 516, 198, 0, 0, 0, 0, 0, 199, - 201, 202, 0, 0, 200, 245, 246, 203, 204, 205, + 103, 141, 141, 141, 143, 143, 640, 68, 0, 940, + 0, 940, 80, 0, 220, 222, 223, 0, 0, 0, + 0, 0, 0, 0, 0, 252, 617, 0, 940, 255, + 256, 393, 648, 649, 260, 261, 298, 299, 263, 264, + 265, 266, 267, 268, 275, 279, 0, 297, 0, 0, + 281, 282, 0, 0, 579, 0, 0, 0, 0, 0, + 570, 572, 573, 578, 32, 329, 0, 559, 0, 0, + 0, 333, 27, 403, 404, 406, 423, 0, 425, 427, + 344, 340, 0, 549, -2, 413, 414, 438, 439, 440, + 0, 0, 0, 0, 436, 418, 0, 449, 450, 451, + 452, 453, 454, 455, 456, 457, 458, 459, 460, 463, + 524, 525, 0, 461, 462, 471, 0, 0, 0, 335, + 336, 441, 0, 597, 29, 0, 0, 0, 0, 446, + 551, 0, 446, 551, 0, 0, 0, 546, 543, 0, + 0, 548, 0, 510, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 390, 0, 0, 0, 0, 0, + 0, 380, 0, 0, 383, 0, 0, 0, 0, 374, + 0, 0, 395, 860, 376, 0, 378, 379, 400, 0, + 400, 45, 400, 47, 0, 394, 603, 52, 0, 0, + 57, 58, 604, 605, 606, 607, 0, 81, 207, 209, + 212, 213, 214, 85, 86, 87, 0, 0, 194, 0, + 0, 188, 188, 0, 186, 187, 83, 153, 151, 0, + 148, 147, 93, 0, 159, 159, 116, 117, 162, 0, + 162, 162, 162, 0, 0, 110, 111, 112, 104, 0, + 105, 106, 107, 0, 108, 0, 0, 940, 70, 619, + 71, 939, 0, 0, 632, 221, 622, 623, 624, 625, + 626, 627, 628, 629, 630, 631, 0, 72, 225, 227, + 226, 230, 0, 0, 0, 250, 940, 254, 294, 278, + 295, 296, 301, 285, 0, 576, 577, 0, 569, 25, + 0, 614, 615, 560, 561, 347, 424, 426, 428, 0, + 334, 415, 436, 419, 0, 416, 0, 0, 410, 476, + 0, 0, 0, 443, -2, 480, 481, 0, 0, 0, + 0, 0, 517, 0, 0, 518, 0, 566, 0, 544, + 0, 0, 492, 0, 511, 0, 0, 512, 513, 514, + 515, 516, 591, 0, 0, -2, 0, 0, 400, 599, + 0, 350, 369, 371, 0, 366, 381, 382, 384, 0, + 386, 0, 388, 389, 354, 356, 357, 0, 0, 0, + 0, 377, 566, 0, 400, 40, 41, 0, 55, 56, + 0, 0, 62, 163, 164, 0, 210, 0, 0, 0, + 181, 188, 188, 184, 189, 185, 0, 155, 0, 152, + 89, 149, 0, 162, 162, 118, 0, 119, 120, 121, + 0, 137, 0, 0, 0, 0, 641, 69, 215, 939, + 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, + 242, 243, 939, 0, 939, 633, 634, 635, 636, 0, + 75, 0, 0, 0, 0, 0, 253, 297, 580, 0, + 26, 400, 0, 341, 550, 0, 417, 0, 437, 420, + 477, 478, 337, 0, 139, 139, 529, 139, 143, 532, + 139, 534, 139, 537, 0, 0, 0, 0, 0, 0, + 0, 541, 491, 547, 0, 549, 0, 0, 33, 0, + 591, 581, 593, 595, 0, 29, 0, 587, 0, 361, + 566, 0, 0, 363, 370, 0, 0, 364, 0, 365, + 385, 387, 0, 0, 0, 0, 574, 401, 39, 59, + 60, 61, 208, 211, 0, 190, 139, 193, 182, 183, + 0, 157, 0, 154, 140, 114, 115, 160, 161, 159, + 0, 159, 0, 144, 0, 940, 216, 217, 218, 219, + 0, 224, 0, 73, 74, 0, 0, 229, 251, 277, + 562, 348, 479, 421, 482, 526, 159, 530, 531, 533, + 535, 536, 538, 484, 483, 0, 0, 0, 0, 0, + 574, 0, 545, 0, 0, 0, 34, 0, 596, -2, + 0, 0, 0, 49, 0, 574, 600, 601, 367, 0, + 372, 0, 0, 0, 375, 38, 173, 0, 192, 0, + 359, 165, 158, 0, 162, 138, 162, 0, 0, 67, + 0, 76, 77, 0, 0, 0, 564, 0, 527, 528, + 0, 0, 0, 0, 519, 0, 542, 0, 0, 0, + 594, 0, -2, 0, 589, 588, 362, 37, 0, 0, + 397, 0, 0, 395, 172, 174, 0, 179, 0, 191, + 0, 0, 170, 0, 167, 169, 156, 127, 128, 142, + 145, 0, 0, 0, 0, 231, 28, 0, 0, 485, + 487, 486, 488, 0, 0, 0, 490, 507, 508, 0, + 584, 29, 0, 368, 396, 398, 399, 358, 175, 176, + 0, 180, 178, 0, 360, 88, 0, 166, 168, 0, + 245, 0, 78, 79, 72, 565, 563, 489, 0, 0, + 0, 592, -2, 590, 177, 0, 171, 244, 0, 0, + 75, 520, 0, 523, 0, 246, 0, 228, 521, 0, + 0, 0, 195, 0, 0, 196, 197, 0, 0, 522, + 198, 0, 0, 0, 0, 0, 199, 201, 202, 0, + 0, 200, 247, 248, 203, 204, 205, } var yyTok1 = [...]int{ 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 75, 3, 3, 3, 102, 94, 3, - 54, 56, 99, 97, 55, 98, 112, 100, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 347, - 83, 82, 84, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 76, 3, 3, 3, 103, 95, 3, + 55, 57, 100, 98, 56, 99, 113, 101, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 348, + 84, 83, 85, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 104, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 105, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 93, 3, 105, + 3, 3, 3, 3, 94, 3, 106, } var yyTok2 = [...]int{ @@ -3239,11 +3289,11 @@ var yyTok2 = [...]int{ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 57, 58, 59, 60, 61, 62, 63, 64, + 52, 53, 54, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 76, 77, 78, 79, 80, 81, 85, 86, 87, 88, - 89, 90, 91, 92, 95, 96, 101, 103, 106, 107, - 108, 109, 110, 111, 113, 114, 115, 116, 117, 118, + 75, 77, 78, 79, 80, 81, 82, 86, 87, 88, + 89, 90, 91, 92, 93, 96, 97, 102, 104, 107, + 108, 109, 110, 111, 112, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, @@ -3276,7 +3326,7 @@ var yyTok3 = [...]int{ 57655, 330, 57656, 331, 57657, 332, 57658, 333, 57659, 334, 57660, 335, 57661, 336, 57662, 337, 57663, 338, 57664, 339, 57665, 340, 57666, 341, 57667, 342, 57668, 343, 57669, 344, - 57670, 345, 57671, 346, 0, + 57670, 345, 57671, 346, 57672, 347, 0, } var yyErrorMessages = [...]struct { @@ -3618,35 +3668,35 @@ yydefault: case 1: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:323 +//line sql.y:324 { setParseTree(yylex, yyDollar[1].statement) } case 2: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:328 +//line sql.y:329 { } case 3: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:329 +//line sql.y:330 { } case 4: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:333 +//line sql.y:334 { yyVAL.statement = yyDollar[1].selStmt } case 23: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:355 +//line sql.y:356 { setParseTree(yylex, nil) } case 24: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:361 +//line sql.y:362 { sel := yyDollar[1].selStmt.(*Select) sel.OrderBy = yyDollar[2].orderBy @@ -3656,55 +3706,55 @@ yydefault: } case 25: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:369 +//line sql.y:370 { yyVAL.selStmt = &Union{Type: yyDollar[2].str, Left: yyDollar[1].selStmt, Right: yyDollar[3].selStmt, OrderBy: yyDollar[4].orderBy, Limit: yyDollar[5].limit, Lock: yyDollar[6].str} } case 26: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:373 +//line sql.y:374 { yyVAL.selStmt = &Select{Comments: Comments(yyDollar[2].bytes2), Cache: yyDollar[3].str, SelectExprs: SelectExprs{Nextval{Expr: yyDollar[5].expr}}, From: TableExprs{&AliasedTableExpr{Expr: yyDollar[7].tableName}}} } case 27: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:379 +//line sql.y:380 { yyVAL.statement = &Stream{Comments: Comments(yyDollar[2].bytes2), SelectExpr: yyDollar[3].selectExpr, Table: yyDollar[5].tableName} } case 28: yyDollar = yyS[yypt-10 : yypt+1] -//line sql.y:386 +//line sql.y:387 { yyVAL.selStmt = &Select{Comments: Comments(yyDollar[2].bytes2), Cache: yyDollar[3].str, Distinct: yyDollar[4].str, Hints: yyDollar[5].str, SelectExprs: yyDollar[6].selectExprs, From: yyDollar[7].tableExprs, Where: NewWhere(WhereStr, yyDollar[8].expr), GroupBy: GroupBy(yyDollar[9].exprs), Having: NewWhere(HavingStr, yyDollar[10].expr)} } case 29: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:392 +//line sql.y:393 { yyVAL.selStmt = yyDollar[1].selStmt } case 30: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:396 +//line sql.y:397 { yyVAL.selStmt = &ParenSelect{Select: yyDollar[2].selStmt} } case 31: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:402 +//line sql.y:403 { yyVAL.selStmt = yyDollar[1].selStmt } case 32: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:406 +//line sql.y:407 { yyVAL.selStmt = &ParenSelect{Select: yyDollar[2].selStmt} } case 33: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:413 +//line sql.y:414 { // insert_data returns a *Insert pre-filled with Columns & Values ins := yyDollar[6].ins @@ -3718,7 +3768,7 @@ yydefault: } case 34: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:425 +//line sql.y:426 { cols := make(Columns, 0, len(yyDollar[7].updateExprs)) vals := make(ValTuple, 0, len(yyDollar[8].updateExprs)) @@ -3730,192 +3780,192 @@ yydefault: } case 35: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:437 +//line sql.y:438 { yyVAL.str = InsertStr } case 36: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:441 +//line sql.y:442 { yyVAL.str = ReplaceStr } case 37: yyDollar = yyS[yypt-9 : yypt+1] -//line sql.y:447 +//line sql.y:448 { yyVAL.statement = &Update{Comments: Comments(yyDollar[2].bytes2), Ignore: yyDollar[3].str, TableExprs: yyDollar[4].tableExprs, Exprs: yyDollar[6].updateExprs, Where: NewWhere(WhereStr, yyDollar[7].expr), OrderBy: yyDollar[8].orderBy, Limit: yyDollar[9].limit} } case 38: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:453 +//line sql.y:454 { yyVAL.statement = &Delete{Comments: Comments(yyDollar[2].bytes2), TableExprs: TableExprs{&AliasedTableExpr{Expr: yyDollar[4].tableName}}, Partitions: yyDollar[5].partitions, Where: NewWhere(WhereStr, yyDollar[6].expr), OrderBy: yyDollar[7].orderBy, Limit: yyDollar[8].limit} } case 39: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:457 +//line sql.y:458 { yyVAL.statement = &Delete{Comments: Comments(yyDollar[2].bytes2), Targets: yyDollar[4].tableNames, TableExprs: yyDollar[6].tableExprs, Where: NewWhere(WhereStr, yyDollar[7].expr)} } case 40: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:461 +//line sql.y:462 { yyVAL.statement = &Delete{Comments: Comments(yyDollar[2].bytes2), Targets: yyDollar[3].tableNames, TableExprs: yyDollar[5].tableExprs, Where: NewWhere(WhereStr, yyDollar[6].expr)} } case 41: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:465 +//line sql.y:466 { yyVAL.statement = &Delete{Comments: Comments(yyDollar[2].bytes2), Targets: yyDollar[3].tableNames, TableExprs: yyDollar[5].tableExprs, Where: NewWhere(WhereStr, yyDollar[6].expr)} } case 42: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:470 +//line sql.y:471 { } case 43: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:471 +//line sql.y:472 { } case 44: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:475 +//line sql.y:476 { yyVAL.tableNames = TableNames{yyDollar[1].tableName} } case 45: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:479 +//line sql.y:480 { yyVAL.tableNames = append(yyVAL.tableNames, yyDollar[3].tableName) } case 46: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:485 +//line sql.y:486 { yyVAL.tableNames = TableNames{yyDollar[1].tableName} } case 47: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:489 +//line sql.y:490 { yyVAL.tableNames = append(yyVAL.tableNames, yyDollar[3].tableName) } case 48: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:494 +//line sql.y:495 { yyVAL.partitions = nil } case 49: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:498 +//line sql.y:499 { yyVAL.partitions = yyDollar[3].partitions } case 50: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:504 +//line sql.y:505 { yyVAL.statement = &Set{Comments: Comments(yyDollar[2].bytes2), Exprs: yyDollar[3].setExprs} } case 51: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:508 +//line sql.y:509 { yyVAL.statement = &Set{Comments: Comments(yyDollar[2].bytes2), Scope: yyDollar[3].str, Exprs: yyDollar[4].setExprs} } case 52: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:512 +//line sql.y:513 { yyVAL.statement = &Set{Comments: Comments(yyDollar[2].bytes2), Scope: yyDollar[3].str, Exprs: yyDollar[5].setExprs} } case 53: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:516 +//line sql.y:517 { yyVAL.statement = &Set{Comments: Comments(yyDollar[2].bytes2), Exprs: yyDollar[4].setExprs} } case 54: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:522 +//line sql.y:523 { yyVAL.setExprs = SetExprs{yyDollar[1].setExpr} } case 55: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:526 +//line sql.y:527 { yyVAL.setExprs = append(yyVAL.setExprs, yyDollar[3].setExpr) } case 56: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:532 +//line sql.y:533 { yyVAL.setExpr = &SetExpr{Name: NewColIdent(TransactionStr), Expr: NewStrVal([]byte(yyDollar[3].str))} } case 57: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:536 +//line sql.y:537 { yyVAL.setExpr = &SetExpr{Name: NewColIdent(TransactionStr), Expr: NewStrVal([]byte(TxReadWrite))} } case 58: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:540 +//line sql.y:541 { yyVAL.setExpr = &SetExpr{Name: NewColIdent(TransactionStr), Expr: NewStrVal([]byte(TxReadOnly))} } case 59: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:546 +//line sql.y:547 { yyVAL.str = IsolationLevelRepeatableRead } case 60: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:550 +//line sql.y:551 { yyVAL.str = IsolationLevelReadCommitted } case 61: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:554 +//line sql.y:555 { yyVAL.str = IsolationLevelReadUncommitted } case 62: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:558 +//line sql.y:559 { yyVAL.str = IsolationLevelSerializable } case 63: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:564 +//line sql.y:565 { yyVAL.str = SessionStr } case 64: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:568 +//line sql.y:569 { yyVAL.str = GlobalStr } case 65: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:574 +//line sql.y:575 { yyDollar[1].ddl.TableSpec = yyDollar[2].TableSpec yyVAL.statement = yyDollar[1].ddl } case 66: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:579 +//line sql.y:580 { // Create table [name] like [name] yyDollar[1].ddl.OptLike = yyDollar[2].optLike @@ -3923,139 +3973,139 @@ yydefault: } case 67: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:585 +//line sql.y:586 { // Change this to an alter statement yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[7].tableName} } case 68: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:590 +//line sql.y:591 { yyVAL.statement = &DDL{Action: CreateStr, Table: yyDollar[3].tableName.ToViewName()} } case 69: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:594 +//line sql.y:595 { yyVAL.statement = &DDL{Action: CreateStr, Table: yyDollar[5].tableName.ToViewName()} } case 70: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:598 +//line sql.y:599 { yyVAL.statement = &DBDDL{Action: CreateStr, DBName: string(yyDollar[4].bytes)} } case 71: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:602 +//line sql.y:603 { yyVAL.statement = &DBDDL{Action: CreateStr, DBName: string(yyDollar[4].bytes)} } case 72: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:607 +//line sql.y:608 { yyVAL.colIdent = NewColIdent("") } case 73: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:611 +//line sql.y:612 { yyVAL.colIdent = yyDollar[2].colIdent } case 74: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:617 +//line sql.y:618 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } case 75: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:622 +//line sql.y:623 { var v []VindexParam yyVAL.vindexParams = v } case 76: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:627 +//line sql.y:628 { yyVAL.vindexParams = yyDollar[2].vindexParams } case 77: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:633 +//line sql.y:634 { yyVAL.vindexParams = make([]VindexParam, 0, 4) yyVAL.vindexParams = append(yyVAL.vindexParams, yyDollar[1].vindexParam) } case 78: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:638 +//line sql.y:639 { yyVAL.vindexParams = append(yyVAL.vindexParams, yyDollar[3].vindexParam) } case 79: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:644 +//line sql.y:645 { yyVAL.vindexParam = VindexParam{Key: yyDollar[1].colIdent, Val: yyDollar[3].str} } case 80: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:650 +//line sql.y:651 { yyVAL.ddl = &DDL{Action: CreateStr, Table: yyDollar[4].tableName} setDDL(yylex, yyVAL.ddl) } case 81: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:657 +//line sql.y:658 { yyVAL.TableSpec = yyDollar[2].TableSpec yyVAL.TableSpec.Options = yyDollar[4].str } case 82: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:664 +//line sql.y:665 { yyVAL.optLike = &OptLike{LikeTable: yyDollar[2].tableName} } case 83: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:668 +//line sql.y:669 { yyVAL.optLike = &OptLike{LikeTable: yyDollar[3].tableName} } case 84: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:674 +//line sql.y:675 { yyVAL.TableSpec = &TableSpec{} yyVAL.TableSpec.AddColumn(yyDollar[1].columnDefinition) } case 85: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:679 +//line sql.y:680 { yyVAL.TableSpec.AddColumn(yyDollar[3].columnDefinition) } case 86: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:683 +//line sql.y:684 { yyVAL.TableSpec.AddIndex(yyDollar[3].indexDefinition) } case 87: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:687 +//line sql.y:688 { yyVAL.TableSpec.AddConstraint(yyDollar[3].constraintDefinition) } case 88: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:693 +//line sql.y:694 { yyDollar[2].columnType.NotNull = yyDollar[3].boolVal yyDollar[2].columnType.Default = yyDollar[4].optVal @@ -4067,7 +4117,7 @@ yydefault: } case 89: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:704 +//line sql.y:705 { yyVAL.columnType = yyDollar[1].columnType yyVAL.columnType.Unsigned = yyDollar[2].boolVal @@ -4075,74 +4125,74 @@ yydefault: } case 93: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:715 +//line sql.y:716 { yyVAL.columnType = yyDollar[1].columnType yyVAL.columnType.Length = yyDollar[2].sqlVal } case 94: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:720 +//line sql.y:721 { yyVAL.columnType = yyDollar[1].columnType } case 95: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:726 +//line sql.y:727 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 96: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:730 +//line sql.y:731 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 97: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:734 +//line sql.y:735 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 98: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:738 +//line sql.y:739 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 99: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:742 +//line sql.y:743 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 100: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:746 +//line sql.y:747 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 101: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:750 +//line sql.y:751 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 102: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:754 +//line sql.y:755 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 103: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:758 +//line sql.y:759 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 104: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:764 +//line sql.y:765 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -4150,7 +4200,7 @@ yydefault: } case 105: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:770 +//line sql.y:771 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -4158,7 +4208,7 @@ yydefault: } case 106: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:776 +//line sql.y:777 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -4166,7 +4216,7 @@ yydefault: } case 107: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:782 +//line sql.y:783 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -4174,7 +4224,7 @@ yydefault: } case 108: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:788 +//line sql.y:789 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -4182,206 +4232,206 @@ yydefault: } case 109: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:796 +//line sql.y:797 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 110: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:800 +//line sql.y:801 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].sqlVal} } case 111: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:804 +//line sql.y:805 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].sqlVal} } case 112: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:808 +//line sql.y:809 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].sqlVal} } case 113: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:812 +//line sql.y:813 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 114: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:818 +//line sql.y:819 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].sqlVal, Charset: yyDollar[3].str, Collate: yyDollar[4].str} } case 115: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:822 +//line sql.y:823 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].sqlVal, Charset: yyDollar[3].str, Collate: yyDollar[4].str} } case 116: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:826 +//line sql.y:827 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].sqlVal} } case 117: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:830 +//line sql.y:831 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].sqlVal} } case 118: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:834 +//line sql.y:835 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Charset: yyDollar[2].str, Collate: yyDollar[3].str} } case 119: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:838 +//line sql.y:839 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Charset: yyDollar[2].str, Collate: yyDollar[3].str} } case 120: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:842 +//line sql.y:843 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Charset: yyDollar[2].str, Collate: yyDollar[3].str} } case 121: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:846 +//line sql.y:847 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Charset: yyDollar[2].str, Collate: yyDollar[3].str} } case 122: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:850 +//line sql.y:851 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 123: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:854 +//line sql.y:855 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 124: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:858 +//line sql.y:859 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 125: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:862 +//line sql.y:863 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 126: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:866 +//line sql.y:867 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 127: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:870 +//line sql.y:871 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), EnumValues: yyDollar[3].strs, Charset: yyDollar[5].str, Collate: yyDollar[6].str} } case 128: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:875 +//line sql.y:876 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), EnumValues: yyDollar[3].strs, Charset: yyDollar[5].str, Collate: yyDollar[6].str} } case 129: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:881 +//line sql.y:882 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 130: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:885 +//line sql.y:886 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 131: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:889 +//line sql.y:890 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 132: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:893 +//line sql.y:894 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 133: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:897 +//line sql.y:898 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 134: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:901 +//line sql.y:902 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 135: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:905 +//line sql.y:906 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 136: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:909 +//line sql.y:910 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 137: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:915 +//line sql.y:916 { yyVAL.strs = make([]string, 0, 4) yyVAL.strs = append(yyVAL.strs, "'"+string(yyDollar[1].bytes)+"'") } case 138: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:920 +//line sql.y:921 { yyVAL.strs = append(yyDollar[1].strs, "'"+string(yyDollar[3].bytes)+"'") } case 139: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:925 +//line sql.y:926 { yyVAL.sqlVal = nil } case 140: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:929 +//line sql.y:930 { yyVAL.sqlVal = NewIntVal(yyDollar[2].bytes) } case 141: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:934 +//line sql.y:935 { yyVAL.LengthScaleOption = LengthScaleOption{} } case 142: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:938 +//line sql.y:939 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: NewIntVal(yyDollar[2].bytes), @@ -4390,13 +4440,13 @@ yydefault: } case 143: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:946 +//line sql.y:947 { yyVAL.LengthScaleOption = LengthScaleOption{} } case 144: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:950 +//line sql.y:951 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: NewIntVal(yyDollar[2].bytes), @@ -4404,7 +4454,7 @@ yydefault: } case 145: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:956 +//line sql.y:957 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: NewIntVal(yyDollar[2].bytes), @@ -4413,466 +4463,478 @@ yydefault: } case 146: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:964 +//line sql.y:965 { yyVAL.boolVal = BoolVal(false) } case 147: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:968 +//line sql.y:969 { yyVAL.boolVal = BoolVal(true) } case 148: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:973 +//line sql.y:974 { yyVAL.boolVal = BoolVal(false) } case 149: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:977 +//line sql.y:978 { yyVAL.boolVal = BoolVal(true) } case 150: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:983 +//line sql.y:984 { yyVAL.boolVal = BoolVal(false) } case 151: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:987 +//line sql.y:988 { yyVAL.boolVal = BoolVal(false) } case 152: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:991 +//line sql.y:992 { yyVAL.boolVal = BoolVal(true) } case 153: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:996 +//line sql.y:997 { yyVAL.optVal = nil } case 154: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1000 +//line sql.y:1001 { yyVAL.optVal = yyDollar[2].expr } case 155: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1005 +//line sql.y:1006 { yyVAL.optVal = nil } case 156: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1009 +//line sql.y:1010 { yyVAL.optVal = yyDollar[3].expr } case 157: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1014 +//line sql.y:1015 { yyVAL.boolVal = BoolVal(false) } case 158: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1018 +//line sql.y:1019 { yyVAL.boolVal = BoolVal(true) } case 159: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1023 +//line sql.y:1024 { yyVAL.str = "" } case 160: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1027 +//line sql.y:1028 { yyVAL.str = string(yyDollar[3].bytes) } case 161: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1031 +//line sql.y:1032 { yyVAL.str = string(yyDollar[3].bytes) } case 162: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1036 +//line sql.y:1037 { yyVAL.str = "" } case 163: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1040 +//line sql.y:1041 { yyVAL.str = string(yyDollar[2].bytes) } case 164: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1044 +//line sql.y:1045 { yyVAL.str = string(yyDollar[2].bytes) } case 165: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1049 +//line sql.y:1050 { yyVAL.colKeyOpt = colKeyNone } case 166: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1053 +//line sql.y:1054 { yyVAL.colKeyOpt = colKeyPrimary } case 167: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1057 +//line sql.y:1058 { yyVAL.colKeyOpt = colKey } case 168: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1061 +//line sql.y:1062 { yyVAL.colKeyOpt = colKeyUniqueKey } case 169: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1065 +//line sql.y:1066 { yyVAL.colKeyOpt = colKeyUnique } case 170: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1070 +//line sql.y:1071 { yyVAL.sqlVal = nil } case 171: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1074 +//line sql.y:1075 { yyVAL.sqlVal = NewStrVal(yyDollar[2].bytes) } case 172: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1080 +//line sql.y:1081 { yyVAL.indexDefinition = &IndexDefinition{Info: yyDollar[1].indexInfo, Columns: yyDollar[3].indexColumns, Options: yyDollar[5].indexOptions} } case 173: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1084 +//line sql.y:1085 { yyVAL.indexDefinition = &IndexDefinition{Info: yyDollar[1].indexInfo, Columns: yyDollar[3].indexColumns} } case 174: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1090 +//line sql.y:1091 { yyVAL.indexOptions = []*IndexOption{yyDollar[1].indexOption} } case 175: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1094 +//line sql.y:1095 { yyVAL.indexOptions = append(yyVAL.indexOptions, yyDollar[2].indexOption) } case 176: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1100 +//line sql.y:1101 { yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), Using: string(yyDollar[2].bytes)} } case 177: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1104 +//line sql.y:1105 { // should not be string yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), Value: NewIntVal(yyDollar[3].bytes)} } case 178: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1109 +//line sql.y:1110 { yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), Value: NewStrVal(yyDollar[2].bytes)} } case 179: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1115 +//line sql.y:1116 { yyVAL.str = "" } case 180: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1119 +//line sql.y:1120 { yyVAL.str = string(yyDollar[1].bytes) } case 181: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1125 +//line sql.y:1126 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes) + " " + string(yyDollar[2].bytes), Name: NewColIdent("PRIMARY"), Primary: true, Unique: true} } case 182: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1129 +//line sql.y:1130 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes) + " " + string(yyDollar[2].str), Name: NewColIdent(yyDollar[3].str), Spatial: true, Unique: false} } case 183: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1133 +//line sql.y:1134 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes) + " " + string(yyDollar[2].str), Name: NewColIdent(yyDollar[3].str), Unique: true} } case 184: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1137 +//line sql.y:1138 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes), Name: NewColIdent(yyDollar[2].str), Unique: true} } case 185: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1141 +//line sql.y:1142 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].str), Name: NewColIdent(yyDollar[2].str), Unique: false} } case 186: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1147 +//line sql.y:1148 { yyVAL.str = string(yyDollar[1].bytes) } case 187: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1151 +//line sql.y:1152 { yyVAL.str = string(yyDollar[1].bytes) } case 188: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1156 +//line sql.y:1157 { yyVAL.str = "" } case 189: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1160 +//line sql.y:1161 { yyVAL.str = string(yyDollar[1].bytes) } case 190: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1166 +//line sql.y:1167 { yyVAL.indexColumns = []*IndexColumn{yyDollar[1].indexColumn} } case 191: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1170 +//line sql.y:1171 { yyVAL.indexColumns = append(yyVAL.indexColumns, yyDollar[3].indexColumn) } case 192: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1176 +//line sql.y:1177 { yyVAL.indexColumn = &IndexColumn{Column: yyDollar[1].colIdent, Length: yyDollar[2].sqlVal} } case 193: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1182 +//line sql.y:1183 { yyVAL.constraintDefinition = &ConstraintDefinition{Name: string(yyDollar[2].bytes), Details: yyDollar[3].constraintInfo} } case 194: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1186 +//line sql.y:1187 { yyVAL.constraintDefinition = &ConstraintDefinition{Details: yyDollar[1].constraintInfo} } case 195: yyDollar = yyS[yypt-10 : yypt+1] -//line sql.y:1193 +//line sql.y:1194 { yyVAL.constraintInfo = &ForeignKeyDefinition{Source: yyDollar[4].columns, ReferencedTable: yyDollar[7].tableName, ReferencedColumns: yyDollar[9].columns} } case 196: yyDollar = yyS[yypt-11 : yypt+1] -//line sql.y:1197 +//line sql.y:1198 { yyVAL.constraintInfo = &ForeignKeyDefinition{Source: yyDollar[4].columns, ReferencedTable: yyDollar[7].tableName, ReferencedColumns: yyDollar[9].columns, OnDelete: yyDollar[11].ReferenceAction} } case 197: yyDollar = yyS[yypt-11 : yypt+1] -//line sql.y:1201 +//line sql.y:1202 { yyVAL.constraintInfo = &ForeignKeyDefinition{Source: yyDollar[4].columns, ReferencedTable: yyDollar[7].tableName, ReferencedColumns: yyDollar[9].columns, OnUpdate: yyDollar[11].ReferenceAction} } case 198: yyDollar = yyS[yypt-12 : yypt+1] -//line sql.y:1205 +//line sql.y:1206 { yyVAL.constraintInfo = &ForeignKeyDefinition{Source: yyDollar[4].columns, ReferencedTable: yyDollar[7].tableName, ReferencedColumns: yyDollar[9].columns, OnDelete: yyDollar[11].ReferenceAction, OnUpdate: yyDollar[12].ReferenceAction} } case 199: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1211 +//line sql.y:1212 { yyVAL.ReferenceAction = yyDollar[3].ReferenceAction } case 200: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1217 +//line sql.y:1218 { yyVAL.ReferenceAction = yyDollar[3].ReferenceAction } case 201: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1223 +//line sql.y:1224 { yyVAL.ReferenceAction = Restrict } case 202: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1227 +//line sql.y:1228 { yyVAL.ReferenceAction = Cascade } case 203: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1231 +//line sql.y:1232 { yyVAL.ReferenceAction = NoAction } case 204: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1235 +//line sql.y:1236 { yyVAL.ReferenceAction = SetDefault } case 205: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1239 +//line sql.y:1240 { yyVAL.ReferenceAction = SetNull } case 206: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1244 +//line sql.y:1245 { yyVAL.str = "" } case 207: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1248 +//line sql.y:1249 { yyVAL.str = " " + string(yyDollar[1].str) } case 208: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1252 +//line sql.y:1253 { yyVAL.str = string(yyDollar[1].str) + ", " + string(yyDollar[3].str) } case 209: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1260 +//line sql.y:1261 { yyVAL.str = yyDollar[1].str } case 210: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1264 +//line sql.y:1265 { yyVAL.str = yyDollar[1].str + " " + yyDollar[2].str } case 211: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1268 +//line sql.y:1269 { yyVAL.str = yyDollar[1].str + "=" + yyDollar[3].str } case 212: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1274 +//line sql.y:1275 { yyVAL.str = yyDollar[1].colIdent.String() } case 213: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1278 +//line sql.y:1279 { yyVAL.str = "'" + string(yyDollar[1].bytes) + "'" } case 214: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1282 +//line sql.y:1283 { yyVAL.str = string(yyDollar[1].bytes) } case 215: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:1288 +//line sql.y:1289 { yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[4].tableName} } case 216: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1292 +//line sql.y:1293 { yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[4].tableName} } case 217: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1296 +//line sql.y:1297 { yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[4].tableName} } case 218: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1300 +//line sql.y:1301 { // Change this to a rename statement yyVAL.statement = &DDL{Action: RenameStr, FromTables: TableNames{yyDollar[4].tableName}, ToTables: TableNames{yyDollar[7].tableName}} } case 219: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1305 +//line sql.y:1306 { // Rename an index can just be an alter yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[4].tableName} } case 220: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1310 +//line sql.y:1311 { yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[3].tableName.ToViewName()} } case 221: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1314 +//line sql.y:1315 { yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[4].tableName, PartitionSpec: yyDollar[5].partSpec} } case 222: + yyDollar = yyS[yypt-4 : yypt+1] +//line sql.y:1319 + { + yyVAL.statement = &DBDDL{Action: AlterStr, DBName: string(yyDollar[3].bytes)} + } + case 223: + yyDollar = yyS[yypt-4 : yypt+1] +//line sql.y:1323 + { + yyVAL.statement = &DBDDL{Action: AlterStr, DBName: string(yyDollar[3].bytes)} + } + case 224: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1318 +//line sql.y:1327 { yyVAL.statement = &DDL{ Action: CreateVindexStr, @@ -4884,9 +4946,9 @@ yydefault: }, } } - case 223: + case 225: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1330 +//line sql.y:1339 { yyVAL.statement = &DDL{ Action: DropVindexStr, @@ -4896,21 +4958,21 @@ yydefault: }, } } - case 224: + case 226: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1340 +//line sql.y:1349 { yyVAL.statement = &DDL{Action: AddVschemaTableStr, Table: yyDollar[5].tableName} } - case 225: + case 227: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1344 +//line sql.y:1353 { yyVAL.statement = &DDL{Action: DropVschemaTableStr, Table: yyDollar[5].tableName} } - case 226: + case 228: yyDollar = yyS[yypt-12 : yypt+1] -//line sql.y:1348 +//line sql.y:1357 { yyVAL.statement = &DDL{ Action: AddColVindexStr, @@ -4923,9 +4985,9 @@ yydefault: VindexCols: yyDollar[9].columns, } } - case 227: + case 229: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1361 +//line sql.y:1370 { yyVAL.statement = &DDL{ Action: DropColVindexStr, @@ -4935,15 +4997,15 @@ yydefault: }, } } - case 228: + case 230: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1371 +//line sql.y:1380 { yyVAL.statement = &DDL{Action: AddSequenceStr, Table: yyDollar[5].tableName} } - case 229: + case 231: yyDollar = yyS[yypt-9 : yypt+1] -//line sql.y:1375 +//line sql.y:1384 { yyVAL.statement = &DDL{ Action: AddAutoIncStr, @@ -4954,59 +5016,59 @@ yydefault: }, } } - case 242: + case 244: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1402 +//line sql.y:1411 { yyVAL.partSpec = &PartitionSpec{Action: ReorganizeStr, Name: yyDollar[3].colIdent, Definitions: yyDollar[6].partDefs} } - case 243: + case 245: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1408 +//line sql.y:1417 { yyVAL.partDefs = []*PartitionDefinition{yyDollar[1].partDef} } - case 244: + case 246: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1412 +//line sql.y:1421 { yyVAL.partDefs = append(yyDollar[1].partDefs, yyDollar[3].partDef) } - case 245: + case 247: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:1418 +//line sql.y:1427 { yyVAL.partDef = &PartitionDefinition{Name: yyDollar[2].colIdent, Limit: yyDollar[7].expr} } - case 246: + case 248: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:1422 +//line sql.y:1431 { yyVAL.partDef = &PartitionDefinition{Name: yyDollar[2].colIdent, Maxvalue: true} } - case 247: + case 249: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1428 +//line sql.y:1437 { yyVAL.statement = yyDollar[3].ddl } - case 248: + case 250: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1434 +//line sql.y:1443 { yyVAL.ddl = &DDL{Action: RenameStr, FromTables: TableNames{yyDollar[1].tableName}, ToTables: TableNames{yyDollar[3].tableName}} } - case 249: + case 251: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1438 +//line sql.y:1447 { yyVAL.ddl = yyDollar[1].ddl yyVAL.ddl.FromTables = append(yyVAL.ddl.FromTables, yyDollar[3].tableName) yyVAL.ddl.ToTables = append(yyVAL.ddl.ToTables, yyDollar[5].tableName) } - case 250: + case 252: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1446 +//line sql.y:1455 { var exists bool if yyDollar[3].byt != 0 { @@ -5014,16 +5076,16 @@ yydefault: } yyVAL.statement = &DDL{Action: DropStr, FromTables: yyDollar[4].tableNames, IfExists: exists} } - case 251: + case 253: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:1454 +//line sql.y:1463 { // Change this to an alter statement yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[5].tableName} } - case 252: + case 254: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1459 +//line sql.y:1468 { var exists bool if yyDollar[3].byt != 0 { @@ -5031,148 +5093,150 @@ yydefault: } yyVAL.statement = &DDL{Action: DropStr, FromTables: TableNames{yyDollar[4].tableName.ToViewName()}, IfExists: exists} } - case 253: + case 255: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1467 +//line sql.y:1476 { yyVAL.statement = &DBDDL{Action: DropStr, DBName: string(yyDollar[4].bytes)} } - case 254: + case 256: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1471 +//line sql.y:1480 { yyVAL.statement = &DBDDL{Action: DropStr, DBName: string(yyDollar[4].bytes)} } - case 255: + case 257: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1477 +//line sql.y:1486 { yyVAL.statement = &DDL{Action: TruncateStr, Table: yyDollar[3].tableName} } - case 256: + case 258: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1481 +//line sql.y:1490 { yyVAL.statement = &DDL{Action: TruncateStr, Table: yyDollar[2].tableName} } - case 257: + case 259: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1486 +//line sql.y:1495 { yyVAL.statement = &DDL{Action: AlterStr, Table: yyDollar[3].tableName} } - case 258: + case 260: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1492 +//line sql.y:1501 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes)} } - case 259: + case 261: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1497 +//line sql.y:1506 { - yyVAL.statement = &Show{Type: CharsetStr} + showTablesOpt := &ShowTablesOpt{Filter: yyDollar[4].showFilter} + yyVAL.statement = &Show{Type: CharsetStr, ShowTablesOpt: showTablesOpt} } - case 260: + case 262: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1501 +//line sql.y:1511 { - yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} + showTablesOpt := &ShowTablesOpt{Filter: yyDollar[3].showFilter} + yyVAL.statement = &Show{Type: string(yyDollar[2].bytes), ShowTablesOpt: showTablesOpt} } - case 261: + case 263: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1505 +//line sql.y:1516 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes)} } - case 262: + case 264: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1510 +//line sql.y:1521 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes)} } - case 263: + case 265: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1514 +//line sql.y:1525 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes)} } - case 264: + case 266: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1518 +//line sql.y:1529 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes), Table: yyDollar[4].tableName} } - case 265: + case 267: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1522 +//line sql.y:1533 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes)} } - case 266: + case 268: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1526 +//line sql.y:1537 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes)} } - case 267: + case 269: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1530 +//line sql.y:1541 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } - case 268: + case 270: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1534 +//line sql.y:1545 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } - case 269: + case 271: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1538 +//line sql.y:1549 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } - case 270: + case 272: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1542 +//line sql.y:1553 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } - case 271: + case 273: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1546 +//line sql.y:1557 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } - case 272: + case 274: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1550 +//line sql.y:1561 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } - case 273: + case 275: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1554 +//line sql.y:1565 { yyVAL.statement = &Show{Scope: yyDollar[2].str, Type: string(yyDollar[3].bytes)} } - case 274: + case 276: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1558 +//line sql.y:1569 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } - case 275: + case 277: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1562 +//line sql.y:1573 { showTablesOpt := &ShowTablesOpt{Full: yyDollar[2].str, DbName: yyDollar[6].str, Filter: yyDollar[7].showFilter} yyVAL.statement = &Show{Type: string(yyDollar[3].str), ShowTablesOpt: showTablesOpt, OnTable: yyDollar[5].tableName} } - case 276: + case 278: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1567 +//line sql.y:1578 { // this is ugly, but I couldn't find a better way for now if yyDollar[3].str == "processlist" { @@ -5182,645 +5246,651 @@ yydefault: yyVAL.statement = &Show{Type: yyDollar[3].str, ShowTablesOpt: showTablesOpt} } } - case 277: + case 279: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1577 +//line sql.y:1588 { yyVAL.statement = &Show{Scope: yyDollar[2].str, Type: string(yyDollar[3].bytes)} } - case 278: + case 280: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1581 +//line sql.y:1592 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } - case 279: + case 281: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1585 +//line sql.y:1596 { // Cannot dereference $4 directly, or else the parser stackcannot be pooled. See yyParsePooled showCollationFilterOpt := yyDollar[4].expr yyVAL.statement = &Show{Type: string(yyDollar[2].bytes), ShowCollationFilterOpt: &showCollationFilterOpt} } - case 280: + case 282: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1591 +//line sql.y:1602 { showTablesOpt := &ShowTablesOpt{Filter: yyDollar[4].showFilter} yyVAL.statement = &Show{Scope: string(yyDollar[2].bytes), Type: string(yyDollar[3].bytes), ShowTablesOpt: showTablesOpt} } - case 281: + case 283: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1596 +//line sql.y:1607 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes)} } - case 282: + case 284: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1600 +//line sql.y:1611 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes)} } - case 283: + case 285: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1604 +//line sql.y:1615 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes), OnTable: yyDollar[5].tableName} } - case 284: + case 286: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1608 +//line sql.y:1619 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } - case 285: + case 287: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1622 +//line sql.y:1633 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes)} } - case 286: + case 288: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1628 +//line sql.y:1639 { yyVAL.str = string(yyDollar[1].bytes) } - case 287: + case 289: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1632 +//line sql.y:1643 { yyVAL.str = string(yyDollar[1].bytes) } - case 288: + case 290: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1638 +//line sql.y:1649 { yyVAL.str = "" } - case 289: + case 291: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1642 +//line sql.y:1653 { yyVAL.str = "full " } - case 290: + case 292: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1648 +//line sql.y:1659 { yyVAL.str = string(yyDollar[1].bytes) } - case 291: + case 293: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1652 +//line sql.y:1663 { yyVAL.str = string(yyDollar[1].bytes) } - case 292: + case 294: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1658 +//line sql.y:1669 { yyVAL.str = "" } - case 293: + case 295: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1662 +//line sql.y:1673 { yyVAL.str = yyDollar[2].tableIdent.v } - case 294: + case 296: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1666 +//line sql.y:1677 { yyVAL.str = yyDollar[2].tableIdent.v } - case 295: + case 297: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1672 +//line sql.y:1683 { yyVAL.showFilter = nil } - case 296: + case 298: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1676 +//line sql.y:1687 { yyVAL.showFilter = &ShowFilter{Like: string(yyDollar[2].bytes)} } - case 297: + case 299: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1680 +//line sql.y:1691 { yyVAL.showFilter = &ShowFilter{Filter: yyDollar[2].expr} } - case 298: + case 300: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1686 +//line sql.y:1697 { yyVAL.showFilter = nil } - case 299: + case 301: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1690 +//line sql.y:1701 { yyVAL.showFilter = &ShowFilter{Like: string(yyDollar[2].bytes)} } - case 300: + case 302: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1696 +//line sql.y:1707 { yyVAL.str = "" } - case 301: + case 303: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1700 +//line sql.y:1711 { yyVAL.str = SessionStr } - case 302: + case 304: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1704 +//line sql.y:1715 { yyVAL.str = GlobalStr } - case 303: + case 305: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1710 +//line sql.y:1721 { yyVAL.statement = &Use{DBName: yyDollar[2].tableIdent} } - case 304: + case 306: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1714 +//line sql.y:1725 { yyVAL.statement = &Use{DBName: TableIdent{v: ""}} } - case 305: + case 307: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1720 +//line sql.y:1731 { yyVAL.statement = &Begin{} } - case 306: + case 308: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1724 +//line sql.y:1735 { yyVAL.statement = &Begin{} } - case 307: + case 309: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1730 +//line sql.y:1741 { yyVAL.statement = &Commit{} } - case 308: + case 310: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1736 +//line sql.y:1747 { yyVAL.statement = &Rollback{} } - case 309: + case 311: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1742 +//line sql.y:1753 { yyVAL.statement = &OtherRead{} } - case 310: + case 312: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1746 +//line sql.y:1757 { yyVAL.statement = &OtherRead{} } - case 311: + case 313: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1750 +//line sql.y:1761 { yyVAL.statement = &OtherRead{} } - case 312: + case 314: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1754 +//line sql.y:1765 { yyVAL.statement = &OtherAdmin{} } - case 313: + case 315: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1758 +//line sql.y:1769 { yyVAL.statement = &OtherAdmin{} } - case 314: + case 316: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1762 +//line sql.y:1773 { yyVAL.statement = &OtherAdmin{} } - case 315: + case 317: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1766 +//line sql.y:1777 { yyVAL.statement = &OtherAdmin{} } - case 316: + case 318: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1772 +//line sql.y:1783 { yyVAL.statement = &DDL{Action: FlushStr} } - case 317: + case 319: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1776 +//line sql.y:1787 { setAllowComments(yylex, true) } - case 318: + case 320: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1780 +//line sql.y:1791 { yyVAL.bytes2 = yyDollar[2].bytes2 setAllowComments(yylex, false) } - case 319: + case 321: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1786 +//line sql.y:1797 { yyVAL.bytes2 = nil } - case 320: + case 322: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1790 +//line sql.y:1801 { yyVAL.bytes2 = append(yyDollar[1].bytes2, yyDollar[2].bytes) } - case 321: + case 323: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1796 +//line sql.y:1807 { yyVAL.str = UnionStr } - case 322: + case 324: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1800 +//line sql.y:1811 { yyVAL.str = UnionAllStr } - case 323: + case 325: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1804 +//line sql.y:1815 { yyVAL.str = UnionDistinctStr } - case 324: + case 326: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1809 +//line sql.y:1820 { yyVAL.str = "" } - case 325: + case 327: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1813 +//line sql.y:1824 { yyVAL.str = SQLNoCacheStr } - case 326: + case 328: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1817 +//line sql.y:1828 { yyVAL.str = SQLCacheStr } - case 327: + case 329: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1822 +//line sql.y:1833 { yyVAL.str = "" } - case 328: + case 330: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1826 +//line sql.y:1837 { yyVAL.str = DistinctStr } - case 329: + case 331: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:1841 + { + yyVAL.str = DistinctStr + } + case 332: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1831 +//line sql.y:1846 { yyVAL.str = "" } - case 330: + case 333: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1835 +//line sql.y:1850 { yyVAL.str = StraightJoinHint } - case 331: + case 334: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1840 +//line sql.y:1855 { yyVAL.selectExprs = nil } - case 332: + case 335: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1844 +//line sql.y:1859 { yyVAL.selectExprs = yyDollar[1].selectExprs } - case 333: + case 336: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1850 +//line sql.y:1865 { yyVAL.selectExprs = SelectExprs{yyDollar[1].selectExpr} } - case 334: + case 337: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1854 +//line sql.y:1869 { yyVAL.selectExprs = append(yyVAL.selectExprs, yyDollar[3].selectExpr) } - case 335: + case 338: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1860 +//line sql.y:1875 { yyVAL.selectExpr = &StarExpr{} } - case 336: + case 339: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1864 +//line sql.y:1879 { yyVAL.selectExpr = &AliasedExpr{Expr: yyDollar[1].expr, As: yyDollar[2].colIdent} } - case 337: + case 340: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1868 +//line sql.y:1883 { yyVAL.selectExpr = &StarExpr{TableName: TableName{Name: yyDollar[1].tableIdent}} } - case 338: + case 341: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1872 +//line sql.y:1887 { yyVAL.selectExpr = &StarExpr{TableName: TableName{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].tableIdent}} } - case 339: + case 342: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1877 +//line sql.y:1892 { yyVAL.colIdent = ColIdent{} } - case 340: + case 343: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1881 +//line sql.y:1896 { yyVAL.colIdent = yyDollar[1].colIdent } - case 341: + case 344: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1885 +//line sql.y:1900 { yyVAL.colIdent = yyDollar[2].colIdent } - case 343: + case 346: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1892 +//line sql.y:1907 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } - case 344: + case 347: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1897 +//line sql.y:1912 { yyVAL.tableExprs = TableExprs{&AliasedTableExpr{Expr: TableName{Name: NewTableIdent("dual")}}} } - case 345: + case 348: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1901 +//line sql.y:1916 { yyVAL.tableExprs = yyDollar[2].tableExprs } - case 346: + case 349: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1907 +//line sql.y:1922 { yyVAL.tableExprs = TableExprs{yyDollar[1].tableExpr} } - case 347: + case 350: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1911 +//line sql.y:1926 { yyVAL.tableExprs = append(yyVAL.tableExprs, yyDollar[3].tableExpr) } - case 350: + case 353: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1921 +//line sql.y:1936 { yyVAL.tableExpr = yyDollar[1].aliasedTableName } - case 351: + case 354: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1925 +//line sql.y:1940 { yyVAL.tableExpr = &AliasedTableExpr{Expr: yyDollar[1].subquery, As: yyDollar[3].tableIdent} } - case 352: + case 355: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1929 +//line sql.y:1944 { // missed alias for subquery yylex.Error("Every derived table must have its own alias") return 1 } - case 353: + case 356: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1935 +//line sql.y:1950 { yyVAL.tableExpr = &ParenTableExpr{Exprs: yyDollar[2].tableExprs} } - case 354: + case 357: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1941 +//line sql.y:1956 { yyVAL.aliasedTableName = &AliasedTableExpr{Expr: yyDollar[1].tableName, As: yyDollar[2].tableIdent, Hints: yyDollar[3].indexHints} } - case 355: + case 358: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1945 +//line sql.y:1960 { yyVAL.aliasedTableName = &AliasedTableExpr{Expr: yyDollar[1].tableName, Partitions: yyDollar[4].partitions, As: yyDollar[6].tableIdent, Hints: yyDollar[7].indexHints} } - case 356: + case 359: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1951 +//line sql.y:1966 { yyVAL.columns = Columns{yyDollar[1].colIdent} } - case 357: + case 360: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1955 +//line sql.y:1970 { yyVAL.columns = append(yyVAL.columns, yyDollar[3].colIdent) } - case 358: + case 361: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1961 +//line sql.y:1976 { yyVAL.partitions = Partitions{yyDollar[1].colIdent} } - case 359: + case 362: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1965 +//line sql.y:1980 { yyVAL.partitions = append(yyVAL.partitions, yyDollar[3].colIdent) } - case 360: + case 363: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1978 +//line sql.y:1993 { yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].str, RightExpr: yyDollar[3].tableExpr, Condition: yyDollar[4].joinCondition} } - case 361: + case 364: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1982 +//line sql.y:1997 { yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].str, RightExpr: yyDollar[3].tableExpr, Condition: yyDollar[4].joinCondition} } - case 362: + case 365: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1986 +//line sql.y:2001 { yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].str, RightExpr: yyDollar[3].tableExpr, Condition: yyDollar[4].joinCondition} } - case 363: + case 366: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1990 +//line sql.y:2005 { yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].str, RightExpr: yyDollar[3].tableExpr} } - case 364: + case 367: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1996 +//line sql.y:2011 { yyVAL.joinCondition = JoinCondition{On: yyDollar[2].expr} } - case 365: + case 368: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1998 +//line sql.y:2013 { yyVAL.joinCondition = JoinCondition{Using: yyDollar[3].columns} } - case 366: + case 369: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2002 +//line sql.y:2017 { yyVAL.joinCondition = JoinCondition{} } - case 367: + case 370: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2004 +//line sql.y:2019 { yyVAL.joinCondition = yyDollar[1].joinCondition } - case 368: + case 371: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2008 +//line sql.y:2023 { yyVAL.joinCondition = JoinCondition{} } - case 369: + case 372: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2010 +//line sql.y:2025 { yyVAL.joinCondition = JoinCondition{On: yyDollar[2].expr} } - case 370: + case 373: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2013 +//line sql.y:2028 { yyVAL.empty = struct{}{} } - case 371: + case 374: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2015 +//line sql.y:2030 { yyVAL.empty = struct{}{} } - case 372: + case 375: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2018 +//line sql.y:2033 { yyVAL.tableIdent = NewTableIdent("") } - case 373: + case 376: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2022 +//line sql.y:2037 { yyVAL.tableIdent = yyDollar[1].tableIdent } - case 374: + case 377: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2026 +//line sql.y:2041 { yyVAL.tableIdent = yyDollar[2].tableIdent } - case 376: + case 379: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2033 +//line sql.y:2048 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } - case 377: + case 380: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2039 +//line sql.y:2054 { yyVAL.str = JoinStr } - case 378: + case 381: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2043 +//line sql.y:2058 { yyVAL.str = JoinStr } - case 379: + case 382: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2047 +//line sql.y:2062 { yyVAL.str = JoinStr } - case 380: + case 383: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2053 +//line sql.y:2068 { yyVAL.str = StraightJoinStr } - case 381: + case 384: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2059 +//line sql.y:2074 { yyVAL.str = LeftJoinStr } - case 382: + case 385: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2063 +//line sql.y:2078 { yyVAL.str = LeftJoinStr } - case 383: + case 386: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2067 +//line sql.y:2082 { yyVAL.str = RightJoinStr } - case 384: + case 387: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2071 +//line sql.y:2086 { yyVAL.str = RightJoinStr } - case 385: + case 388: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2077 +//line sql.y:2092 { yyVAL.str = NaturalJoinStr } - case 386: + case 389: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2081 +//line sql.y:2096 { if yyDollar[2].str == LeftJoinStr { yyVAL.str = NaturalLeftJoinStr @@ -5828,465 +5898,471 @@ yydefault: yyVAL.str = NaturalRightJoinStr } } - case 387: + case 390: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2091 +//line sql.y:2106 { yyVAL.tableName = yyDollar[2].tableName } - case 388: + case 391: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2095 +//line sql.y:2110 { yyVAL.tableName = yyDollar[1].tableName } - case 389: + case 392: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2101 +//line sql.y:2116 { yyVAL.tableName = TableName{Name: yyDollar[1].tableIdent} } - case 390: + case 393: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2105 +//line sql.y:2120 { yyVAL.tableName = TableName{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].tableIdent} } - case 391: + case 394: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2111 +//line sql.y:2126 { yyVAL.tableName = TableName{Name: yyDollar[1].tableIdent} } - case 392: + case 395: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2116 +//line sql.y:2131 { yyVAL.indexHints = nil } - case 393: + case 396: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2120 +//line sql.y:2135 { yyVAL.indexHints = &IndexHints{Type: UseStr, Indexes: yyDollar[4].columns} } - case 394: + case 397: + yyDollar = yyS[yypt-4 : yypt+1] +//line sql.y:2139 + { + yyVAL.indexHints = &IndexHints{Type: UseStr} + } + case 398: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2124 +//line sql.y:2143 { yyVAL.indexHints = &IndexHints{Type: IgnoreStr, Indexes: yyDollar[4].columns} } - case 395: + case 399: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2128 +//line sql.y:2147 { yyVAL.indexHints = &IndexHints{Type: ForceStr, Indexes: yyDollar[4].columns} } - case 396: + case 400: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2133 +//line sql.y:2152 { yyVAL.expr = nil } - case 397: + case 401: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2137 +//line sql.y:2156 { yyVAL.expr = yyDollar[2].expr } - case 398: + case 402: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2143 +//line sql.y:2162 { yyVAL.expr = yyDollar[1].expr } - case 399: + case 403: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2147 +//line sql.y:2166 { yyVAL.expr = &AndExpr{Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 400: + case 404: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2151 +//line sql.y:2170 { yyVAL.expr = &OrExpr{Left: yyDollar[1].expr, Right: yyDollar[3].expr} } - case 401: + case 405: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2155 +//line sql.y:2174 { yyVAL.expr = &NotExpr{Expr: yyDollar[2].expr} } - case 402: + case 406: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2159 +//line sql.y:2178 { yyVAL.expr = &IsExpr{Operator: yyDollar[3].str, Expr: yyDollar[1].expr} } - case 403: + case 407: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2163 +//line sql.y:2182 { yyVAL.expr = yyDollar[1].expr } - case 404: + case 408: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2167 +//line sql.y:2186 { yyVAL.expr = &Default{ColName: yyDollar[2].str} } - case 405: + case 409: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2173 +//line sql.y:2192 { yyVAL.str = "" } - case 406: + case 410: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2177 +//line sql.y:2196 { yyVAL.str = string(yyDollar[2].bytes) } - case 407: + case 411: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2183 +//line sql.y:2202 { yyVAL.boolVal = BoolVal(true) } - case 408: + case 412: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2187 +//line sql.y:2206 { yyVAL.boolVal = BoolVal(false) } - case 409: + case 413: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2193 +//line sql.y:2212 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: yyDollar[2].str, Right: yyDollar[3].expr} } - case 410: + case 414: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2197 +//line sql.y:2216 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: InStr, Right: yyDollar[3].colTuple} } - case 411: + case 415: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2201 +//line sql.y:2220 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotInStr, Right: yyDollar[4].colTuple} } - case 412: + case 416: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2205 +//line sql.y:2224 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: LikeStr, Right: yyDollar[3].expr, Escape: yyDollar[4].expr} } - case 413: + case 417: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2209 +//line sql.y:2228 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotLikeStr, Right: yyDollar[4].expr, Escape: yyDollar[5].expr} } - case 414: + case 418: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2213 +//line sql.y:2232 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: RegexpStr, Right: yyDollar[3].expr} } - case 415: + case 419: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2217 +//line sql.y:2236 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotRegexpStr, Right: yyDollar[4].expr} } - case 416: + case 420: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2221 +//line sql.y:2240 { yyVAL.expr = &RangeCond{Left: yyDollar[1].expr, Operator: BetweenStr, From: yyDollar[3].expr, To: yyDollar[5].expr} } - case 417: + case 421: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:2225 +//line sql.y:2244 { yyVAL.expr = &RangeCond{Left: yyDollar[1].expr, Operator: NotBetweenStr, From: yyDollar[4].expr, To: yyDollar[6].expr} } - case 418: + case 422: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2229 +//line sql.y:2248 { yyVAL.expr = &ExistsExpr{Subquery: yyDollar[2].subquery} } - case 419: + case 423: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2235 +//line sql.y:2254 { yyVAL.str = IsNullStr } - case 420: + case 424: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2239 +//line sql.y:2258 { yyVAL.str = IsNotNullStr } - case 421: + case 425: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2243 +//line sql.y:2262 { yyVAL.str = IsTrueStr } - case 422: + case 426: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2247 +//line sql.y:2266 { yyVAL.str = IsNotTrueStr } - case 423: + case 427: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2251 +//line sql.y:2270 { yyVAL.str = IsFalseStr } - case 424: + case 428: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2255 +//line sql.y:2274 { yyVAL.str = IsNotFalseStr } - case 425: + case 429: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2261 +//line sql.y:2280 { yyVAL.str = EqualStr } - case 426: + case 430: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2265 +//line sql.y:2284 { yyVAL.str = LessThanStr } - case 427: + case 431: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2269 +//line sql.y:2288 { yyVAL.str = GreaterThanStr } - case 428: + case 432: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2273 +//line sql.y:2292 { yyVAL.str = LessEqualStr } - case 429: + case 433: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2277 +//line sql.y:2296 { yyVAL.str = GreaterEqualStr } - case 430: + case 434: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2281 +//line sql.y:2300 { yyVAL.str = NotEqualStr } - case 431: + case 435: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2285 +//line sql.y:2304 { yyVAL.str = NullSafeEqualStr } - case 432: + case 436: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2290 +//line sql.y:2309 { yyVAL.expr = nil } - case 433: + case 437: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2294 +//line sql.y:2313 { yyVAL.expr = yyDollar[2].expr } - case 434: + case 438: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2300 +//line sql.y:2319 { yyVAL.colTuple = yyDollar[1].valTuple } - case 435: + case 439: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2304 +//line sql.y:2323 { yyVAL.colTuple = yyDollar[1].subquery } - case 436: + case 440: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2308 +//line sql.y:2327 { yyVAL.colTuple = ListArg(yyDollar[1].bytes) } - case 437: + case 441: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2314 +//line sql.y:2333 { yyVAL.subquery = &Subquery{yyDollar[2].selStmt} } - case 438: + case 442: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2320 +//line sql.y:2339 { yyVAL.exprs = Exprs{yyDollar[1].expr} } - case 439: + case 443: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2324 +//line sql.y:2343 { yyVAL.exprs = append(yyDollar[1].exprs, yyDollar[3].expr) } - case 440: + case 444: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2330 +//line sql.y:2349 { yyVAL.expr = yyDollar[1].expr } - case 441: + case 445: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2334 +//line sql.y:2353 { yyVAL.expr = yyDollar[1].boolVal } - case 442: + case 446: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2338 +//line sql.y:2357 { yyVAL.expr = yyDollar[1].colName } - case 443: + case 447: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2342 +//line sql.y:2361 { yyVAL.expr = yyDollar[1].expr } - case 444: + case 448: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2346 +//line sql.y:2365 { yyVAL.expr = yyDollar[1].subquery } - case 445: + case 449: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2350 +//line sql.y:2369 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitAndStr, Right: yyDollar[3].expr} } - case 446: + case 450: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2354 +//line sql.y:2373 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitOrStr, Right: yyDollar[3].expr} } - case 447: + case 451: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2358 +//line sql.y:2377 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitXorStr, Right: yyDollar[3].expr} } - case 448: + case 452: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2362 +//line sql.y:2381 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: PlusStr, Right: yyDollar[3].expr} } - case 449: + case 453: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2366 +//line sql.y:2385 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: MinusStr, Right: yyDollar[3].expr} } - case 450: + case 454: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2370 +//line sql.y:2389 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: MultStr, Right: yyDollar[3].expr} } - case 451: + case 455: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2374 +//line sql.y:2393 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: DivStr, Right: yyDollar[3].expr} } - case 452: + case 456: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2378 +//line sql.y:2397 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: IntDivStr, Right: yyDollar[3].expr} } - case 453: + case 457: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2382 +//line sql.y:2401 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ModStr, Right: yyDollar[3].expr} } - case 454: + case 458: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2386 +//line sql.y:2405 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ModStr, Right: yyDollar[3].expr} } - case 455: + case 459: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2390 +//line sql.y:2409 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ShiftLeftStr, Right: yyDollar[3].expr} } - case 456: + case 460: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2394 +//line sql.y:2413 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ShiftRightStr, Right: yyDollar[3].expr} } - case 457: + case 461: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2398 +//line sql.y:2417 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].colName, Operator: JSONExtractOp, Right: yyDollar[3].expr} } - case 458: + case 462: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2402 +//line sql.y:2421 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].colName, Operator: JSONUnquoteExtractOp, Right: yyDollar[3].expr} } - case 459: + case 463: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2406 +//line sql.y:2425 { yyVAL.expr = &CollateExpr{Expr: yyDollar[1].expr, Charset: yyDollar[3].str} } - case 460: + case 464: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2410 +//line sql.y:2429 { yyVAL.expr = &UnaryExpr{Operator: BinaryStr, Expr: yyDollar[2].expr} } - case 461: + case 465: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2414 +//line sql.y:2433 { yyVAL.expr = &UnaryExpr{Operator: UBinaryStr, Expr: yyDollar[2].expr} } - case 462: + case 466: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2418 +//line sql.y:2437 { yyVAL.expr = &UnaryExpr{Operator: Utf8mb4Str, Expr: yyDollar[2].expr} } - case 463: + case 467: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2422 +//line sql.y:2441 { if num, ok := yyDollar[2].expr.(*SQLVal); ok && num.Type == IntVal { yyVAL.expr = num @@ -6294,9 +6370,9 @@ yydefault: yyVAL.expr = &UnaryExpr{Operator: UPlusStr, Expr: yyDollar[2].expr} } } - case 464: + case 468: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2430 +//line sql.y:2449 { if num, ok := yyDollar[2].expr.(*SQLVal); ok && num.Type == IntVal { // Handle double negative @@ -6310,21 +6386,21 @@ yydefault: yyVAL.expr = &UnaryExpr{Operator: UMinusStr, Expr: yyDollar[2].expr} } } - case 465: + case 469: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2444 +//line sql.y:2463 { yyVAL.expr = &UnaryExpr{Operator: TildaStr, Expr: yyDollar[2].expr} } - case 466: + case 470: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2448 +//line sql.y:2467 { yyVAL.expr = &UnaryExpr{Operator: BangStr, Expr: yyDollar[2].expr} } - case 467: + case 471: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2452 +//line sql.y:2471 { // This rule prevents the usage of INTERVAL // as a function. If support is needed for that, @@ -6332,485 +6408,497 @@ yydefault: // will be non-trivial because of grammar conflicts. yyVAL.expr = &IntervalExpr{Expr: yyDollar[2].expr, Unit: yyDollar[3].colIdent.String()} } - case 472: + case 476: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2470 +//line sql.y:2489 { yyVAL.expr = &FuncExpr{Name: yyDollar[1].colIdent, Exprs: yyDollar[3].selectExprs} } - case 473: + case 477: + yyDollar = yyS[yypt-5 : yypt+1] +//line sql.y:2493 + { + yyVAL.expr = &FuncExpr{Name: yyDollar[1].colIdent, Distinct: true, Exprs: yyDollar[4].selectExprs} + } + case 478: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2474 +//line sql.y:2497 { yyVAL.expr = &FuncExpr{Name: yyDollar[1].colIdent, Distinct: true, Exprs: yyDollar[4].selectExprs} } - case 474: + case 479: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:2478 +//line sql.y:2501 { yyVAL.expr = &FuncExpr{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].colIdent, Exprs: yyDollar[5].selectExprs} } - case 475: + case 480: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2488 +//line sql.y:2511 { yyVAL.expr = &FuncExpr{Name: NewColIdent("left"), Exprs: yyDollar[3].selectExprs} } - case 476: + case 481: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2492 +//line sql.y:2515 { yyVAL.expr = &FuncExpr{Name: NewColIdent("right"), Exprs: yyDollar[3].selectExprs} } - case 477: + case 482: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:2496 +//line sql.y:2519 { yyVAL.expr = &ConvertExpr{Expr: yyDollar[3].expr, Type: yyDollar[5].convertType} } - case 478: + case 483: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:2500 +//line sql.y:2523 { yyVAL.expr = &ConvertExpr{Expr: yyDollar[3].expr, Type: yyDollar[5].convertType} } - case 479: + case 484: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:2504 +//line sql.y:2527 { yyVAL.expr = &ConvertUsingExpr{Expr: yyDollar[3].expr, Type: yyDollar[5].str} } - case 480: + case 485: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2508 +//line sql.y:2531 { yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: yyDollar[7].expr} } - case 481: + case 486: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2512 +//line sql.y:2535 { yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: yyDollar[7].expr} } - case 482: + case 487: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2516 +//line sql.y:2539 { yyVAL.expr = &SubstrExpr{StrVal: NewStrVal(yyDollar[3].bytes), From: yyDollar[5].expr, To: yyDollar[7].expr} } - case 483: + case 488: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2520 +//line sql.y:2543 { yyVAL.expr = &SubstrExpr{StrVal: NewStrVal(yyDollar[3].bytes), From: yyDollar[5].expr, To: yyDollar[7].expr} } - case 484: + case 489: yyDollar = yyS[yypt-9 : yypt+1] -//line sql.y:2524 +//line sql.y:2547 { yyVAL.expr = &MatchExpr{Columns: yyDollar[3].selectExprs, Expr: yyDollar[7].expr, Option: yyDollar[8].str} } - case 485: - yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:2528 + case 490: + yyDollar = yyS[yypt-8 : yypt+1] +//line sql.y:2551 { - yyVAL.expr = &GroupConcatExpr{Distinct: yyDollar[3].str, Exprs: yyDollar[4].selectExprs, OrderBy: yyDollar[5].orderBy, Separator: yyDollar[6].str} + yyVAL.expr = &GroupConcatExpr{Distinct: yyDollar[3].str, Exprs: yyDollar[4].selectExprs, OrderBy: yyDollar[5].orderBy, Separator: yyDollar[6].str, Limit: yyDollar[7].limit} } - case 486: + case 491: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2532 +//line sql.y:2555 { yyVAL.expr = &CaseExpr{Expr: yyDollar[2].expr, Whens: yyDollar[3].whens, Else: yyDollar[4].expr} } - case 487: + case 492: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2536 +//line sql.y:2559 { yyVAL.expr = &ValuesFuncExpr{Name: yyDollar[3].colName} } - case 488: + case 493: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2546 +//line sql.y:2569 { yyVAL.expr = &FuncExpr{Name: NewColIdent("current_timestamp")} } - case 489: + case 494: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2550 +//line sql.y:2573 { yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_timestamp")} } - case 490: + case 495: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2554 +//line sql.y:2577 { yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_time")} } - case 491: + case 496: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2559 +//line sql.y:2582 { yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_date")} } - case 492: + case 497: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2564 +//line sql.y:2587 { yyVAL.expr = &FuncExpr{Name: NewColIdent("localtime")} } - case 493: + case 498: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2569 +//line sql.y:2592 { yyVAL.expr = &FuncExpr{Name: NewColIdent("localtimestamp")} } - case 494: + case 499: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2575 +//line sql.y:2598 { yyVAL.expr = &FuncExpr{Name: NewColIdent("current_date")} } - case 495: + case 500: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2580 +//line sql.y:2603 { yyVAL.expr = &FuncExpr{Name: NewColIdent("current_time")} } - case 496: + case 501: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2585 +//line sql.y:2608 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("current_timestamp"), Fsp: yyDollar[2].expr} } - case 497: + case 502: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2589 +//line sql.y:2612 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("utc_timestamp"), Fsp: yyDollar[2].expr} } - case 498: + case 503: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2593 +//line sql.y:2616 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("utc_time"), Fsp: yyDollar[2].expr} } - case 499: + case 504: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2598 +//line sql.y:2621 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("localtime"), Fsp: yyDollar[2].expr} } - case 500: + case 505: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2603 +//line sql.y:2626 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("localtimestamp"), Fsp: yyDollar[2].expr} } - case 501: + case 506: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2608 +//line sql.y:2631 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("current_time"), Fsp: yyDollar[2].expr} } - case 502: + case 507: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2612 +//line sql.y:2635 { yyVAL.expr = &TimestampFuncExpr{Name: string("timestampadd"), Unit: yyDollar[3].colIdent.String(), Expr1: yyDollar[5].expr, Expr2: yyDollar[7].expr} } - case 503: + case 508: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2616 +//line sql.y:2639 { yyVAL.expr = &TimestampFuncExpr{Name: string("timestampdiff"), Unit: yyDollar[3].colIdent.String(), Expr1: yyDollar[5].expr, Expr2: yyDollar[7].expr} } - case 506: + case 511: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2626 +//line sql.y:2649 { yyVAL.expr = yyDollar[2].expr } - case 507: + case 512: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2636 +//line sql.y:2659 { yyVAL.expr = &FuncExpr{Name: NewColIdent("if"), Exprs: yyDollar[3].selectExprs} } - case 508: + case 513: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2640 +//line sql.y:2663 { yyVAL.expr = &FuncExpr{Name: NewColIdent("database"), Exprs: yyDollar[3].selectExprs} } - case 509: + case 514: + yyDollar = yyS[yypt-4 : yypt+1] +//line sql.y:2667 + { + yyVAL.expr = &FuncExpr{Name: NewColIdent("schema"), Exprs: yyDollar[3].selectExprs} + } + case 515: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2644 +//line sql.y:2671 { yyVAL.expr = &FuncExpr{Name: NewColIdent("mod"), Exprs: yyDollar[3].selectExprs} } - case 510: + case 516: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2648 +//line sql.y:2675 { yyVAL.expr = &FuncExpr{Name: NewColIdent("replace"), Exprs: yyDollar[3].selectExprs} } - case 511: + case 517: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2652 +//line sql.y:2679 { yyVAL.expr = &FuncExpr{Name: NewColIdent("substr"), Exprs: yyDollar[3].selectExprs} } - case 512: + case 518: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2656 +//line sql.y:2683 { yyVAL.expr = &FuncExpr{Name: NewColIdent("substr"), Exprs: yyDollar[3].selectExprs} } - case 513: + case 519: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2662 +//line sql.y:2689 { yyVAL.str = "" } - case 514: + case 520: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2666 +//line sql.y:2693 { yyVAL.str = BooleanModeStr } - case 515: + case 521: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2670 +//line sql.y:2697 { yyVAL.str = NaturalLanguageModeStr } - case 516: + case 522: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:2674 +//line sql.y:2701 { yyVAL.str = NaturalLanguageModeWithQueryExpansionStr } - case 517: + case 523: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2678 +//line sql.y:2705 { yyVAL.str = QueryExpansionStr } - case 518: + case 524: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2684 +//line sql.y:2711 { yyVAL.str = string(yyDollar[1].bytes) } - case 519: + case 525: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2688 +//line sql.y:2715 { yyVAL.str = string(yyDollar[1].bytes) } - case 520: + case 526: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2694 +//line sql.y:2721 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].sqlVal} } - case 521: + case 527: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2698 +//line sql.y:2725 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].sqlVal, Charset: yyDollar[3].str, Operator: CharacterSetStr} } - case 522: + case 528: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2702 +//line sql.y:2729 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].sqlVal, Charset: string(yyDollar[3].bytes)} } - case 523: + case 529: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2706 +//line sql.y:2733 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 524: + case 530: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2710 +//line sql.y:2737 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].sqlVal} } - case 525: + case 531: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2714 +//line sql.y:2741 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} yyVAL.convertType.Length = yyDollar[2].LengthScaleOption.Length yyVAL.convertType.Scale = yyDollar[2].LengthScaleOption.Scale } - case 526: + case 532: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2720 +//line sql.y:2747 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 527: + case 533: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2724 +//line sql.y:2751 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].sqlVal} } - case 528: + case 534: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2728 +//line sql.y:2755 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 529: + case 535: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2732 +//line sql.y:2759 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 530: + case 536: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2736 +//line sql.y:2763 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].sqlVal} } - case 531: + case 537: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2740 +//line sql.y:2767 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 532: + case 538: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2744 +//line sql.y:2771 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } - case 533: + case 539: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2749 +//line sql.y:2776 { yyVAL.expr = nil } - case 534: + case 540: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2753 +//line sql.y:2780 { yyVAL.expr = yyDollar[1].expr } - case 535: + case 541: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2758 +//line sql.y:2785 { yyVAL.str = string("") } - case 536: + case 542: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2762 +//line sql.y:2789 { yyVAL.str = " separator '" + string(yyDollar[2].bytes) + "'" } - case 537: + case 543: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2768 +//line sql.y:2795 { yyVAL.whens = []*When{yyDollar[1].when} } - case 538: + case 544: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2772 +//line sql.y:2799 { yyVAL.whens = append(yyDollar[1].whens, yyDollar[2].when) } - case 539: + case 545: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2778 +//line sql.y:2805 { yyVAL.when = &When{Cond: yyDollar[2].expr, Val: yyDollar[4].expr} } - case 540: + case 546: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2783 +//line sql.y:2810 { yyVAL.expr = nil } - case 541: + case 547: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2787 +//line sql.y:2814 { yyVAL.expr = yyDollar[2].expr } - case 542: + case 548: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2793 +//line sql.y:2820 { yyVAL.colName = &ColName{Name: yyDollar[1].colIdent} } - case 543: + case 549: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2797 +//line sql.y:2824 { yyVAL.colName = &ColName{Qualifier: TableName{Name: yyDollar[1].tableIdent}, Name: yyDollar[3].colIdent} } - case 544: + case 550: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2801 +//line sql.y:2828 { yyVAL.colName = &ColName{Qualifier: TableName{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].tableIdent}, Name: yyDollar[5].colIdent} } - case 545: + case 551: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2807 +//line sql.y:2834 { yyVAL.expr = NewStrVal(yyDollar[1].bytes) } - case 546: + case 552: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2811 +//line sql.y:2838 { yyVAL.expr = NewHexVal(yyDollar[1].bytes) } - case 547: + case 553: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2815 +//line sql.y:2842 { yyVAL.expr = NewBitVal(yyDollar[1].bytes) } - case 548: + case 554: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2819 +//line sql.y:2846 { yyVAL.expr = NewIntVal(yyDollar[1].bytes) } - case 549: + case 555: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2823 +//line sql.y:2850 { yyVAL.expr = NewFloatVal(yyDollar[1].bytes) } - case 550: + case 556: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2827 +//line sql.y:2854 { yyVAL.expr = NewHexNum(yyDollar[1].bytes) } - case 551: + case 557: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2831 +//line sql.y:2858 { yyVAL.expr = NewValArg(yyDollar[1].bytes) } - case 552: + case 558: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2835 +//line sql.y:2862 { yyVAL.expr = &NullVal{} } - case 553: + case 559: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2841 +//line sql.y:2868 { // TODO(sougou): Deprecate this construct. if yyDollar[1].colIdent.Lowered() != "value" { @@ -6819,239 +6907,239 @@ yydefault: } yyVAL.expr = NewIntVal([]byte("1")) } - case 554: + case 560: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2850 +//line sql.y:2877 { yyVAL.expr = NewIntVal(yyDollar[1].bytes) } - case 555: + case 561: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2854 +//line sql.y:2881 { yyVAL.expr = NewValArg(yyDollar[1].bytes) } - case 556: + case 562: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2859 +//line sql.y:2886 { yyVAL.exprs = nil } - case 557: + case 563: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2863 +//line sql.y:2890 { yyVAL.exprs = yyDollar[3].exprs } - case 558: + case 564: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2868 +//line sql.y:2895 { yyVAL.expr = nil } - case 559: + case 565: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2872 +//line sql.y:2899 { yyVAL.expr = yyDollar[2].expr } - case 560: + case 566: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2877 +//line sql.y:2904 { yyVAL.orderBy = nil } - case 561: + case 567: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2881 +//line sql.y:2908 { yyVAL.orderBy = yyDollar[3].orderBy } - case 562: + case 568: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2887 +//line sql.y:2914 { yyVAL.orderBy = OrderBy{yyDollar[1].order} } - case 563: + case 569: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2891 +//line sql.y:2918 { yyVAL.orderBy = append(yyDollar[1].orderBy, yyDollar[3].order) } - case 564: + case 570: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2897 +//line sql.y:2924 { yyVAL.order = &Order{Expr: yyDollar[1].expr, Direction: yyDollar[2].str} } - case 565: + case 571: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2902 +//line sql.y:2929 { yyVAL.str = AscScr } - case 566: + case 572: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2906 +//line sql.y:2933 { yyVAL.str = AscScr } - case 567: + case 573: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2910 +//line sql.y:2937 { yyVAL.str = DescScr } - case 568: + case 574: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2915 +//line sql.y:2942 { yyVAL.limit = nil } - case 569: + case 575: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2919 +//line sql.y:2946 { yyVAL.limit = &Limit{Rowcount: yyDollar[2].expr} } - case 570: + case 576: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2923 +//line sql.y:2950 { yyVAL.limit = &Limit{Offset: yyDollar[2].expr, Rowcount: yyDollar[4].expr} } - case 571: + case 577: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2927 +//line sql.y:2954 { yyVAL.limit = &Limit{Offset: yyDollar[4].expr, Rowcount: yyDollar[2].expr} } - case 572: + case 578: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2932 +//line sql.y:2959 { yyVAL.str = "" } - case 573: + case 579: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2936 +//line sql.y:2963 { yyVAL.str = ForUpdateStr } - case 574: + case 580: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2940 +//line sql.y:2967 { yyVAL.str = ShareModeStr } - case 575: + case 581: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2953 +//line sql.y:2980 { yyVAL.ins = &Insert{Rows: yyDollar[2].values} } - case 576: + case 582: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2957 +//line sql.y:2984 { yyVAL.ins = &Insert{Rows: yyDollar[1].selStmt} } - case 577: + case 583: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2961 +//line sql.y:2988 { // Drop the redundant parenthesis. yyVAL.ins = &Insert{Rows: yyDollar[2].selStmt} } - case 578: + case 584: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2966 +//line sql.y:2993 { yyVAL.ins = &Insert{Columns: yyDollar[2].columns, Rows: yyDollar[5].values} } - case 579: + case 585: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2970 +//line sql.y:2997 { yyVAL.ins = &Insert{Columns: yyDollar[2].columns, Rows: yyDollar[4].selStmt} } - case 580: + case 586: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:2974 +//line sql.y:3001 { // Drop the redundant parenthesis. yyVAL.ins = &Insert{Columns: yyDollar[2].columns, Rows: yyDollar[5].selStmt} } - case 581: + case 587: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2981 +//line sql.y:3008 { yyVAL.columns = Columns{yyDollar[1].colIdent} } - case 582: + case 588: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2985 +//line sql.y:3012 { yyVAL.columns = Columns{yyDollar[3].colIdent} } - case 583: + case 589: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2989 +//line sql.y:3016 { yyVAL.columns = append(yyVAL.columns, yyDollar[3].colIdent) } - case 584: + case 590: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2993 +//line sql.y:3020 { yyVAL.columns = append(yyVAL.columns, yyDollar[5].colIdent) } - case 585: + case 591: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2998 +//line sql.y:3025 { yyVAL.updateExprs = nil } - case 586: + case 592: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:3002 +//line sql.y:3029 { yyVAL.updateExprs = yyDollar[5].updateExprs } - case 587: + case 593: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3008 +//line sql.y:3035 { yyVAL.values = Values{yyDollar[1].valTuple} } - case 588: + case 594: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3012 +//line sql.y:3039 { yyVAL.values = append(yyDollar[1].values, yyDollar[3].valTuple) } - case 589: + case 595: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3018 +//line sql.y:3045 { yyVAL.valTuple = yyDollar[1].valTuple } - case 590: + case 596: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3022 +//line sql.y:3049 { yyVAL.valTuple = ValTuple{} } - case 591: + case 597: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3028 +//line sql.y:3055 { yyVAL.valTuple = ValTuple(yyDollar[2].exprs) } - case 592: + case 598: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3034 +//line sql.y:3061 { if len(yyDollar[1].valTuple) == 1 { yyVAL.expr = &ParenExpr{yyDollar[1].valTuple[0]} @@ -7059,312 +7147,312 @@ yydefault: yyVAL.expr = yyDollar[1].valTuple } } - case 593: + case 599: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3044 +//line sql.y:3071 { yyVAL.updateExprs = UpdateExprs{yyDollar[1].updateExpr} } - case 594: + case 600: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3048 +//line sql.y:3075 { yyVAL.updateExprs = append(yyDollar[1].updateExprs, yyDollar[3].updateExpr) } - case 595: + case 601: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3054 +//line sql.y:3081 { yyVAL.updateExpr = &UpdateExpr{Name: yyDollar[1].colName, Expr: yyDollar[3].expr} } - case 596: + case 602: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3060 +//line sql.y:3087 { yyVAL.setExprs = SetExprs{yyDollar[1].setExpr} } - case 597: + case 603: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3064 +//line sql.y:3091 { yyVAL.setExprs = append(yyDollar[1].setExprs, yyDollar[3].setExpr) } - case 598: + case 604: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3070 +//line sql.y:3097 { yyVAL.setExpr = &SetExpr{Name: yyDollar[1].colIdent, Expr: NewStrVal([]byte("on"))} } - case 599: + case 605: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3074 +//line sql.y:3101 { yyVAL.setExpr = &SetExpr{Name: yyDollar[1].colIdent, Expr: NewStrVal([]byte("off"))} } - case 600: + case 606: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3078 +//line sql.y:3105 { yyVAL.setExpr = &SetExpr{Name: yyDollar[1].colIdent, Expr: yyDollar[3].expr} } - case 601: + case 607: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3082 +//line sql.y:3109 { yyVAL.setExpr = &SetExpr{Name: NewColIdent(string(yyDollar[1].bytes)), Expr: yyDollar[2].expr} } - case 603: + case 609: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3089 +//line sql.y:3116 { yyVAL.bytes = []byte("charset") } - case 605: + case 611: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3096 +//line sql.y:3123 { yyVAL.expr = NewStrVal([]byte(yyDollar[1].colIdent.String())) } - case 606: + case 612: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3100 +//line sql.y:3127 { yyVAL.expr = NewStrVal(yyDollar[1].bytes) } - case 607: + case 613: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3104 +//line sql.y:3131 { yyVAL.expr = &Default{} } - case 610: + case 616: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3113 +//line sql.y:3140 { yyVAL.byt = 0 } - case 611: + case 617: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3115 +//line sql.y:3142 { yyVAL.byt = 1 } - case 612: + case 618: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3118 +//line sql.y:3145 { yyVAL.empty = struct{}{} } - case 613: + case 619: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3120 +//line sql.y:3147 { yyVAL.empty = struct{}{} } - case 614: + case 620: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3123 +//line sql.y:3150 { yyVAL.str = "" } - case 615: + case 621: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3125 +//line sql.y:3152 { yyVAL.str = IgnoreStr } - case 616: + case 622: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3129 +//line sql.y:3156 { yyVAL.empty = struct{}{} } - case 617: + case 623: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3131 +//line sql.y:3158 { yyVAL.empty = struct{}{} } - case 618: + case 624: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3133 +//line sql.y:3160 { yyVAL.empty = struct{}{} } - case 619: + case 625: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3135 +//line sql.y:3162 { yyVAL.empty = struct{}{} } - case 620: + case 626: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3137 +//line sql.y:3164 { yyVAL.empty = struct{}{} } - case 621: + case 627: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3139 +//line sql.y:3166 { yyVAL.empty = struct{}{} } - case 622: + case 628: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3141 +//line sql.y:3168 { yyVAL.empty = struct{}{} } - case 623: + case 629: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3143 +//line sql.y:3170 { yyVAL.empty = struct{}{} } - case 624: + case 630: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3145 +//line sql.y:3172 { yyVAL.empty = struct{}{} } - case 625: + case 631: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3147 +//line sql.y:3174 { yyVAL.empty = struct{}{} } - case 626: + case 632: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3150 +//line sql.y:3177 { yyVAL.empty = struct{}{} } - case 627: + case 633: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3152 +//line sql.y:3179 { yyVAL.empty = struct{}{} } - case 628: + case 634: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3154 +//line sql.y:3181 { yyVAL.empty = struct{}{} } - case 629: + case 635: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3158 +//line sql.y:3185 { yyVAL.empty = struct{}{} } - case 630: + case 636: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3160 +//line sql.y:3187 { yyVAL.empty = struct{}{} } - case 631: + case 637: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3163 +//line sql.y:3190 { yyVAL.empty = struct{}{} } - case 632: + case 638: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3165 +//line sql.y:3192 { yyVAL.empty = struct{}{} } - case 633: + case 639: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3167 +//line sql.y:3194 { yyVAL.empty = struct{}{} } - case 634: + case 640: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3170 +//line sql.y:3197 { yyVAL.colIdent = ColIdent{} } - case 635: + case 641: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3172 +//line sql.y:3199 { yyVAL.colIdent = yyDollar[2].colIdent } - case 636: + case 642: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3176 +//line sql.y:3203 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } - case 637: + case 643: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3180 +//line sql.y:3207 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } - case 639: + case 645: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3187 +//line sql.y:3214 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } - case 640: + case 646: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3193 +//line sql.y:3220 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } - case 641: + case 647: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3197 +//line sql.y:3224 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } - case 643: + case 649: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3204 +//line sql.y:3231 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } - case 930: + case 937: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3516 +//line sql.y:3544 { if incNesting(yylex) { yylex.Error("max nesting level reached") return 1 } } - case 931: + case 938: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3525 +//line sql.y:3553 { decNesting(yylex) } - case 932: + case 939: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3530 +//line sql.y:3558 { skipToEnd(yylex) } - case 933: + case 940: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3535 +//line sql.y:3563 { skipToEnd(yylex) } - case 934: + case 941: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3539 +//line sql.y:3567 { skipToEnd(yylex) } - case 935: + case 942: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3543 +//line sql.y:3571 { skipToEnd(yylex) } diff --git a/go/vt/sqlparser/sql.y b/go/vt/sqlparser/sql.y index 10b363b3065..f26b31d6cad 100644 --- a/go/vt/sqlparser/sql.y +++ b/go/vt/sqlparser/sql.y @@ -121,6 +121,7 @@ func skipToEnd(yylex interface{}) { %left UNION %token SELECT STREAM INSERT UPDATE DELETE FROM WHERE GROUP HAVING ORDER BY LIMIT OFFSET FOR %token ALL DISTINCT AS EXISTS ASC DESC INTO DUPLICATE KEY DEFAULT SET LOCK UNLOCK KEYS +%token DISTINCTROW %token VALUES LAST_INSERT_ID %token NEXT VALUE SHARE MODE %token SQL_NO_CACHE SQL_CACHE @@ -1314,6 +1315,14 @@ alter_statement: { $$ = &DDL{Action: AlterStr, Table: $4, PartitionSpec: $5} } +| ALTER DATABASE ID ddl_skip_to_end + { + $$ = &DBDDL{Action: AlterStr, DBName: string($3)} + } +| ALTER SCHEMA ID ddl_skip_to_end + { + $$ = &DBDDL{Action: AlterStr, DBName: string($3)} + } | ALTER VSCHEMA CREATE VINDEX table_name vindex_type_opt vindex_params_opt { $$ = &DDL{ @@ -1493,13 +1502,15 @@ show_statement: $$ = &Show{Type: string($2) + " " + string($3)} } /* SHOW CHARACTER SET and SHOW CHARSET are equivalent */ -| SHOW CHARACTER SET ddl_skip_to_end +| SHOW CHARACTER SET like_or_where_opt { - $$ = &Show{Type: CharsetStr} + showTablesOpt := &ShowTablesOpt{Filter: $4} + $$ = &Show{Type: CharsetStr, ShowTablesOpt: showTablesOpt} } -| SHOW CHARSET ddl_skip_to_end +| SHOW CHARSET like_or_where_opt { - $$ = &Show{Type: string($2)} + showTablesOpt := &ShowTablesOpt{Filter: $3} + $$ = &Show{Type: string($2), ShowTablesOpt: showTablesOpt} } | SHOW CREATE DATABASE ddl_skip_to_end { @@ -1826,6 +1837,10 @@ distinct_opt: { $$ = DistinctStr } +| DISTINCTROW + { + $$ = DistinctStr + } straight_join_opt: { @@ -2120,6 +2135,10 @@ index_hint_list: { $$ = &IndexHints{Type: UseStr, Indexes: $4} } +| USE INDEX openb closeb + { + $$ = &IndexHints{Type: UseStr} + } | IGNORE INDEX openb column_list closeb { $$ = &IndexHints{Type: IgnoreStr, Indexes: $4} @@ -2474,6 +2493,10 @@ function_call_generic: { $$ = &FuncExpr{Name: $1, Distinct: true, Exprs: $4} } +| sql_id openb DISTINCTROW select_expression_list closeb + { + $$ = &FuncExpr{Name: $1, Distinct: true, Exprs: $4} + } | table_id '.' reserved_sql_id openb select_expression_list_opt closeb { $$ = &FuncExpr{Qualifier: $1, Name: $3, Exprs: $5} @@ -2524,9 +2547,9 @@ function_call_keyword: { $$ = &MatchExpr{Columns: $3, Expr: $7, Option: $8} } -| GROUP_CONCAT openb distinct_opt select_expression_list order_by_opt separator_opt closeb +| GROUP_CONCAT openb distinct_opt select_expression_list order_by_opt separator_opt limit_opt closeb { - $$ = &GroupConcatExpr{Distinct: $3, Exprs: $4, OrderBy: $5, Separator: $6} + $$ = &GroupConcatExpr{Distinct: $3, Exprs: $4, OrderBy: $5, Separator: $6, Limit: $7} } | CASE expression_opt when_expression_list else_expression_opt END { @@ -2640,6 +2663,10 @@ function_call_conflict: { $$ = &FuncExpr{Name: NewColIdent("database"), Exprs: $3} } +| SCHEMA openb select_expression_list_opt closeb + { + $$ = &FuncExpr{Name: NewColIdent("schema"), Exprs: $3} + } | MOD openb select_expression_list closeb { $$ = &FuncExpr{Name: NewColIdent("mod"), Exprs: $3} @@ -3243,6 +3270,7 @@ reserved_keyword: | DESC | DESCRIBE | DISTINCT +| DISTINCTROW | DIV | DROP | ELSE diff --git a/go/vt/sqlparser/token.go b/go/vt/sqlparser/token.go index f7fd4850f30..e6d59753920 100644 --- a/go/vt/sqlparser/token.go +++ b/go/vt/sqlparser/token.go @@ -18,7 +18,6 @@ package sqlparser import ( "bytes" - "errors" "fmt" "io" @@ -156,7 +155,7 @@ var keywords = map[string]int{ "describe": DESCRIBE, "deterministic": UNUSED, "distinct": DISTINCT, - "distinctrow": UNUSED, + "distinctrow": DISTINCTROW, "div": DIV, "double": DOUBLE, "drop": DROP, @@ -452,15 +451,23 @@ func (tkn *Tokenizer) Lex(lval *yySymType) int { return typ } +// PositionedErr holds context related to parser errors +type PositionedErr struct { + Err string + Pos int + Near []byte +} + +func (p PositionedErr) Error() string { + if p.Near != nil { + return fmt.Sprintf("%s at position %v near '%s'", p.Err, p.Pos, p.Near) + } + return fmt.Sprintf("%s at position %v", p.Err, p.Pos) +} + // Error is called by go yacc if there's a parsing error. func (tkn *Tokenizer) Error(err string) { - buf := &bytes2.Buffer{} - if tkn.lastToken != nil { - fmt.Fprintf(buf, "%s at position %v near '%s'", err, tkn.Position, tkn.lastToken) - } else { - fmt.Fprintf(buf, "%s at position %v", err, tkn.Position) - } - tkn.LastError = errors.New(buf.String()) + tkn.LastError = PositionedErr{Err: err, Pos: tkn.Position, Near: tkn.lastToken} // Try and re-sync to the next statement tkn.skipStatement() @@ -654,7 +661,7 @@ func (tkn *Tokenizer) scanIdentifier(firstByte byte, isDbSystemVariable bool) (i lowered := bytes.ToLower(buffer.Bytes()) loweredStr := string(lowered) if keywordID, found := keywords[loweredStr]; found { - return keywordID, lowered + return keywordID, buffer.Bytes() } // dual must always be case-insensitive if loweredStr == "dual" { diff --git a/go/vt/sqlparser/visitorgen/ast_walker.go b/go/vt/sqlparser/visitorgen/ast_walker.go new file mode 100644 index 00000000000..822fb6c4c5e --- /dev/null +++ b/go/vt/sqlparser/visitorgen/ast_walker.go @@ -0,0 +1,130 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package visitorgen + +import ( + "go/ast" + "reflect" +) + +var _ ast.Visitor = (*walker)(nil) + +type walker struct { + result SourceFile +} + +// Walk walks the given AST and translates it to the simplified AST used by the next steps +func Walk(node ast.Node) *SourceFile { + var w walker + ast.Walk(&w, node) + return &w.result +} + +// Visit implements the ast.Visitor interface +func (w *walker) Visit(node ast.Node) ast.Visitor { + switch n := node.(type) { + case *ast.TypeSpec: + switch t2 := n.Type.(type) { + case *ast.InterfaceType: + w.append(&InterfaceDeclaration{ + name: n.Name.Name, + block: "", + }) + case *ast.StructType: + var fields []*Field + for _, f := range t2.Fields.List { + for _, name := range f.Names { + fields = append(fields, &Field{ + name: name.Name, + typ: sastType(f.Type), + }) + } + + } + w.append(&StructDeclaration{ + name: n.Name.Name, + fields: fields, + }) + case *ast.ArrayType: + w.append(&TypeAlias{ + name: n.Name.Name, + typ: &Array{inner: sastType(t2.Elt)}, + }) + case *ast.Ident: + w.append(&TypeAlias{ + name: n.Name.Name, + typ: &TypeString{t2.Name}, + }) + + default: + panic(reflect.TypeOf(t2)) + } + case *ast.FuncDecl: + if len(n.Recv.List) > 1 || len(n.Recv.List[0].Names) > 1 { + panic("don't know what to do!") + } + var f *Field + if len(n.Recv.List) == 1 { + r := n.Recv.List[0] + t := sastType(r.Type) + if len(r.Names) > 1 { + panic("don't know what to do!") + } + if len(r.Names) == 1 { + f = &Field{ + name: r.Names[0].Name, + typ: t, + } + } else { + f = &Field{ + name: "", + typ: t, + } + } + } + + w.append(&FuncDeclaration{ + receiver: f, + name: n.Name.Name, + block: "", + arguments: nil, + }) + } + + return w +} + +func (w *walker) append(line Sast) { + w.result.lines = append(w.result.lines, line) +} + +func sastType(e ast.Expr) Type { + switch n := e.(type) { + case *ast.StarExpr: + return &Ref{sastType(n.X)} + case *ast.Ident: + return &TypeString{n.Name} + case *ast.ArrayType: + return &Array{inner: sastType(n.Elt)} + case *ast.InterfaceType: + return &TypeString{"interface{}"} + case *ast.StructType: + return &TypeString{"struct{}"} + } + + panic(reflect.TypeOf(e)) +} diff --git a/go/vt/sqlparser/visitorgen/ast_walker_test.go b/go/vt/sqlparser/visitorgen/ast_walker_test.go new file mode 100644 index 00000000000..a4b01f70835 --- /dev/null +++ b/go/vt/sqlparser/visitorgen/ast_walker_test.go @@ -0,0 +1,239 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package visitorgen + +import ( + "go/parser" + "go/token" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/stretchr/testify/require" +) + +func TestSingleInterface(t *testing.T) { + input := ` +package sqlparser + +type Nodeiface interface { + iNode() +} +` + + fset := token.NewFileSet() + ast, err := parser.ParseFile(fset, "ast.go", input, 0) + require.NoError(t, err) + + result := Walk(ast) + expected := SourceFile{ + lines: []Sast{&InterfaceDeclaration{ + name: "Nodeiface", + block: "", + }}, + } + assert.Equal(t, expected.String(), result.String()) +} + +func TestEmptyStruct(t *testing.T) { + input := ` +package sqlparser + +type Empty struct {} +` + + fset := token.NewFileSet() + ast, err := parser.ParseFile(fset, "ast.go", input, 0) + require.NoError(t, err) + + result := Walk(ast) + expected := SourceFile{ + lines: []Sast{&StructDeclaration{ + name: "Empty", + fields: []*Field{}, + }}, + } + assert.Equal(t, expected.String(), result.String()) +} + +func TestStructWithStringField(t *testing.T) { + input := ` +package sqlparser + +type Struct struct { + field string +} +` + + fset := token.NewFileSet() + ast, err := parser.ParseFile(fset, "ast.go", input, 0) + require.NoError(t, err) + + result := Walk(ast) + expected := SourceFile{ + lines: []Sast{&StructDeclaration{ + name: "Struct", + fields: []*Field{{ + name: "field", + typ: &TypeString{typName: "string"}, + }}, + }}, + } + assert.Equal(t, expected.String(), result.String()) +} + +func TestStructWithDifferentTypes(t *testing.T) { + input := ` +package sqlparser + +type Struct struct { + field string + reference *string + array []string + arrayOfRef []*string +} +` + + fset := token.NewFileSet() + ast, err := parser.ParseFile(fset, "ast.go", input, 0) + require.NoError(t, err) + + result := Walk(ast) + expected := SourceFile{ + lines: []Sast{&StructDeclaration{ + name: "Struct", + fields: []*Field{{ + name: "field", + typ: &TypeString{typName: "string"}, + }, { + name: "reference", + typ: &Ref{&TypeString{typName: "string"}}, + }, { + name: "array", + typ: &Array{&TypeString{typName: "string"}}, + }, { + name: "arrayOfRef", + typ: &Array{&Ref{&TypeString{typName: "string"}}}, + }}, + }}, + } + assert.Equal(t, expected.String(), result.String()) +} + +func TestStructWithTwoStringFieldInOneLine(t *testing.T) { + input := ` +package sqlparser + +type Struct struct { + left, right string +} +` + + fset := token.NewFileSet() + ast, err := parser.ParseFile(fset, "ast.go", input, 0) + require.NoError(t, err) + + result := Walk(ast) + expected := SourceFile{ + lines: []Sast{&StructDeclaration{ + name: "Struct", + fields: []*Field{{ + name: "left", + typ: &TypeString{typName: "string"}, + }, { + name: "right", + typ: &TypeString{typName: "string"}, + }}, + }}, + } + assert.Equal(t, expected.String(), result.String()) +} + +func TestStructWithSingleMethod(t *testing.T) { + input := ` +package sqlparser + +type Empty struct {} + +func (*Empty) method() {} +` + + fset := token.NewFileSet() + ast, err := parser.ParseFile(fset, "ast.go", input, 0) + require.NoError(t, err) + + result := Walk(ast) + expected := SourceFile{ + lines: []Sast{ + &StructDeclaration{ + name: "Empty", + fields: []*Field{}}, + &FuncDeclaration{ + receiver: &Field{ + name: "", + typ: &Ref{&TypeString{"Empty"}}, + }, + name: "method", + block: "", + arguments: []*Field{}, + }, + }, + } + assert.Equal(t, expected.String(), result.String()) +} + +func TestSingleArrayType(t *testing.T) { + input := ` +package sqlparser + +type Strings []string +` + + fset := token.NewFileSet() + ast, err := parser.ParseFile(fset, "ast.go", input, 0) + require.NoError(t, err) + + result := Walk(ast) + expected := SourceFile{ + lines: []Sast{&TypeAlias{ + name: "Strings", + typ: &Array{&TypeString{"string"}}, + }}, + } + assert.Equal(t, expected.String(), result.String()) +} + +func TestSingleTypeAlias(t *testing.T) { + input := ` +package sqlparser + +type String string +` + + fset := token.NewFileSet() + ast, err := parser.ParseFile(fset, "ast.go", input, 0) + require.NoError(t, err) + + result := Walk(ast) + expected := SourceFile{ + lines: []Sast{&TypeAlias{ + name: "String", + typ: &TypeString{"string"}, + }}, + } + assert.Equal(t, expected.String(), result.String()) +} diff --git a/go/vt/sqlparser/visitorgen/main/main.go b/go/vt/sqlparser/visitorgen/main/main.go new file mode 100644 index 00000000000..0d940ea060f --- /dev/null +++ b/go/vt/sqlparser/visitorgen/main/main.go @@ -0,0 +1,164 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package main + +import ( + "bytes" + "flag" + "fmt" + "go/parser" + "go/token" + "io/ioutil" + "os" + + "vitess.io/vitess/go/exit" + "vitess.io/vitess/go/vt/log" + + "vitess.io/vitess/go/vt/sqlparser/visitorgen" +) + +var ( + inputFile = flag.String("input", "", "input file to use") + outputFile = flag.String("output", "", "output file") + compare = flag.Bool("compareOnly", false, "instead of writing to the output file, compare if the generated visitor is still valid for this ast.go") +) + +const usage = `Usage of visitorgen: + +go run /path/to/visitorgen/main -input=/path/to/ast.go -output=/path/to/rewriter.go +` + +func main() { + defer exit.Recover() + flag.Usage = printUsage + flag.Parse() + + if *inputFile == "" || *outputFile == "" { + printUsage() + exit.Return(1) + } + + fs := token.NewFileSet() + file, err := parser.ParseFile(fs, *inputFile, nil, parser.DeclarationErrors) + if err != nil { + log.Error(err) + exit.Return(1) + } + + astWalkResult := visitorgen.Walk(file) + vp := visitorgen.Transform(astWalkResult) + vd := visitorgen.ToVisitorPlan(vp) + + replacementMethods := visitorgen.EmitReplacementMethods(vd) + typeSwitch := visitorgen.EmitTypeSwitches(vd) + + b := &bytes.Buffer{} + fmt.Fprint(b, fileHeader) + fmt.Fprintln(b) + fmt.Fprintln(b, replacementMethods) + fmt.Fprint(b, applyHeader) + fmt.Fprintln(b, typeSwitch) + fmt.Fprintln(b, fileFooter) + + if *compare { + currentFile, err := ioutil.ReadFile(*outputFile) + if err != nil { + log.Error(err) + exit.Return(1) + } + if !bytes.Equal(b.Bytes(), currentFile) { + fmt.Println("rewriter needs to be re-generated: go generate " + *outputFile) + exit.Return(1) + } + } else { + err = ioutil.WriteFile(*outputFile, b.Bytes(), 0644) + if err != nil { + log.Error(err) + exit.Return(1) + } + } + +} + +func printUsage() { + os.Stderr.WriteString(usage) + os.Stderr.WriteString("\nOptions:\n") + flag.PrintDefaults() +} + +const fileHeader = `// Code generated by visitorgen/main/main.go. DO NOT EDIT. + +package sqlparser + +//go:generate go run ./visitorgen/main -input=ast.go -output=rewriter.go + +import ( + "reflect" +) + +type replacerFunc func(newNode, parent SQLNode) + +// application carries all the shared data so we can pass it around cheaply. +type application struct { + pre, post ApplyFunc + cursor Cursor +} +` + +const applyHeader = ` +// apply is where the visiting happens. Here is where we keep the big switch-case that will be used +// to do the actual visiting of SQLNodes +func (a *application) apply(parent, node SQLNode, replacer replacerFunc) { + if node == nil || isNilValue(node) { + return + } + + // avoid heap-allocating a new cursor for each apply call; reuse a.cursor instead + saved := a.cursor + a.cursor.replacer = replacer + a.cursor.node = node + a.cursor.parent = parent + + if a.pre != nil && !a.pre(&a.cursor) { + a.cursor = saved + return + } + + // walk children + // (the order of the cases is alphabetical) + switch n := node.(type) { + case nil: + ` + +const fileFooter = ` + default: + panic("unknown ast type " + reflect.TypeOf(node).String()) + } + + if a.post != nil && !a.post(&a.cursor) { + panic(abort) + } + + a.cursor = saved +} + +func isNilValue(i interface{}) bool { + valueOf := reflect.ValueOf(i) + kind := valueOf.Kind() + isNullable := kind == reflect.Ptr || kind == reflect.Array || kind == reflect.Slice + return isNullable && valueOf.IsNil() +}` diff --git a/go/vt/sqlparser/visitorgen/sast.go b/go/vt/sqlparser/visitorgen/sast.go new file mode 100644 index 00000000000..e46485e8f5d --- /dev/null +++ b/go/vt/sqlparser/visitorgen/sast.go @@ -0,0 +1,178 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package visitorgen + +// simplified ast - when reading the golang ast of the ast.go file, we translate the golang ast objects +// to this much simpler format, that contains only the necessary information and no more +type ( + // SourceFile contains all important lines from an ast.go file + SourceFile struct { + lines []Sast + } + + // Sast or simplified AST, is a representation of the ast.go lines we are interested in + Sast interface { + toSastString() string + } + + // InterfaceDeclaration represents a declaration of an interface. This is used to keep track of which types + // need to be handled by the visitor framework + InterfaceDeclaration struct { + name, block string + } + + // TypeAlias is used whenever we see a `type XXX YYY` - XXX is the new name for YYY. + // Note that YYY could be an array or a reference + TypeAlias struct { + name string + typ Type + } + + // FuncDeclaration represents a function declaration. These are tracked to know which types implement interfaces. + FuncDeclaration struct { + receiver *Field + name, block string + arguments []*Field + } + + // StructDeclaration represents a struct. It contains the fields and their types + StructDeclaration struct { + name string + fields []*Field + } + + // Field is a field in a struct - a name with a type tuple + Field struct { + name string + typ Type + } + + // Type represents a type in the golang type system. Used to keep track of type we need to handle, + // and the types of fields. + Type interface { + toTypString() string + rawTypeName() string + } + + // TypeString is a raw type name, such as `string` + TypeString struct { + typName string + } + + // Ref is a reference to something, such as `*string` + Ref struct { + inner Type + } + + // Array is an array of things, such as `[]string` + Array struct { + inner Type + } +) + +var _ Sast = (*InterfaceDeclaration)(nil) +var _ Sast = (*StructDeclaration)(nil) +var _ Sast = (*FuncDeclaration)(nil) +var _ Sast = (*TypeAlias)(nil) + +var _ Type = (*TypeString)(nil) +var _ Type = (*Ref)(nil) +var _ Type = (*Array)(nil) + +// String returns a textual representation of the SourceFile. This is for testing purposed +func (t *SourceFile) String() string { + var result string + for _, l := range t.lines { + result += l.toSastString() + result += "\n" + } + + return result +} + +func (t *Ref) toTypString() string { + return "*" + t.inner.toTypString() +} + +func (t *Array) toTypString() string { + return "[]" + t.inner.toTypString() +} + +func (t *TypeString) toTypString() string { + return t.typName +} + +func (f *FuncDeclaration) toSastString() string { + var receiver string + if f.receiver != nil { + receiver = "(" + f.receiver.String() + ") " + } + var args string + for i, arg := range f.arguments { + if i > 0 { + args += ", " + } + args += arg.String() + } + + return "func " + receiver + f.name + "(" + args + ") {" + blockInNewLines(f.block) + "}" +} + +func (i *InterfaceDeclaration) toSastString() string { + return "type " + i.name + " interface {" + blockInNewLines(i.block) + "}" +} + +func (a *TypeAlias) toSastString() string { + return "type " + a.name + " " + a.typ.toTypString() +} + +func (s *StructDeclaration) toSastString() string { + var block string + for _, f := range s.fields { + block += "\t" + f.String() + "\n" + } + + return "type " + s.name + " struct {" + blockInNewLines(block) + "}" +} + +func blockInNewLines(block string) string { + if block == "" { + return "" + } + return "\n" + block + "\n" +} + +// String returns a string representation of a field +func (f *Field) String() string { + if f.name != "" { + return f.name + " " + f.typ.toTypString() + } + + return f.typ.toTypString() +} + +func (t *TypeString) rawTypeName() string { + return t.typName +} + +func (t *Ref) rawTypeName() string { + return t.inner.rawTypeName() +} + +func (t *Array) rawTypeName() string { + return t.inner.rawTypeName() +} diff --git a/go/vt/sqlparser/visitorgen/struct_producer.go b/go/vt/sqlparser/visitorgen/struct_producer.go new file mode 100644 index 00000000000..1c293f30803 --- /dev/null +++ b/go/vt/sqlparser/visitorgen/struct_producer.go @@ -0,0 +1,253 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package visitorgen + +import ( + "fmt" + "sort" +) + +// VisitorData is the data needed to produce the output file +type ( + // VisitorItem represents something that needs to be added to the rewriter infrastructure + VisitorItem interface { + toFieldItemString() string + typeName() string + asSwitchCase() string + asReplMethod() string + getFieldName() string + } + + // SingleFieldItem is a single field in a struct + SingleFieldItem struct { + StructType, FieldType Type + FieldName string + } + + // ArrayFieldItem is an array field in a struct + ArrayFieldItem struct { + StructType, ItemType Type + FieldName string + } + + // ArrayItem is an array that implements SQLNode + ArrayItem struct { + StructType, ItemType Type + } + + // VisitorPlan represents all the output needed for the rewriter + VisitorPlan struct { + Switches []*SwitchCase // The cases for the big switch statement used to implement the visitor + } + + // SwitchCase is what we need to know to produce all the type switch cases in the visitor. + SwitchCase struct { + Type Type + Fields []VisitorItem + } +) + +var _ VisitorItem = (*SingleFieldItem)(nil) +var _ VisitorItem = (*ArrayItem)(nil) +var _ VisitorItem = (*ArrayFieldItem)(nil) +var _ sort.Interface = (*VisitorPlan)(nil) +var _ sort.Interface = (*SwitchCase)(nil) + +// ToVisitorPlan transforms the source information into a plan for the visitor code that needs to be produced +func ToVisitorPlan(input *SourceInformation) *VisitorPlan { + var output VisitorPlan + + for _, typ := range input.interestingTypes { + switchit := &SwitchCase{Type: typ} + stroct, isStruct := input.structs[typ.rawTypeName()] + if isStruct { + for _, f := range stroct.fields { + switchit.Fields = append(switchit.Fields, trySingleItem(input, f, typ)...) + } + } else { + itemType := input.getItemTypeOfArray(typ) + if itemType != nil && input.isSQLNode(itemType) { + switchit.Fields = append(switchit.Fields, &ArrayItem{ + StructType: typ, + ItemType: itemType, + }) + } + } + sort.Sort(switchit) + output.Switches = append(output.Switches, switchit) + } + sort.Sort(&output) + return &output +} + +func trySingleItem(input *SourceInformation, f *Field, typ Type) []VisitorItem { + if input.isSQLNode(f.typ) { + return []VisitorItem{&SingleFieldItem{ + StructType: typ, + FieldType: f.typ, + FieldName: f.name, + }} + } + + arrType, isArray := f.typ.(*Array) + if isArray && input.isSQLNode(arrType.inner) { + return []VisitorItem{&ArrayFieldItem{ + StructType: typ, + ItemType: arrType.inner, + FieldName: f.name, + }} + } + return []VisitorItem{} +} + +// String returns a string, used for testing +func (v *VisitorPlan) String() string { + var sb builder + for _, s := range v.Switches { + sb.appendF("Type: %v", s.Type.toTypString()) + for _, f := range s.Fields { + sb.appendF("\t%v", f.toFieldItemString()) + } + } + return sb.String() +} + +func (s *SingleFieldItem) toFieldItemString() string { + return fmt.Sprintf("single item: %v of type: %v", s.FieldName, s.FieldType.toTypString()) +} + +func (s *SingleFieldItem) asSwitchCase() string { + return fmt.Sprintf(` a.apply(node, n.%s, %s)`, s.FieldName, s.typeName()) +} + +func (s *SingleFieldItem) asReplMethod() string { + _, isRef := s.StructType.(*Ref) + + if isRef { + return fmt.Sprintf(`func %s(newNode, parent SQLNode) { + parent.(%s).%s = newNode.(%s) +}`, s.typeName(), s.StructType.toTypString(), s.FieldName, s.FieldType.toTypString()) + } + + return fmt.Sprintf(`func %s(newNode, parent SQLNode) { + tmp := parent.(%s) + tmp.%s = newNode.(%s) +}`, s.typeName(), s.StructType.toTypString(), s.FieldName, s.FieldType.toTypString()) + +} + +func (ai *ArrayItem) asReplMethod() string { + name := ai.typeName() + return fmt.Sprintf(`type %s int + +func (r *%s) replace(newNode, container SQLNode) { + container.(%s)[int(*r)] = newNode.(%s) +} + +func (r *%s) inc() { + *r++ +}`, name, name, ai.StructType.toTypString(), ai.ItemType.toTypString(), name) +} + +func (afi *ArrayFieldItem) asReplMethod() string { + name := afi.typeName() + return fmt.Sprintf(`type %s int + +func (r *%s) replace(newNode, container SQLNode) { + container.(%s).%s[int(*r)] = newNode.(%s) +} + +func (r *%s) inc() { + *r++ +}`, name, name, afi.StructType.toTypString(), afi.FieldName, afi.ItemType.toTypString(), name) +} + +func (s *SingleFieldItem) getFieldName() string { + return s.FieldName +} + +func (s *SingleFieldItem) typeName() string { + return "replace" + s.StructType.rawTypeName() + s.FieldName +} + +func (afi *ArrayFieldItem) toFieldItemString() string { + return fmt.Sprintf("array field item: %v.%v contains items of type %v", afi.StructType.toTypString(), afi.FieldName, afi.ItemType.toTypString()) +} + +func (ai *ArrayItem) toFieldItemString() string { + return fmt.Sprintf("array item: %v containing items of type %v", ai.StructType.toTypString(), ai.ItemType.toTypString()) +} + +func (ai *ArrayItem) getFieldName() string { + panic("Should not be called!") +} + +func (afi *ArrayFieldItem) getFieldName() string { + return afi.FieldName +} + +func (ai *ArrayItem) asSwitchCase() string { + return fmt.Sprintf(` replacer := %s(0) + replacerRef := &replacer + for _, item := range n { + a.apply(node, item, replacerRef.replace) + replacerRef.inc() + }`, ai.typeName()) +} + +func (afi *ArrayFieldItem) asSwitchCase() string { + return fmt.Sprintf(` replacer%s := %s(0) + replacer%sB := &replacer%s + for _, item := range n.%s { + a.apply(node, item, replacer%sB.replace) + replacer%sB.inc() + }`, afi.FieldName, afi.typeName(), afi.FieldName, afi.FieldName, afi.FieldName, afi.FieldName, afi.FieldName) +} + +func (ai *ArrayItem) typeName() string { + return "replace" + ai.StructType.rawTypeName() + "Items" +} + +func (afi *ArrayFieldItem) typeName() string { + return "replace" + afi.StructType.rawTypeName() + afi.FieldName +} +func (v *VisitorPlan) Len() int { + return len(v.Switches) +} + +func (v *VisitorPlan) Less(i, j int) bool { + return v.Switches[i].Type.rawTypeName() < v.Switches[j].Type.rawTypeName() +} + +func (v *VisitorPlan) Swap(i, j int) { + temp := v.Switches[i] + v.Switches[i] = v.Switches[j] + v.Switches[j] = temp +} +func (s *SwitchCase) Len() int { + return len(s.Fields) +} + +func (s *SwitchCase) Less(i, j int) bool { + return s.Fields[i].getFieldName() < s.Fields[j].getFieldName() +} + +func (s *SwitchCase) Swap(i, j int) { + temp := s.Fields[i] + s.Fields[i] = s.Fields[j] + s.Fields[j] = temp +} diff --git a/go/vt/sqlparser/visitorgen/struct_producer_test.go b/go/vt/sqlparser/visitorgen/struct_producer_test.go new file mode 100644 index 00000000000..065b532a9eb --- /dev/null +++ b/go/vt/sqlparser/visitorgen/struct_producer_test.go @@ -0,0 +1,423 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package visitorgen + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestEmptyStructVisitor(t *testing.T) { + /* + type Node interface{} + type Struct struct {} + func (*Struct) iNode() {} + */ + + input := &SourceInformation{ + interestingTypes: map[string]Type{ + "*Struct": &Ref{&TypeString{"Struct"}}, + }, + interfaces: map[string]bool{ + "Node": true, + }, + structs: map[string]*StructDeclaration{ + "Struct": {name: "Struct", fields: []*Field{}}, + }, + typeAliases: map[string]*TypeAlias{}, + } + + result := ToVisitorPlan(input) + + expected := &VisitorPlan{ + Switches: []*SwitchCase{{ + Type: &Ref{&TypeString{"Struct"}}, + Fields: []VisitorItem{}, + }}, + } + + assert.Equal(t, expected.String(), result.String()) +} + +func TestStructWithSqlNodeField(t *testing.T) { + /* + type Node interface{} + type Struct struct { + Field Node + } + func (*Struct) iNode() {} + */ + input := &SourceInformation{ + interestingTypes: map[string]Type{ + "*Struct": &Ref{&TypeString{"Struct"}}, + }, + interfaces: map[string]bool{ + "Node": true, + }, + structs: map[string]*StructDeclaration{ + "Struct": {name: "Struct", fields: []*Field{ + {name: "Field", typ: &TypeString{"Node"}}, + }}, + }, + typeAliases: map[string]*TypeAlias{}, + } + + result := ToVisitorPlan(input) + + expected := &VisitorPlan{ + Switches: []*SwitchCase{{ + Type: &Ref{&TypeString{"Struct"}}, + Fields: []VisitorItem{&SingleFieldItem{ + StructType: &Ref{&TypeString{"Struct"}}, + FieldType: &TypeString{"Node"}, + FieldName: "Field", + }}, + }}, + } + + assert.Equal(t, expected.String(), result.String()) +} + +func TestStructWithStringField2(t *testing.T) { + /* + type Node interface{} + type Struct struct { + Field Node + } + func (*Struct) iNode() {} + */ + + input := &SourceInformation{ + interestingTypes: map[string]Type{ + "*Struct": &Ref{&TypeString{"Struct"}}, + }, + interfaces: map[string]bool{ + "Node": true, + }, + structs: map[string]*StructDeclaration{ + "Struct": {name: "Struct", fields: []*Field{ + {name: "Field", typ: &TypeString{"string"}}, + }}, + }, + typeAliases: map[string]*TypeAlias{}, + } + + result := ToVisitorPlan(input) + + expected := &VisitorPlan{ + Switches: []*SwitchCase{{ + Type: &Ref{&TypeString{"Struct"}}, + Fields: []VisitorItem{}, + }}, + } + + assert.Equal(t, expected.String(), result.String()) +} + +func TestArrayAsSqlNode(t *testing.T) { + /* + type NodeInterface interface { + iNode() + } + + func (*NodeArray) iNode{} + + type NodeArray []NodeInterface + */ + + input := &SourceInformation{ + interfaces: map[string]bool{"NodeInterface": true}, + interestingTypes: map[string]Type{ + "*NodeArray": &Ref{&TypeString{"NodeArray"}}}, + structs: map[string]*StructDeclaration{}, + typeAliases: map[string]*TypeAlias{ + "NodeArray": { + name: "NodeArray", + typ: &Array{&TypeString{"NodeInterface"}}, + }, + }, + } + + result := ToVisitorPlan(input) + + expected := &VisitorPlan{ + Switches: []*SwitchCase{{ + Type: &Ref{&TypeString{"NodeArray"}}, + Fields: []VisitorItem{&ArrayItem{ + StructType: &Ref{&TypeString{"NodeArray"}}, + ItemType: &TypeString{"NodeInterface"}, + }}, + }}, + } + + assert.Equal(t, expected.String(), result.String()) +} + +func TestStructWithStructField(t *testing.T) { + /* + type Node interface{} + type Struct struct { + Field *Struct + } + func (*Struct) iNode() {} + */ + + input := &SourceInformation{ + interestingTypes: map[string]Type{ + "*Struct": &Ref{&TypeString{"Struct"}}}, + structs: map[string]*StructDeclaration{ + "Struct": {name: "Struct", fields: []*Field{ + {name: "Field", typ: &Ref{&TypeString{"Struct"}}}, + }}, + }, + typeAliases: map[string]*TypeAlias{}, + } + + result := ToVisitorPlan(input) + + expected := &VisitorPlan{ + Switches: []*SwitchCase{{ + Type: &Ref{&TypeString{"Struct"}}, + Fields: []VisitorItem{&SingleFieldItem{ + StructType: &Ref{&TypeString{"Struct"}}, + FieldType: &Ref{&TypeString{"Struct"}}, + FieldName: "Field", + }}, + }}, + } + + assert.Equal(t, expected.String(), result.String()) +} + +func TestStructWithArrayOfNodes(t *testing.T) { + /* + type NodeInterface interface {} + type Struct struct { + Items []NodeInterface + } + + func (*Struct) iNode{} + */ + + input := &SourceInformation{ + interfaces: map[string]bool{ + "NodeInterface": true, + }, + interestingTypes: map[string]Type{ + "*Struct": &Ref{&TypeString{"Struct"}}}, + structs: map[string]*StructDeclaration{ + "Struct": {name: "Struct", fields: []*Field{ + {name: "Items", typ: &Array{&TypeString{"NodeInterface"}}}, + }}, + }, + typeAliases: map[string]*TypeAlias{}, + } + + result := ToVisitorPlan(input) + + expected := &VisitorPlan{ + Switches: []*SwitchCase{{ + Type: &Ref{&TypeString{"Struct"}}, + Fields: []VisitorItem{&ArrayFieldItem{ + StructType: &Ref{&TypeString{"Struct"}}, + ItemType: &TypeString{"NodeInterface"}, + FieldName: "Items", + }}, + }}, + } + + assert.Equal(t, expected.String(), result.String()) +} + +func TestStructWithArrayOfStrings(t *testing.T) { + /* + type NodeInterface interface {} + type Struct struct { + Items []string + } + + func (*Struct) iNode{} + */ + + input := &SourceInformation{ + interfaces: map[string]bool{ + "NodeInterface": true, + }, + interestingTypes: map[string]Type{ + "*Struct": &Ref{&TypeString{"Struct"}}}, + structs: map[string]*StructDeclaration{ + "Struct": {name: "Struct", fields: []*Field{ + {name: "Items", typ: &Array{&TypeString{"string"}}}, + }}, + }, + typeAliases: map[string]*TypeAlias{}, + } + + result := ToVisitorPlan(input) + + expected := &VisitorPlan{ + Switches: []*SwitchCase{{ + Type: &Ref{&TypeString{"Struct"}}, + Fields: []VisitorItem{}, + }}, + } + + assert.Equal(t, expected.String(), result.String()) +} + +func TestArrayOfStringsThatImplementSQLNode(t *testing.T) { + /* + type NodeInterface interface {} + type Struct []string + func (Struct) iNode{} + */ + + input := &SourceInformation{ + interfaces: map[string]bool{"NodeInterface": true}, + interestingTypes: map[string]Type{"Struct": &Ref{&TypeString{"Struct"}}}, + structs: map[string]*StructDeclaration{}, + typeAliases: map[string]*TypeAlias{ + "Struct": { + name: "Struct", + typ: &Array{&TypeString{"string"}}, + }, + }, + } + + result := ToVisitorPlan(input) + + expected := &VisitorPlan{ + Switches: []*SwitchCase{{ + Type: &Ref{&TypeString{"Struct"}}, + Fields: []VisitorItem{}, + }}, + } + + assert.Equal(t, expected.String(), result.String()) +} + +func TestSortingOfOutputs(t *testing.T) { + /* + type NodeInterface interface {} + type AStruct struct { + AField NodeInterface + BField NodeInterface + } + type BStruct struct { + CField NodeInterface + } + func (*AStruct) iNode{} + func (*BStruct) iNode{} + */ + + input := &SourceInformation{ + interfaces: map[string]bool{"NodeInterface": true}, + interestingTypes: map[string]Type{ + "AStruct": &Ref{&TypeString{"AStruct"}}, + "BStruct": &Ref{&TypeString{"BStruct"}}, + }, + structs: map[string]*StructDeclaration{ + "AStruct": {name: "AStruct", fields: []*Field{ + {name: "BField", typ: &TypeString{"NodeInterface"}}, + {name: "AField", typ: &TypeString{"NodeInterface"}}, + }}, + "BStruct": {name: "BStruct", fields: []*Field{ + {name: "CField", typ: &TypeString{"NodeInterface"}}, + }}, + }, + typeAliases: map[string]*TypeAlias{}, + } + + result := ToVisitorPlan(input) + + expected := &VisitorPlan{ + Switches: []*SwitchCase{ + {Type: &Ref{&TypeString{"AStruct"}}, + Fields: []VisitorItem{ + &SingleFieldItem{ + StructType: &Ref{&TypeString{"AStruct"}}, + FieldType: &TypeString{"NodeInterface"}, + FieldName: "AField", + }, + &SingleFieldItem{ + StructType: &Ref{&TypeString{"AStruct"}}, + FieldType: &TypeString{"NodeInterface"}, + FieldName: "BField", + }}}, + {Type: &Ref{&TypeString{"BStruct"}}, + Fields: []VisitorItem{ + &SingleFieldItem{ + StructType: &Ref{&TypeString{"BStruct"}}, + FieldType: &TypeString{"NodeInterface"}, + FieldName: "CField", + }}}}, + } + assert.Equal(t, expected.String(), result.String()) +} + +func TestAliasOfAlias(t *testing.T) { + /* + type NodeInterface interface { + iNode() + } + + type NodeArray []NodeInterface + type AliasOfAlias NodeArray + + func (NodeArray) iNode{} + func (AliasOfAlias) iNode{} + */ + + input := &SourceInformation{ + interfaces: map[string]bool{"NodeInterface": true}, + interestingTypes: map[string]Type{ + "NodeArray": &TypeString{"NodeArray"}, + "AliasOfAlias": &TypeString{"AliasOfAlias"}, + }, + structs: map[string]*StructDeclaration{}, + typeAliases: map[string]*TypeAlias{ + "NodeArray": { + name: "NodeArray", + typ: &Array{&TypeString{"NodeInterface"}}, + }, + "AliasOfAlias": { + name: "NodeArray", + typ: &TypeString{"NodeArray"}, + }, + }, + } + + result := ToVisitorPlan(input) + + expected := &VisitorPlan{ + Switches: []*SwitchCase{ + {Type: &TypeString{"AliasOfAlias"}, + Fields: []VisitorItem{&ArrayItem{ + StructType: &TypeString{"AliasOfAlias"}, + ItemType: &TypeString{"NodeInterface"}, + }}, + }, + {Type: &TypeString{"NodeArray"}, + Fields: []VisitorItem{&ArrayItem{ + StructType: &TypeString{"NodeArray"}, + ItemType: &TypeString{"NodeInterface"}, + }}, + }}, + } + assert.Equal(t, expected.String(), result.String()) +} diff --git a/go/vt/sqlparser/visitorgen/transformer.go b/go/vt/sqlparser/visitorgen/transformer.go new file mode 100644 index 00000000000..98129be81b1 --- /dev/null +++ b/go/vt/sqlparser/visitorgen/transformer.go @@ -0,0 +1,95 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package visitorgen + +import "fmt" + +// Transform takes an input file and collects the information into an easier to consume format +func Transform(input *SourceFile) *SourceInformation { + interestingTypes := make(map[string]Type) + interfaces := make(map[string]bool) + structs := make(map[string]*StructDeclaration) + typeAliases := make(map[string]*TypeAlias) + + for _, l := range input.lines { + switch line := l.(type) { + case *FuncDeclaration: + interestingTypes[line.receiver.typ.toTypString()] = line.receiver.typ + case *StructDeclaration: + structs[line.name] = line + case *TypeAlias: + typeAliases[line.name] = line + case *InterfaceDeclaration: + interfaces[line.name] = true + } + } + + return &SourceInformation{ + interfaces: interfaces, + interestingTypes: interestingTypes, + structs: structs, + typeAliases: typeAliases, + } +} + +// SourceInformation contains the information from the ast.go file, but in a format that is easier to consume +type SourceInformation struct { + interestingTypes map[string]Type + interfaces map[string]bool + structs map[string]*StructDeclaration + typeAliases map[string]*TypeAlias +} + +func (v *SourceInformation) String() string { + var types string + for _, k := range v.interestingTypes { + types += k.toTypString() + "\n" + } + var structs string + for _, k := range v.structs { + structs += k.toSastString() + "\n" + } + var typeAliases string + for _, k := range v.typeAliases { + typeAliases += k.toSastString() + "\n" + } + + return fmt.Sprintf("Types to build visitor for:\n%s\nStructs with fields: \n%s\nTypeAliases with type: \n%s\n", types, structs, typeAliases) +} + +// getItemTypeOfArray will return nil if the given type is not pointing to a array type. +// If it is an array type, the type of it's items will be returned +func (v *SourceInformation) getItemTypeOfArray(typ Type) Type { + alias := v.typeAliases[typ.rawTypeName()] + if alias == nil { + return nil + } + arrTyp, isArray := alias.typ.(*Array) + if !isArray { + return v.getItemTypeOfArray(alias.typ) + } + return arrTyp.inner +} + +func (v *SourceInformation) isSQLNode(typ Type) bool { + _, isInteresting := v.interestingTypes[typ.toTypString()] + if isInteresting { + return true + } + _, isInterface := v.interfaces[typ.toTypString()] + return isInterface +} diff --git a/go/vt/sqlparser/visitorgen/transformer_test.go b/go/vt/sqlparser/visitorgen/transformer_test.go new file mode 100644 index 00000000000..4a0849e9e9c --- /dev/null +++ b/go/vt/sqlparser/visitorgen/transformer_test.go @@ -0,0 +1,110 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package visitorgen + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSimplestAst(t *testing.T) { + /* + type NodeInterface interface { + iNode() + } + + type NodeStruct struct {} + + func (*NodeStruct) iNode{} + */ + input := &SourceFile{ + lines: []Sast{ + &InterfaceDeclaration{ + name: "NodeInterface", + block: "// an interface lives here"}, + &StructDeclaration{ + name: "NodeStruct", + fields: []*Field{}}, + &FuncDeclaration{ + receiver: &Field{ + name: "", + typ: &Ref{&TypeString{"NodeStruct"}}, + }, + name: "iNode", + block: "", + arguments: []*Field{}}, + }, + } + + expected := &SourceInformation{ + interestingTypes: map[string]Type{ + "*NodeStruct": &Ref{&TypeString{"NodeStruct"}}}, + structs: map[string]*StructDeclaration{ + "NodeStruct": { + name: "NodeStruct", + fields: []*Field{}}}, + } + + assert.Equal(t, expected.String(), Transform(input).String()) +} + +func TestAstWithArray(t *testing.T) { + /* + type NodeInterface interface { + iNode() + } + + func (*NodeArray) iNode{} + + type NodeArray []NodeInterface + */ + input := &SourceFile{ + lines: []Sast{ + &InterfaceDeclaration{ + name: "NodeInterface"}, + &TypeAlias{ + name: "NodeArray", + typ: &Array{&TypeString{"NodeInterface"}}, + }, + &FuncDeclaration{ + receiver: &Field{ + name: "", + typ: &Ref{&TypeString{"NodeArray"}}, + }, + name: "iNode", + block: "", + arguments: []*Field{}}, + }, + } + + expected := &SourceInformation{ + interestingTypes: map[string]Type{ + "*NodeArray": &Ref{&TypeString{"NodeArray"}}}, + structs: map[string]*StructDeclaration{}, + typeAliases: map[string]*TypeAlias{ + "NodeArray": { + name: "NodeArray", + typ: &Array{&TypeString{"NodeInterface"}}, + }, + }, + } + + result := Transform(input) + + assert.Equal(t, expected.String(), result.String()) +} diff --git a/go/vt/sqlparser/visitorgen/visitor_emitter.go b/go/vt/sqlparser/visitorgen/visitor_emitter.go new file mode 100644 index 00000000000..889c05fe7f7 --- /dev/null +++ b/go/vt/sqlparser/visitorgen/visitor_emitter.go @@ -0,0 +1,76 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package visitorgen + +import ( + "fmt" + "strings" +) + +// EmitReplacementMethods is an anti-parser (a.k.a prettifier) - it takes a struct that is much like an AST, +// and produces a string from it. This method will produce the replacement methods that make it possible to +// replace objects in fields or in slices. +func EmitReplacementMethods(vd *VisitorPlan) string { + var sb builder + for _, s := range vd.Switches { + for _, k := range s.Fields { + sb.appendF(k.asReplMethod()) + sb.newLine() + } + } + + return sb.String() +} + +// EmitTypeSwitches is an anti-parser (a.k.a prettifier) - it takes a struct that is much like an AST, +// and produces a string from it. This method will produce the switch cases needed to cover the Vitess AST. +func EmitTypeSwitches(vd *VisitorPlan) string { + var sb builder + for _, s := range vd.Switches { + sb.newLine() + sb.appendF(" case %s:", s.Type.toTypString()) + for _, k := range s.Fields { + sb.appendF(k.asSwitchCase()) + } + } + + return sb.String() +} + +func (b *builder) String() string { + return strings.TrimSpace(b.sb.String()) +} + +type builder struct { + sb strings.Builder +} + +func (b *builder) appendF(format string, data ...interface{}) *builder { + _, err := b.sb.WriteString(fmt.Sprintf(format, data...)) + if err != nil { + panic(err) + } + b.newLine() + return b +} + +func (b *builder) newLine() { + _, err := b.sb.WriteString("\n") + if err != nil { + panic(err) + } +} diff --git a/go/vt/sqlparser/visitorgen/visitor_emitter_test.go b/go/vt/sqlparser/visitorgen/visitor_emitter_test.go new file mode 100644 index 00000000000..94666daa743 --- /dev/null +++ b/go/vt/sqlparser/visitorgen/visitor_emitter_test.go @@ -0,0 +1,92 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +package visitorgen + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestSingleItem(t *testing.T) { + sfi := SingleFieldItem{ + StructType: &Ref{&TypeString{"Struct"}}, + FieldType: &TypeString{"string"}, + FieldName: "Field", + } + + expectedReplacer := `func replaceStructField(newNode, parent SQLNode) { + parent.(*Struct).Field = newNode.(string) +}` + + expectedSwitch := ` a.apply(node, n.Field, replaceStructField)` + require.Equal(t, expectedReplacer, sfi.asReplMethod()) + require.Equal(t, expectedSwitch, sfi.asSwitchCase()) +} + +func TestArrayFieldItem(t *testing.T) { + sfi := ArrayFieldItem{ + StructType: &Ref{&TypeString{"Struct"}}, + ItemType: &TypeString{"string"}, + FieldName: "Field", + } + + expectedReplacer := `type replaceStructField int + +func (r *replaceStructField) replace(newNode, container SQLNode) { + container.(*Struct).Field[int(*r)] = newNode.(string) +} + +func (r *replaceStructField) inc() { + *r++ +}` + + expectedSwitch := ` replacerField := replaceStructField(0) + replacerFieldB := &replacerField + for _, item := range n.Field { + a.apply(node, item, replacerFieldB.replace) + replacerFieldB.inc() + }` + require.Equal(t, expectedReplacer, sfi.asReplMethod()) + require.Equal(t, expectedSwitch, sfi.asSwitchCase()) +} + +func TestArrayItem(t *testing.T) { + sfi := ArrayItem{ + StructType: &Ref{&TypeString{"Struct"}}, + ItemType: &TypeString{"string"}, + } + + expectedReplacer := `type replaceStructItems int + +func (r *replaceStructItems) replace(newNode, container SQLNode) { + container.(*Struct)[int(*r)] = newNode.(string) +} + +func (r *replaceStructItems) inc() { + *r++ +}` + + expectedSwitch := ` replacer := replaceStructItems(0) + replacerRef := &replacer + for _, item := range n { + a.apply(node, item, replacerRef.replace) + replacerRef.inc() + }` + require.Equal(t, expectedReplacer, sfi.asReplMethod()) + require.Equal(t, expectedSwitch, sfi.asSwitchCase()) +} diff --git a/go/vt/sqlparser/visitorgen/visitorgen.go b/go/vt/sqlparser/visitorgen/visitorgen.go new file mode 100644 index 00000000000..284f8c4d9be --- /dev/null +++ b/go/vt/sqlparser/visitorgen/visitorgen.go @@ -0,0 +1,33 @@ +/* +Copyright 2019 The Vitess Authors. + +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. +*/ + +//Package visitorgen is responsible for taking the ast.go of Vitess and +//and producing visitor infrastructure for it. +// +//This is accomplished in a few steps. +//Step 1: Walk the AST and collect the interesting information into a format that is +// easy to consume for the next step. The output format is a *SourceFile, that +// contains the needed information in a format that is pretty close to the golang ast, +// but simplified +//Step 2: A SourceFile is packaged into a SourceInformation. SourceInformation is still +// concerned with the input ast - it's just an even more distilled and easy to +// consume format for the last step. This step is performed by the code in transformer.go. +//Step 3: Using the SourceInformation, the struct_producer.go code produces the final data structure +// used, a VisitorPlan. This is focused on the output - it contains a list of all fields or +// arrays that need to be handled by the visitor produced. +//Step 4: The VisitorPlan is lastly turned into a string that is written as the output of +// this whole process. +package visitorgen diff --git a/go/vt/srvtopo/resilient_server.go b/go/vt/srvtopo/resilient_server.go index dce6f3dccda..efd126859e0 100644 --- a/go/vt/srvtopo/resilient_server.go +++ b/go/vt/srvtopo/resilient_server.go @@ -211,11 +211,19 @@ func NewResilientServer(base *topo.Server, counterPrefix string) *ResilientServe log.Fatalf("srv_topo_cache_refresh must be less than or equal to srv_topo_cache_ttl") } + var metric string + + if counterPrefix == "" { + metric = counterPrefix + "Counts" + } else { + metric = "" + } + return &ResilientServer{ topoServer: base, cacheTTL: *srvTopoCacheTTL, cacheRefresh: *srvTopoCacheRefresh, - counts: stats.NewCountersWithSingleLabel(counterPrefix+"Counts", "Resilient srvtopo server operations", "type"), + counts: stats.NewCountersWithSingleLabel(metric, "Resilient srvtopo server operations", "type"), srvKeyspaceNamesCache: make(map[string]*srvKeyspaceNamesEntry), srvKeyspaceCache: make(map[string]*srvKeyspaceEntry), diff --git a/go/vt/srvtopo/resilient_server_flaky_test.go b/go/vt/srvtopo/resilient_server_test.go similarity index 99% rename from go/vt/srvtopo/resilient_server_flaky_test.go rename to go/vt/srvtopo/resilient_server_test.go index ed0cd2bca00..f3571e1adba 100644 --- a/go/vt/srvtopo/resilient_server_flaky_test.go +++ b/go/vt/srvtopo/resilient_server_test.go @@ -312,7 +312,7 @@ func TestGetSrvKeyspace(t *testing.T) { _, err = rs.GetSrvKeyspace(timeoutCtx, "test_cell", "test_ks") wantErr := "timed out waiting for keyspace" if err == nil || err.Error() != wantErr { - t.Errorf("expected error '%v', got '%v'", wantErr, err.Error()) + t.Errorf("expected error '%v', got '%v'", wantErr, err) } factory.Unlock() } diff --git a/go/vt/srvtopo/resolver.go b/go/vt/srvtopo/resolver.go index a7a5043cf3a..981b583f92d 100644 --- a/go/vt/srvtopo/resolver.go +++ b/go/vt/srvtopo/resolver.go @@ -38,8 +38,8 @@ type Resolver struct { // topoServ is the srvtopo.Server to use for topo queries. topoServ Server - // stats provides the health information. - stats TargetStats + // queryService is the actual query service that will be used to execute queries. + queryService queryservice.QueryService // localCell is the local cell for the queries. localCell string @@ -50,11 +50,11 @@ type Resolver struct { } // NewResolver creates a new Resolver. -func NewResolver(topoServ Server, stats TargetStats, localCell string) *Resolver { +func NewResolver(topoServ Server, queryService queryservice.QueryService, localCell string) *Resolver { return &Resolver{ - topoServ: topoServ, - stats: stats, - localCell: localCell, + topoServ: topoServ, + queryService: queryService, + localCell: localCell, } } @@ -130,18 +130,13 @@ func (r *Resolver) GetAllShards(ctx context.Context, keyspace string, tabletType TabletType: tabletType, Cell: r.localCell, } - _, qs, err := r.stats.GetAggregateStats(target) - if err != nil { - return nil, nil, resolverError(err, target) - } - - // FIXME(alainjobart) we ignore the stats for now. + // Right now we always set the Cell to "" // Later we can fallback to another cell if needed. // We would then need to read the SrvKeyspace there too. target.Cell = "" res[i] = &ResolvedShard{ Target: target, - QueryService: qs, + QueryService: r.queryService, } } return res, srvKeyspace, nil @@ -193,19 +188,14 @@ func (r *Resolver) ResolveDestinations(ctx context.Context, keyspace string, tab TabletType: tabletType, Cell: r.localCell, } - _, qs, err := r.stats.GetAggregateStats(target) - if err != nil { - return resolverError(err, target) - } - - // FIXME(alainjobart) we ignore the stats for now. + // Right now we always set the Cell to "" // Later we can fallback to another cell if needed. // We would then need to read the SrvKeyspace there too. target.Cell = "" s = len(result) result = append(result, &ResolvedShard{ Target: target, - QueryService: qs, + QueryService: r.queryService, }) if ids != nil { values = append(values, nil) @@ -247,7 +237,3 @@ func ValuesEqual(vss1, vss2 [][]*querypb.Value) bool { } return true } - -func resolverError(in error, target *querypb.Target) error { - return vterrors.Errorf(vtrpcpb.Code_UNAVAILABLE, "target: %s.%s.%s, no valid tablet: %v", target.Keyspace, target.Shard, topoproto.TabletTypeLString(target.TabletType), in) -} diff --git a/go/vt/srvtopo/resolver_test.go b/go/vt/srvtopo/resolver_test.go index 18b0d0cd6e7..0cc6ce5a9ae 100644 --- a/go/vt/srvtopo/resolver_test.go +++ b/go/vt/srvtopo/resolver_test.go @@ -26,23 +26,12 @@ import ( "vitess.io/vitess/go/vt/logutil" "vitess.io/vitess/go/vt/topo/memorytopo" "vitess.io/vitess/go/vt/topotools" - "vitess.io/vitess/go/vt/vttablet/queryservice" + "vitess.io/vitess/go/vt/vttablet/tabletconntest" querypb "vitess.io/vitess/go/vt/proto/query" topodatapb "vitess.io/vitess/go/vt/proto/topodata" ) -// fakeStats implements TargetStats. -type fakeStats struct{} - -func (s *fakeStats) GetAggregateStats(target *querypb.Target) (*querypb.AggregateStats, queryservice.QueryService, error) { - return &querypb.AggregateStats{}, nil, nil -} - -func (s *fakeStats) GetMasterCell(keyspace, shard string) (cell string, qs queryservice.QueryService, err error) { - return "", nil, nil -} - func initResolver(t *testing.T, name string) *Resolver { ctx := context.Background() cell := "cell1" @@ -79,7 +68,7 @@ func initResolver(t *testing.T, name string) *Resolver { } } - return NewResolver(rs, &fakeStats{}, cell) + return NewResolver(rs, &tabletconntest.FakeQueryService{}, cell) } func TestResolveDestinations(t *testing.T) { diff --git a/go/vt/srvtopo/target_stats.go b/go/vt/srvtopo/target_stats.go index 8dd11763647..e492bd59991 100644 --- a/go/vt/srvtopo/target_stats.go +++ b/go/vt/srvtopo/target_stats.go @@ -20,36 +20,13 @@ import ( "fmt" querypb "vitess.io/vitess/go/vt/proto/query" - "vitess.io/vitess/go/vt/vttablet/queryservice" ) -// TargetStats is an interface that the srvtopo module uses to handle -// routing of queries. -// - discovery.TabletStatsCache will implement the discovery part of the -// interface, and discoverygateway will have the QueryService. -type TargetStats interface { - // GetAggregateStats returns the aggregate stats for the given Target. - // The srvtopo module will use that information to route queries - // to the right cell. Also returns the QueryService to use to - // reach that target. - // Can return topo.ErrNoNode if the target has no stats. - GetAggregateStats(target *querypb.Target) (*querypb.AggregateStats, queryservice.QueryService, error) - - // GetMasterCell returns the master location for a keyspace/shard. - // Since there is only one master for a shard, we only need to - // know its cell to complete the Target. Also returns the QueryService - // to use to reach that target. - GetMasterCell(keyspace, shard string) (cell string, qs queryservice.QueryService, err error) -} - // TargetStatsEntry has the updated information for a Target. type TargetStatsEntry struct { // Target is what this entry applies to. Target *querypb.Target - // Stats is the aggregate stats for this entry. - Stats *querypb.AggregateStats - // TabletExternallyReparentedTimestamp is the latest timestamp // that was reported for this entry. It applies to masters only. TabletExternallyReparentedTimestamp int64 diff --git a/go/vt/tlstest/tlstest.go b/go/vt/tlstest/tlstest.go index 89b715cf523..810aa4c2796 100644 --- a/go/vt/tlstest/tlstest.go +++ b/go/vt/tlstest/tlstest.go @@ -147,3 +147,51 @@ func CreateSignedCert(root, parent, serial, name, commonName string) { "-extfile", config, "-out", cert) } + +type ClientServerKeyPairs struct { + ServerCert string + ServerKey string + ServerCA string + ServerName string + ClientCert string + ClientKey string + ClientCA string +} + +var serialCounter = 0 + +func CreateClientServerCertPairs(root string) ClientServerKeyPairs { + // Create the certs and configs. + CreateCA(root) + + serverSerial := fmt.Sprintf("%03d", serialCounter*2+1) + clientSerial := fmt.Sprintf("%03d", serialCounter*2+2) + + serialCounter = serialCounter + 1 + + serverName := fmt.Sprintf("server-%s", serverSerial) + serverCACommonName := fmt.Sprintf("Server %s CA", serverSerial) + serverCertName := fmt.Sprintf("server-instance-%s", serverSerial) + serverCertCommonName := fmt.Sprintf("server%s.example.com", serverSerial) + + clientName := fmt.Sprintf("clients-%s", serverSerial) + clientCACommonName := fmt.Sprintf("Clients %s CA", serverSerial) + clientCertName := fmt.Sprintf("client-instance-%s", serverSerial) + clientCertCommonName := fmt.Sprintf("Client Instance %s", serverSerial) + + CreateSignedCert(root, CA, serverSerial, serverName, serverCACommonName) + CreateSignedCert(root, serverName, serverSerial, serverCertName, serverCertCommonName) + + CreateSignedCert(root, CA, clientSerial, clientName, clientCACommonName) + CreateSignedCert(root, clientName, serverSerial, clientCertName, clientCertCommonName) + + return ClientServerKeyPairs{ + ServerCert: path.Join(root, fmt.Sprintf("%s-cert.pem", serverCertName)), + ServerKey: path.Join(root, fmt.Sprintf("%s-key.pem", serverCertName)), + ServerCA: path.Join(root, fmt.Sprintf("%s-cert.pem", serverName)), + ClientCert: path.Join(root, fmt.Sprintf("%s-cert.pem", clientCertName)), + ClientKey: path.Join(root, fmt.Sprintf("%s-key.pem", clientCertName)), + ClientCA: path.Join(root, fmt.Sprintf("%s-cert.pem", clientName)), + ServerName: serverCertCommonName, + } +} diff --git a/go/vt/tlstest/tlstest_test.go b/go/vt/tlstest/tlstest_test.go index 1f22403cddd..746ab161cea 100644 --- a/go/vt/tlstest/tlstest_test.go +++ b/go/vt/tlstest/tlstest_test.go @@ -24,7 +24,6 @@ import ( "io/ioutil" "net" "os" - "path" "strings" "sync" "testing" @@ -47,20 +46,20 @@ func TestClientServer(t *testing.T) { } defer os.RemoveAll(root) - clientServerKeyPairs := createClientServerCertPairs(root) + clientServerKeyPairs := CreateClientServerCertPairs(root) serverConfig, err := vttls.ServerConfig( - clientServerKeyPairs.serverCert, - clientServerKeyPairs.serverKey, - clientServerKeyPairs.clientCA) + clientServerKeyPairs.ServerCert, + clientServerKeyPairs.ServerKey, + clientServerKeyPairs.ClientCA) if err != nil { t.Fatalf("TLSServerConfig failed: %v", err) } clientConfig, err := vttls.ClientConfig( - clientServerKeyPairs.clientCert, - clientServerKeyPairs.clientKey, - clientServerKeyPairs.serverCA, - clientServerKeyPairs.serverName) + clientServerKeyPairs.ClientCert, + clientServerKeyPairs.ClientKey, + clientServerKeyPairs.ServerCA, + clientServerKeyPairs.ServerName) if err != nil { t.Fatalf("TLSClientConfig failed: %v", err) } @@ -117,10 +116,10 @@ func TestClientServer(t *testing.T) { // badClientConfig, err := vttls.ClientConfig( - clientServerKeyPairs.serverCert, - clientServerKeyPairs.serverKey, - clientServerKeyPairs.serverCA, - clientServerKeyPairs.serverName) + clientServerKeyPairs.ServerCert, + clientServerKeyPairs.ServerKey, + clientServerKeyPairs.ServerCA, + clientServerKeyPairs.ServerName) if err != nil { t.Fatalf("TLSClientConfig failed: %v", err) } @@ -165,69 +164,19 @@ func TestClientServer(t *testing.T) { } } -var serialCounter = 0 - -type clientServerKeyPairs struct { - serverCert string - serverKey string - serverCA string - serverName string - clientCert string - clientKey string - clientCA string -} - -func createClientServerCertPairs(root string) clientServerKeyPairs { - - // Create the certs and configs. - CreateCA(root) - - serverSerial := fmt.Sprintf("%03d", serialCounter*2+1) - clientSerial := fmt.Sprintf("%03d", serialCounter*2+2) - - serialCounter = serialCounter + 1 - - serverName := fmt.Sprintf("server-%s", serverSerial) - serverCACommonName := fmt.Sprintf("Server %s CA", serverSerial) - serverCertName := fmt.Sprintf("server-instance-%s", serverSerial) - serverCertCommonName := fmt.Sprintf("server%s.example.com", serverSerial) - - clientName := fmt.Sprintf("clients-%s", serverSerial) - clientCACommonName := fmt.Sprintf("Clients %s CA", serverSerial) - clientCertName := fmt.Sprintf("client-instance-%s", serverSerial) - clientCertCommonName := fmt.Sprintf("Client Instance %s", serverSerial) - - CreateSignedCert(root, CA, serverSerial, serverName, serverCACommonName) - CreateSignedCert(root, serverName, serverSerial, serverCertName, serverCertCommonName) - - CreateSignedCert(root, CA, clientSerial, clientName, clientCACommonName) - CreateSignedCert(root, clientName, serverSerial, clientCertName, clientCertCommonName) - - return clientServerKeyPairs{ - serverCert: path.Join(root, fmt.Sprintf("%s-cert.pem", serverCertName)), - serverKey: path.Join(root, fmt.Sprintf("%s-key.pem", serverCertName)), - serverCA: path.Join(root, fmt.Sprintf("%s-cert.pem", serverName)), - clientCert: path.Join(root, fmt.Sprintf("%s-cert.pem", clientCertName)), - clientKey: path.Join(root, fmt.Sprintf("%s-key.pem", clientCertName)), - clientCA: path.Join(root, fmt.Sprintf("%s-cert.pem", clientName)), - serverName: serverCertCommonName, - } - -} - -func getServerConfig(keypairs clientServerKeyPairs) (*tls.Config, error) { +func getServerConfig(keypairs ClientServerKeyPairs) (*tls.Config, error) { return vttls.ServerConfig( - keypairs.clientCert, - keypairs.clientKey, - keypairs.serverCA) + keypairs.ClientCert, + keypairs.ClientKey, + keypairs.ServerCA) } -func getClientConfig(keypairs clientServerKeyPairs) (*tls.Config, error) { +func getClientConfig(keypairs ClientServerKeyPairs) (*tls.Config, error) { return vttls.ClientConfig( - keypairs.clientCert, - keypairs.clientKey, - keypairs.serverCA, - keypairs.serverName) + keypairs.ClientCert, + keypairs.ClientKey, + keypairs.ServerCA, + keypairs.ServerName) } func TestServerTLSConfigCaching(t *testing.T) { @@ -242,7 +191,7 @@ func TestClientTLSConfigCaching(t *testing.T) { }) } -func testConfigGeneration(t *testing.T, rootPrefix string, generateConfig func(clientServerKeyPairs) (*tls.Config, error), getCertPool func(tlsConfig *tls.Config) *x509.CertPool) { +func testConfigGeneration(t *testing.T, rootPrefix string, generateConfig func(ClientServerKeyPairs) (*tls.Config, error), getCertPool func(tlsConfig *tls.Config) *x509.CertPool) { // Our test root. root, err := ioutil.TempDir("", rootPrefix) if err != nil { @@ -252,8 +201,8 @@ func testConfigGeneration(t *testing.T, rootPrefix string, generateConfig func(c const configsToGenerate = 1 - firstClientServerKeyPairs := createClientServerCertPairs(root) - secondClientServerKeyPairs := createClientServerCertPairs(root) + firstClientServerKeyPairs := CreateClientServerCertPairs(root) + secondClientServerKeyPairs := CreateClientServerCertPairs(root) firstExpectedConfig, _ := generateConfig(firstClientServerKeyPairs) secondExpectedConfig, _ := generateConfig(secondClientServerKeyPairs) diff --git a/go/vt/topo/consultopo/error.go b/go/vt/topo/consultopo/error.go index f8aad4d1c61..2880ce6187d 100644 --- a/go/vt/topo/consultopo/error.go +++ b/go/vt/topo/consultopo/error.go @@ -18,6 +18,7 @@ package consultopo import ( "errors" + "net/url" "golang.org/x/net/context" @@ -38,11 +39,18 @@ var ( // convertError converts a context error into a topo error. All errors // are either application-level errors, or context errors. func convertError(err error, nodePath string) error { + // Unwrap errors from the Go HTTP client. + if urlErr, ok := err.(*url.Error); ok { + err = urlErr.Err + } + + // Convert specific sentinel values. switch err { case context.Canceled: return topo.NewError(topo.Interrupted, nodePath) case context.DeadlineExceeded: return topo.NewError(topo.Timeout, nodePath) } + return err } diff --git a/go/vt/topo/consultopo/server_test.go b/go/vt/topo/consultopo/server_flaky_test.go similarity index 100% rename from go/vt/topo/consultopo/server_test.go rename to go/vt/topo/consultopo/server_flaky_test.go diff --git a/go/vt/topo/consultopo/watch.go b/go/vt/topo/consultopo/watch.go index e97aaf9d106..c77b7630c50 100644 --- a/go/vt/topo/consultopo/watch.go +++ b/go/vt/topo/consultopo/watch.go @@ -28,7 +28,7 @@ import ( ) var ( - watchPollDuration = flag.Duration("topo_consul_watch_poll_duration", 30*time.Second, "time of the long poll for watch queries. Interrupting a watch may wait for up to that time.") + watchPollDuration = flag.Duration("topo_consul_watch_poll_duration", 30*time.Second, "time of the long poll for watch queries.") ) // Watch is part of the topo.Conn interface. @@ -58,6 +58,12 @@ func (s *Server) Watch(ctx context.Context, filePath string) (*topo.WatchData, < go func() { defer close(notifications) + var getCtx context.Context + // Initialize to no-op function to avoid having to check for nil. + cancelGetCtx := func() {} + + defer cancelGetCtx() + for { // Wait/poll until we get a new version. // Get with a WaitIndex and WaitTime will return @@ -65,14 +71,24 @@ func (s *Server) Watch(ctx context.Context, filePath string) (*topo.WatchData, < // if it didn't change. So we just check for that // and swallow the notifications when version matches. waitIndex := pair.ModifyIndex - pair, _, err = s.kv.Get(nodePath, &api.QueryOptions{ + opts := &api.QueryOptions{ WaitIndex: waitIndex, WaitTime: *watchPollDuration, - }) + } + + // Make a new Context for just this one Get() call. + // The server should send us something after WaitTime at the latest. + // If it takes more than 2x that long, assume we've lost contact. + // This essentially uses WaitTime as a heartbeat interval to detect + // a dead connection. + cancelGetCtx() + getCtx, cancelGetCtx = context.WithTimeout(watchCtx, 2*opts.WaitTime) + + pair, _, err = s.kv.Get(nodePath, opts.WithContext(getCtx)) if err != nil { - // Serious error. + // Serious error or context timeout/cancelled. notifications <- &topo.WatchData{ - Err: err, + Err: convertError(err, nodePath), } return } diff --git a/go/vt/topo/etcd2topo/server.go b/go/vt/topo/etcd2topo/server.go index 8e6b2588a48..5d67a6f0107 100644 --- a/go/vt/topo/etcd2topo/server.go +++ b/go/vt/topo/etcd2topo/server.go @@ -34,13 +34,21 @@ We follow these conventions within this package: package etcd2topo import ( + "flag" "strings" "time" "github.com/coreos/etcd/clientv3" + "github.com/coreos/etcd/pkg/transport" "vitess.io/vitess/go/vt/topo" ) +var ( + clientCertPath = flag.String("topo_etcd_tls_cert", "", "path to the client cert to use to connect to the etcd topo server, requires topo_etcd_tls_key, enables TLS") + clientKeyPath = flag.String("topo_etcd_tls_key", "", "path to the client key to use to connect to the etcd topo server, enables TLS") + serverCaPath = flag.String("topo_etcd_tls_ca", "", "path to the ca to use to validate the server cert when connecting to the etcd topo server") +) + // Factory is the consul topo.Factory implementation. type Factory struct{} @@ -71,12 +79,31 @@ func (s *Server) Close() { s.cli = nil } -// NewServer returns a new etcdtopo.Server. -func NewServer(serverAddr, root string) (*Server, error) { - cli, err := clientv3.New(clientv3.Config{ +func NewServerWithOpts(serverAddr, root, certPath, keyPath, caPath string) (*Server, error) { + // TODO: Rename this to NewServer and change NewServer to a name that signifies it uses the process-wide TLS settings. + + config := clientv3.Config{ Endpoints: strings.Split(serverAddr, ","), DialTimeout: 5 * time.Second, - }) + } + + // If TLS is enabled, attach TLS config info. + if certPath != "" && keyPath != "" { + // Safe now to build up TLS info. + tlsInfo := transport.TLSInfo{ + CertFile: certPath, + KeyFile: keyPath, + TrustedCAFile: caPath, + } + + tlsConfig, err := tlsInfo.ClientConfig() + if err != nil { + return nil, err + } + config.TLS = tlsConfig + } + + cli, err := clientv3.New(config) if err != nil { return nil, err } @@ -87,6 +114,13 @@ func NewServer(serverAddr, root string) (*Server, error) { }, nil } +// NewServer returns a new etcdtopo.Server. +func NewServer(serverAddr, root string) (*Server, error) { + // TODO: Rename this to a name to signifies this function uses the process-wide TLS settings. + + return NewServerWithOpts(serverAddr, root, *clientCertPath, *clientKeyPath, *serverCaPath) +} + func init() { topo.RegisterFactory("etcd2", Factory{}) } diff --git a/go/vt/topo/etcd2topo/server_test.go b/go/vt/topo/etcd2topo/server_test.go index c782e9638a3..7e2a0784b96 100644 --- a/go/vt/topo/etcd2topo/server_test.go +++ b/go/vt/topo/etcd2topo/server_test.go @@ -25,6 +25,10 @@ import ( "testing" "time" + "vitess.io/vitess/go/vt/tlstest" + + "github.com/coreos/etcd/pkg/transport" + "golang.org/x/net/context" "github.com/coreos/etcd/clientv3" @@ -89,6 +93,130 @@ func startEtcd(t *testing.T) (*exec.Cmd, string, string) { return cmd, dataDir, clientAddr } +// startEtcdWithTLS starts an etcd subprocess with TLS setup, and waits for it to be ready. +func startEtcdWithTLS(t *testing.T) (string, *tlstest.ClientServerKeyPairs, func()) { + // Create a temporary directory. + dataDir, err := ioutil.TempDir("", "etcd") + if err != nil { + t.Fatalf("cannot create tempdir: %v", err) + } + + // Get our two ports to listen to. + port := testfiles.GoVtTopoEtcd2topoPort + name := "vitess_unit_test" + clientAddr := fmt.Sprintf("https://localhost:%v", port+2) + peerAddr := fmt.Sprintf("https://localhost:%v", port+3) + initialCluster := fmt.Sprintf("%v=%v", name, peerAddr) + + certs := tlstest.CreateClientServerCertPairs(dataDir) + + cmd := exec.Command("etcd", + "-name", name, + "-advertise-client-urls", clientAddr, + "-initial-advertise-peer-urls", peerAddr, + "-listen-client-urls", clientAddr, + "-listen-peer-urls", peerAddr, + "-initial-cluster", initialCluster, + "-cert-file", certs.ServerCert, + "-key-file", certs.ServerKey, + "-trusted-ca-file", certs.ClientCA, + "-peer-trusted-ca-file", certs.ClientCA, + "-peer-cert-file", certs.ServerCert, + "-peer-key-file", certs.ServerKey, + "-client-cert-auth", + "-data-dir", dataDir) + + cmd.Stderr = os.Stderr + cmd.Stdout = os.Stdout + err = cmd.Start() + if err != nil { + t.Fatalf("failed to start etcd: %v", err) + } + + // Safe now to build up TLS info. + tlsInfo := transport.TLSInfo{ + CertFile: certs.ClientCert, + KeyFile: certs.ClientKey, + TrustedCAFile: certs.ServerCA, + } + + tlsConfig, err := tlsInfo.ClientConfig() + + var cli *clientv3.Client + // Create client + start := time.Now() + for { + // Create a client to connect to the created etcd. + cli, err = clientv3.New(clientv3.Config{ + Endpoints: []string{clientAddr}, + TLS: tlsConfig, + DialTimeout: 5 * time.Second, + }) + if err == nil { + break + } + t.Logf("error establishing client for etcd tls test: %v", err) + if time.Since(start) > 60*time.Second { + t.Fatalf("failed to start client for etcd tls test in time") + } + time.Sleep(100 * time.Millisecond) + } + defer cli.Close() + + // Wait until we can list "/", or timeout. + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + start = time.Now() + for { + if _, err := cli.Get(ctx, "/"); err == nil { + break + } + if time.Since(start) > 60*time.Second { + t.Fatalf("failed to start etcd daemon in time") + } + time.Sleep(100 * time.Millisecond) + } + + stopEtcd := func() { + cmd.Process.Kill() + cmd.Wait() + os.RemoveAll(dataDir) + } + + return clientAddr, &certs, stopEtcd +} + +func TestEtcd2TLS(t *testing.T) { + // Start a single etcd in the background. + clientAddr, certs, stopEtcd := startEtcdWithTLS(t) + defer stopEtcd() + + testIndex := 0 + testRoot := fmt.Sprintf("/test-%v", testIndex) + + // Create the server on the new root. + server, err := NewServerWithOpts(clientAddr, testRoot, certs.ClientCert, certs.ClientKey, certs.ServerCA) + if err != nil { + t.Fatalf("NewServerWithOpts failed: %v", err) + } + defer server.Close() + + testCtx := context.Background() + testKey := "testkey" + testVal := "testval" + _, err = server.Create(testCtx, testKey, []byte(testVal)) + if err != nil { + t.Fatalf("Failed to set key value pair: %v", err) + } + val, _, err := server.Get(testCtx, testKey) + if err != nil { + t.Fatalf("Failed to retrieve value at key we just set: %v", err) + } + if string(val) != testVal { + t.Fatalf("Value returned doesn't match %s, err: %v", testVal, err) + } +} + func TestEtcd2Topo(t *testing.T) { // Start a single etcd in the background. cmd, dataDir, clientAddr := startEtcd(t) diff --git a/go/vt/topo/keyspace.go b/go/vt/topo/keyspace.go index 7eb63e19f96..72b44aa75a6 100755 --- a/go/vt/topo/keyspace.go +++ b/go/vt/topo/keyspace.go @@ -21,7 +21,6 @@ import ( "github.com/golang/protobuf/proto" "golang.org/x/net/context" - "vitess.io/vitess/go/vt/proto/vtrpc" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/event" @@ -29,6 +28,7 @@ import ( "vitess.io/vitess/go/vt/topo/events" topodatapb "vitess.io/vitess/go/vt/proto/topodata" + vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" ) // This file contains keyspace utility functions @@ -62,25 +62,25 @@ func (ki *KeyspaceInfo) CheckServedFromMigration(tabletType topodatapb.TabletTyp // master is a special case with a few extra checks if tabletType == topodatapb.TabletType_MASTER { if !remove { - return vterrors.Errorf(vtrpc.Code_FAILED_PRECONDITION, "cannot add master back to %v", ki.keyspace) + return vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "cannot add master back to %v", ki.keyspace) } if len(cells) > 0 { - return vterrors.Errorf(vtrpc.Code_FAILED_PRECONDITION, "cannot migrate only some cells for master removal in keyspace %v", ki.keyspace) + return vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "cannot migrate only some cells for master removal in keyspace %v", ki.keyspace) } if len(ki.ServedFroms) > 1 { - return vterrors.Errorf(vtrpc.Code_FAILED_PRECONDITION, "cannot migrate master into %v until everything else is migrated", ki.keyspace) + return vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "cannot migrate master into %v until everything else is migrated", ki.keyspace) } } // we can't remove a type we don't have if ki.GetServedFrom(tabletType) == nil && remove { - return vterrors.Errorf(vtrpc.Code_INVALID_ARGUMENT, "supplied type cannot be migrated") + return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "supplied type cannot be migrated") } // check the keyspace is consistent in any case for _, ksf := range ki.ServedFroms { if ksf.Keyspace != keyspace { - return vterrors.Errorf(vtrpc.Code_INVALID_ARGUMENT, "inconsistent keyspace specified in migration: %v != %v for type %v", keyspace, ksf.Keyspace, ksf.TabletType) + return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "inconsistent keyspace specified in migration: %v != %v for type %v", keyspace, ksf.Keyspace, ksf.TabletType) } } @@ -129,7 +129,7 @@ func (ki *KeyspaceInfo) UpdateServedFromMap(tabletType topodatapb.TabletType, ce } } else { if ksf.Keyspace != keyspace { - return vterrors.Errorf(vtrpc.Code_FAILED_PRECONDITION, "cannot UpdateServedFromMap on existing record for keyspace %v, different keyspace: %v != %v", ki.keyspace, ksf.Keyspace, keyspace) + return vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "cannot UpdateServedFromMap on existing record for keyspace %v, different keyspace: %v != %v", ki.keyspace, ksf.Keyspace, keyspace) } ksf.Cells = addCells(ksf.Cells, cells) } @@ -240,6 +240,30 @@ func (ts *Server) FindAllShardsInKeyspace(ctx context.Context, keyspace string) return result, nil } +// GetServingShards returns all shards where the master is serving. +func (ts *Server) GetServingShards(ctx context.Context, keyspace string) ([]*ShardInfo, error) { + shards, err := ts.GetShardNames(ctx, keyspace) + if err != nil { + return nil, vterrors.Wrapf(err, "failed to get list of shards for keyspace '%v'", keyspace) + } + + result := make([]*ShardInfo, 0, len(shards)) + for _, shard := range shards { + si, err := ts.GetShard(ctx, keyspace, shard) + if err != nil { + return nil, vterrors.Wrapf(err, "GetShard(%v, %v) failed", keyspace, shard) + } + if !si.IsMasterServing { + continue + } + result = append(result, si) + } + if len(result) == 0 { + return nil, vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "%v has no serving shards", keyspace) + } + return result, nil +} + // GetOnlyShard returns the single ShardInfo of an unsharded keyspace. func (ts *Server) GetOnlyShard(ctx context.Context, keyspace string) (*ShardInfo, error) { allShards, err := ts.FindAllShardsInKeyspace(ctx, keyspace) @@ -251,7 +275,7 @@ func (ts *Server) GetOnlyShard(ctx context.Context, keyspace string) (*ShardInfo return s, nil } } - return nil, vterrors.Errorf(vtrpc.Code_INVALID_ARGUMENT, "keyspace %s must have one and only one shard: %v", keyspace, allShards) + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "keyspace %s must have one and only one shard: %v", keyspace, allShards) } // DeleteKeyspace wraps the underlying Conn.Delete diff --git a/go/vt/topo/locks.go b/go/vt/topo/locks.go index cdebbe4c03c..bf1e2eb1e95 100644 --- a/go/vt/topo/locks.go +++ b/go/vt/topo/locks.go @@ -42,11 +42,6 @@ var ( // Now used only for unlock operations defaultLockTimeout = 30 * time.Second - // Deprecated - // LockTimeout is the command line flag that introduces a shorter - // timeout for locking topology structures. - _ = flag.Duration("lock_timeout", defaultLockTimeout, "deprecated: timeout for acquiring topology locks, use remote_operation_timeout") - // RemoteOperationTimeout is used for operations where we have to // call out to another process. // Used for RPC calls (including topo server calls) diff --git a/go/vt/topo/shard.go b/go/vt/topo/shard.go index 49d75847cf4..30fd5db1cda 100644 --- a/go/vt/topo/shard.go +++ b/go/vt/topo/shard.go @@ -279,7 +279,7 @@ func (ts *Server) CreateShard(ctx context.Context, keyspace, shard string) (err defer unlock(&err) // validate parameters - name, keyRange, err := ValidateShardName(shard) + _, keyRange, err := ValidateShardName(shard) if err != nil { return err } @@ -288,27 +288,20 @@ func (ts *Server) CreateShard(ctx context.Context, keyspace, shard string) (err KeyRange: keyRange, } - isMasterServing := true - - // start the shard IsMasterServing. If it overlaps with - // other shards for some serving types, remove them. - - if IsShardUsingRangeBasedSharding(name) { - // if we are using range-based sharding, we don't want - // overlapping shards to all serve and confuse the clients. - sis, err := ts.FindAllShardsInKeyspace(ctx, keyspace) - if err != nil && !IsErrType(err, NoNode) { - return err - } - for _, si := range sis { - if si.KeyRange == nil || key.KeyRangesIntersect(si.KeyRange, keyRange) { - isMasterServing = false - } + // Set master as serving only if its keyrange doesn't overlap + // with other shards. This applies to unsharded keyspaces also + value.IsMasterServing = true + sis, err := ts.FindAllShardsInKeyspace(ctx, keyspace) + if err != nil && !IsErrType(err, NoNode) { + return err + } + for _, si := range sis { + if si.KeyRange == nil || key.KeyRangesIntersect(si.KeyRange, keyRange) { + value.IsMasterServing = false + break } } - value.IsMasterServing = isMasterServing - // Marshal and save. data, err := proto.Marshal(value) if err != nil { diff --git a/go/vt/topo/test/vschema.go b/go/vt/topo/test/vschema.go index e86cb3df2f6..0349e6b63fa 100644 --- a/go/vt/topo/test/vschema.go +++ b/go/vt/topo/test/vschema.go @@ -20,6 +20,7 @@ import ( "testing" "github.com/golang/protobuf/proto" + "github.com/stretchr/testify/require" "golang.org/x/net/context" "vitess.io/vitess/go/vt/topo" @@ -53,9 +54,7 @@ func checkVSchema(t *testing.T, ts *topo.Server) { } got, err := ts.GetVSchema(ctx, "test_keyspace") - if err != nil { - t.Error(err) - } + require.NoError(t, err) want := &vschemapb.Keyspace{ Tables: map[string]*vschemapb.Table{ "unsharded": {}, @@ -68,14 +67,10 @@ func checkVSchema(t *testing.T, ts *topo.Server) { err = ts.SaveVSchema(ctx, "test_keyspace", &vschemapb.Keyspace{ Sharded: true, }) - if err != nil { - t.Error(err) - } + require.NoError(t, err) got, err = ts.GetVSchema(ctx, "test_keyspace") - if err != nil { - t.Error(err) - } + require.NoError(t, err) want = &vschemapb.Keyspace{ Sharded: true, } @@ -113,9 +108,7 @@ func checkRoutingRules(t *testing.T, ts *topo.Server) { } got, err := ts.GetRoutingRules(ctx) - if err != nil { - t.Error(err) - } + require.NoError(t, err) if !proto.Equal(got, want) { t.Errorf("GetRoutingRules: %v, want %v", got, want) } diff --git a/go/vt/topo/test/watch.go b/go/vt/topo/test/watch.go index 5ab22b82944..756195403ac 100644 --- a/go/vt/topo/test/watch.go +++ b/go/vt/topo/test/watch.go @@ -193,7 +193,7 @@ func checkWatchInterrupt(t *testing.T, ts *topo.Server) { break } if wd.Err != nil { - t.Fatalf("bad error returned for deletion: %v", wd.Err) + t.Fatalf("bad error returned for cancellation: %v", wd.Err) } // we got something, better be the right value got := &topodatapb.SrvKeyspace{} diff --git a/go/vt/topotools/shard_test.go b/go/vt/topotools/shard_test.go index 521d163d378..68ab7be9a99 100644 --- a/go/vt/topotools/shard_test.go +++ b/go/vt/topotools/shard_test.go @@ -55,9 +55,11 @@ func TestCreateShard(t *testing.T) { } } -// TestCreateShardCustomSharding checks ServedTypes is set correctly -// when creating multiple custom sharding shards -func TestCreateShardCustomSharding(t *testing.T) { +// TestCreateShardMultiUnsharded checks ServedTypes is set +// only for the first created shard. +// TODO(sougou): we should eventually disallow multiple shards +// for unsharded keyspaces. +func TestCreateShardMultiUnsharded(t *testing.T) { ctx := context.Background() // Set up topology. @@ -90,7 +92,7 @@ func TestCreateShardCustomSharding(t *testing.T) { if si, err := ts.GetShard(ctx, keyspace, shard1); err != nil { t.Fatalf("GetShard(shard1) failed: %v", err) } else { - if !si.IsMasterServing { + if si.IsMasterServing { t.Fatalf("shard1 should have all 3 served types") } } diff --git a/go/vt/topotools/split.go b/go/vt/topotools/split.go index 98c93e0eb6b..04431ddd699 100644 --- a/go/vt/topotools/split.go +++ b/go/vt/topotools/split.go @@ -17,14 +17,66 @@ limitations under the License. package topotools import ( + "errors" "fmt" "sort" "golang.org/x/net/context" "vitess.io/vitess/go/vt/key" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" "vitess.io/vitess/go/vt/topo" ) +// ValidateForReshard returns an error if sourceShards cannot reshard into +// targetShards. +func ValidateForReshard(sourceShards, targetShards []*topo.ShardInfo) error { + for _, source := range sourceShards { + for _, target := range targetShards { + if key.KeyRangeEqual(source.KeyRange, target.KeyRange) { + return fmt.Errorf("same keyrange is present in source and target: %v", key.KeyRangeString(source.KeyRange)) + } + } + } + sourcekr, err := combineKeyRanges(sourceShards) + if err != nil { + return err + } + targetkr, err := combineKeyRanges(targetShards) + if err != nil { + return err + } + if !key.KeyRangeEqual(sourcekr, targetkr) { + return fmt.Errorf("source and target keyranges don't match: %v vs %v", key.KeyRangeString(sourcekr), key.KeyRangeString(targetkr)) + } + return nil +} + +func combineKeyRanges(shards []*topo.ShardInfo) (*topodatapb.KeyRange, error) { + if len(shards) == 0 { + return nil, fmt.Errorf("there are no shards to combine") + } + result := shards[0].KeyRange + krmap := make(map[string]*topodatapb.KeyRange) + for _, si := range shards[1:] { + krmap[si.ShardName()] = si.KeyRange + } + for len(krmap) != 0 { + foundOne := false + for k, kr := range krmap { + newkr, ok := key.KeyRangeAdd(result, kr) + if ok { + foundOne = true + result = newkr + delete(krmap, k) + } + } + if !foundOne { + return nil, errors.New("shards don't form a contiguous keyrange") + } + } + return result, nil +} + // OverlappingShards contains sets of shards that overlap which each-other. // With this library, there is no guarantee of which set will be left or right. type OverlappingShards struct { diff --git a/go/vt/topotools/split_test.go b/go/vt/topotools/split_test.go index 7ee34a15946..5dbbc0f686a 100644 --- a/go/vt/topotools/split_test.go +++ b/go/vt/topotools/split_test.go @@ -20,6 +20,7 @@ import ( "encoding/hex" "testing" + "github.com/stretchr/testify/assert" "vitess.io/vitess/go/vt/topo" topodatapb "vitess.io/vitess/go/vt/proto/topodata" @@ -94,6 +95,64 @@ func compareResultLists(t *testing.T, os []*OverlappingShards, expected []expect } } +func TestValidateForReshard(t *testing.T) { + testcases := []struct { + sources []string + targets []string + out string + }{{ + sources: []string{"-80", "80-"}, + targets: []string{"-40", "40-"}, + out: "", + }, { + sources: []string{"80-", "-80"}, + targets: []string{"-40", "40-"}, + out: "", + }, { + sources: []string{"-40", "40-80", "80-"}, + targets: []string{"-30", "30-"}, + out: "", + }, { + sources: []string{"0"}, + targets: []string{"-40", "40-"}, + out: "", + }, { + sources: []string{"-40", "40-80", "80-"}, + targets: []string{"-40", "40-"}, + out: "same keyrange is present in source and target: -40", + }, { + sources: []string{"-30", "30-80"}, + targets: []string{"-40", "40-"}, + out: "source and target keyranges don't match: -80 vs -", + }, { + sources: []string{"-30", "20-80"}, + targets: []string{"-40", "40-"}, + out: "shards don't form a contiguous keyrange", + }} + buildShards := func(shards []string) []*topo.ShardInfo { + sis := make([]*topo.ShardInfo, 0, len(shards)) + for _, shard := range shards { + _, kr, err := topo.ValidateShardName(shard) + if err != nil { + panic(err) + } + sis = append(sis, topo.NewShardInfo("", shard, &topodatapb.Shard{KeyRange: kr}, nil)) + } + return sis + } + + for _, tcase := range testcases { + sources := buildShards(tcase.sources) + targets := buildShards(tcase.targets) + err := ValidateForReshard(sources, targets) + if tcase.out == "" { + assert.NoError(t, err) + } else { + assert.EqualError(t, err, tcase.out) + } + } +} + func TestFindOverlappingShardsNoOverlap(t *testing.T) { var shardMap map[string]*topo.ShardInfo var os []*OverlappingShards diff --git a/go/vt/vitessdriver/convert.go b/go/vt/vitessdriver/convert.go index 3a0e875b0d9..16d1b61134d 100644 --- a/go/vt/vitessdriver/convert.go +++ b/go/vt/vitessdriver/convert.go @@ -31,7 +31,7 @@ type converter struct { func (cv *converter) ToNative(v sqltypes.Value) (interface{}, error) { switch v.Type() { - case sqltypes.Datetime: + case sqltypes.Datetime, sqltypes.Timestamp: return DatetimeToNative(v, cv.location) case sqltypes.Date: return DateToNative(v, cv.location) diff --git a/go/vt/vitessdriver/convert_test.go b/go/vt/vitessdriver/convert_test.go index a8ccc6ffab1..be5aef82d60 100644 --- a/go/vt/vitessdriver/convert_test.go +++ b/go/vt/vitessdriver/convert_test.go @@ -40,7 +40,7 @@ func TestToNative(t *testing.T) { }, { convert: &converter{}, in: sqltypes.TestValue(sqltypes.Timestamp, "2012-02-24 23:19:43"), - out: []byte("2012-02-24 23:19:43"), // TIMESTAMP is not handled + out: time.Date(2012, 02, 24, 23, 19, 43, 0, time.UTC), }, { convert: &converter{}, in: sqltypes.TestValue(sqltypes.Time, "23:19:43"), diff --git a/go/vt/vitessdriver/doc.go b/go/vt/vitessdriver/doc.go index a3e2770b8ac..31ea98651be 100644 --- a/go/vt/vitessdriver/doc.go +++ b/go/vt/vitessdriver/doc.go @@ -28,13 +28,12 @@ Example Using this SQL driver is as simple as: import ( - "time" "vitess.io/vitess/go/vt/vitessdriver" ) func main() { // Connect to vtgate. - db, err := vitessdriver.Open("localhost:15991", "keyspace", "master", 30*time.Second) + db, err := vitessdriver.Open("localhost:15991", "@master") // Use "db" via the Golang sql interface. } diff --git a/go/vt/vitessdriver/driver.go b/go/vt/vitessdriver/driver.go index 720f13f5bc6..92b89756d76 100644 --- a/go/vt/vitessdriver/driver.go +++ b/go/vt/vitessdriver/driver.go @@ -23,6 +23,8 @@ import ( "encoding/json" "errors" + "google.golang.org/grpc" + "vitess.io/vitess/go/vt/vtgate/grpcvtgateconn" "vitess.io/vitess/go/vt/vtgate/vtgateconn" ) @@ -72,10 +74,17 @@ func OpenForStreaming(address, target string) (*sql.DB, error) { // It allows to pass in a Configuration struct to control all possible // settings of the Vitess Go SQL driver. func OpenWithConfiguration(c Configuration) (*sql.DB, error) { + c.setDefaults() + json, err := c.toJSON() if err != nil { return nil, err } + + if len(c.GRPCDialOptions) != 0 { + vtgateconn.RegisterDialer(c.Protocol, grpcvtgateconn.DialWithOpts(context.TODO(), c.GRPCDialOptions...)) + } + return sql.Open("vitess", json) } @@ -102,12 +111,17 @@ func (d drv) Open(name string) (driver.Conn, error) { if err != nil { return nil, err } + + c.setDefaults() + if c.convert, err = newConverter(&c.Configuration); err != nil { return nil, err } + if err = c.dial(); err != nil { return nil, err } + return c, nil } @@ -139,12 +153,18 @@ type Configuration struct { // This setting has no effect if ConvertDatetime is not set. // Default: UTC DefaultLocation string + + // GRPCDialOptions registers a new vtgateconn dialer with these dial options using the + // protocol as the key. This may overwrite the default grpcvtgateconn dial option + // if a custom one hasn't been specified in the config. + // + // Default: none + GRPCDialOptions []grpc.DialOption `json:"-"` } // toJSON converts Configuration to the JSON string which is required by the // Vitess driver. Default values for empty fields will be set. func (c Configuration) toJSON() (string, error) { - c.setDefaults() jsonBytes, err := json.Marshal(c) if err != nil { return "", err @@ -154,6 +174,8 @@ func (c Configuration) toJSON() (string, error) { // setDefaults sets the default values for empty fields. func (c *Configuration) setDefaults() { + // if no protocol is provided default to grpc so the driver is in control + // of the connection protocol and not the flag vtgateconn.VtgateProtocol if c.Protocol == "" { c.Protocol = "grpc" } @@ -168,11 +190,7 @@ type conn struct { func (c *conn) dial() error { var err error - if c.Protocol == "" { - c.conn, err = vtgateconn.Dial(context.Background(), c.Address) - } else { - c.conn, err = vtgateconn.DialProtocol(context.Background(), c.Protocol, c.Address) - } + c.conn, err = vtgateconn.DialProtocol(context.Background(), c.Protocol, c.Address) if err != nil { return err } diff --git a/go/vt/vitessdriver/driver_test.go b/go/vt/vitessdriver/driver_test.go index 57e1d9fb6db..f1bbbfd8763 100644 --- a/go/vt/vitessdriver/driver_test.go +++ b/go/vt/vitessdriver/driver_test.go @@ -28,6 +28,7 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" "google.golang.org/grpc" "vitess.io/vitess/go/sqltypes" @@ -78,7 +79,8 @@ func TestOpen(t *testing.T) { connStr: fmt.Sprintf(`{"address": "%s", "target": "@replica", "timeout": %d}`, testAddress, int64(30*time.Second)), conn: &conn{ Configuration: Configuration{ - Target: "@replica", + Protocol: "grpc", + Target: "@replica", }, convert: &converter{ location: time.UTC, @@ -89,7 +91,9 @@ func TestOpen(t *testing.T) { desc: "Open() (defaults omitted)", connStr: fmt.Sprintf(`{"address": "%s", "timeout": %d}`, testAddress, int64(30*time.Second)), conn: &conn{ - Configuration: Configuration{}, + Configuration: Configuration{ + Protocol: "grpc", + }, convert: &converter{ location: time.UTC, }, @@ -115,6 +119,7 @@ func TestOpen(t *testing.T) { testAddress, int64(30*time.Second)), conn: &conn{ Configuration: Configuration{ + Protocol: "grpc", DefaultLocation: "America/Los_Angeles", }, convert: &converter{ @@ -160,9 +165,7 @@ func TestOpen_InvalidJson(t *testing.T) { func TestBeginIsolation(t *testing.T) { db, err := Open(testAddress, "@master") - if err != nil { - t.Error(err) - } + require.NoError(t, err) defer db.Close() _, err = db.BeginTx(context.Background(), &sql.TxOptions{Isolation: sql.LevelRepeatableRead}) want := errIsolationUnsupported.Error() diff --git a/go/vt/vitessdriver/rows_test.go b/go/vt/vitessdriver/rows_test.go index 6a40402dbea..e6e7502c114 100644 --- a/go/vt/vitessdriver/rows_test.go +++ b/go/vt/vitessdriver/rows_test.go @@ -22,6 +22,7 @@ import ( "reflect" "testing" + "github.com/stretchr/testify/require" "vitess.io/vitess/go/sqltypes" querypb "vitess.io/vitess/go/vt/proto/query" ) @@ -106,9 +107,7 @@ func TestRows(t *testing.T) { } gotRow := make([]driver.Value, len(wantRow)) err := ri.Next(gotRow) - if err != nil { - t.Error(err) - } + require.NoError(t, err) if !reflect.DeepEqual(gotRow, wantRow) { t.Errorf("row1: %#v, want %#v type: %T", gotRow, wantRow, wantRow[3]) logMismatchedTypes(t, gotRow, wantRow) @@ -122,9 +121,7 @@ func TestRows(t *testing.T) { uint64(18446744073709551615), } err = ri.Next(gotRow) - if err != nil { - t.Error(err) - } + require.NoError(t, err) if !reflect.DeepEqual(gotRow, wantRow) { t.Errorf("row1: %v, want %v", gotRow, wantRow) logMismatchedTypes(t, gotRow, wantRow) diff --git a/go/vt/vitessdriver/streaming_rows_test.go b/go/vt/vitessdriver/streaming_rows_test.go index d084f0755b8..171da527cb3 100644 --- a/go/vt/vitessdriver/streaming_rows_test.go +++ b/go/vt/vitessdriver/streaming_rows_test.go @@ -24,6 +24,7 @@ import ( "strings" "testing" + "github.com/stretchr/testify/require" "vitess.io/vitess/go/sqltypes" querypb "vitess.io/vitess/go/vt/proto/query" ) @@ -102,9 +103,7 @@ func TestStreamingRows(t *testing.T) { } gotRow := make([]driver.Value, 3) err := ri.Next(gotRow) - if err != nil { - t.Error(err) - } + require.NoError(t, err) if !reflect.DeepEqual(gotRow, wantRow) { t.Errorf("row1: %v, want %v", gotRow, wantRow) } @@ -115,9 +114,7 @@ func TestStreamingRows(t *testing.T) { []byte("value2"), } err = ri.Next(gotRow) - if err != nil { - t.Error(err) - } + require.NoError(t, err) if !reflect.DeepEqual(gotRow, wantRow) { t.Errorf("row1: %v, want %v", gotRow, wantRow) } @@ -146,9 +143,7 @@ func TestStreamingRowsReversed(t *testing.T) { } gotRow := make([]driver.Value, 3) err := ri.Next(gotRow) - if err != nil { - t.Error(err) - } + require.NoError(t, err) if !reflect.DeepEqual(gotRow, wantRow) { t.Errorf("row1: %v, want %v", gotRow, wantRow) } @@ -216,9 +211,7 @@ func TestStreamingRowsError(t *testing.T) { ri = newStreamingRows(&adapter{c: c, err: errors.New("error after rows")}, &converter{}) gotRow = make([]driver.Value, 3) err = ri.Next(gotRow) - if err != nil { - t.Error(err) - } + require.NoError(t, err) err = ri.Next(gotRow) wantErr = "error after rows" if err == nil || !strings.Contains(err.Error(), wantErr) { diff --git a/go/vt/vtaclcheck/vtaclcheck.go b/go/vt/vtaclcheck/vtaclcheck.go index 6b84e594e4b..2454b80018d 100644 --- a/go/vt/vtaclcheck/vtaclcheck.go +++ b/go/vt/vtaclcheck/vtaclcheck.go @@ -69,7 +69,7 @@ func Run() error { } if options.StaticAuthFile != "" { - mysql.RegisterAuthServerStaticFromParams(options.StaticAuthFile, "") + mysql.RegisterAuthServerStaticFromParams(options.StaticAuthFile, "", 0) fmt.Printf("Static auth file %s looks good\n", options.StaticAuthFile) } diff --git a/go/vt/vtctl/query.go b/go/vt/vtctl/query.go index 3a97e961aaf..d9d72943b80 100644 --- a/go/vt/vtctl/query.go +++ b/go/vt/vtctl/query.go @@ -195,7 +195,6 @@ func commandVtGateExecute(ctx context.Context, wr *wrangler.Wrangler, subFlags * qr, err := session.Execute(ctx, subFlags.Arg(0), bindVars) if err != nil { - //lint:ignore ST1005 function name return fmt.Errorf("execute failed: %v", err) } if *json { @@ -444,7 +443,6 @@ func commandVtTabletExecute(ctx context.Context, wr *wrangler.Wrangler, subFlags TabletType: tabletInfo.Tablet.Type, }, subFlags.Arg(1), bindVars, int64(*transactionID), executeOptions) if err != nil { - //lint:ignore ST1005 function name return fmt.Errorf("execute failed: %v", err) } if *json { diff --git a/go/vt/vtctl/vtctl.go b/go/vt/vtctl/vtctl.go index 0048d12fc30..30b608f5f45 100644 --- a/go/vt/vtctl/vtctl.go +++ b/go/vt/vtctl/vtctl.go @@ -126,6 +126,7 @@ import ( replicationdatapb "vitess.io/vitess/go/vt/proto/replicationdata" topodatapb "vitess.io/vitess/go/vt/proto/topodata" vschemapb "vitess.io/vitess/go/vt/proto/vschema" + vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" "vitess.io/vitess/go/vt/proto/vttime" ) @@ -307,6 +308,21 @@ var commands = []commandGroup{ {"ValidateKeyspace", commandValidateKeyspace, "[-ping-tablets] ", "Validates that all nodes reachable from the specified keyspace are consistent."}, + {"Reshard", commandReshard, + "[-skip_schema_copy] ", + "Start a Resharding process. Example: Reshard ks.workflow001 '0' '-80,80-'"}, + {"Migrate", commandMigrate, + "[-cell=] [-tablet_types=] -workflow= ", + `Start a table(s) migration, table_specs is a list of tables or the tables section of the vschema for the target keyspace. Example: '{"t1":{"column_vindexes": [{""column": "id1", "name": "hash"}]}, "t2":{"column_vindexes": [{""column": "id2", "name": "hash"}]}}`}, + {"CreateLookupVindex", commandCreateLookupVindex, + "[-cell=] [-tablet_types=] ", + `Create and backfill a lookup vindex. the json_spec must contain the vindex and colvindex specs for the new lookup.`}, + {"ExternalizeVindex", commandExternalizeVindex, + ".", + `Externalize a backfilled vindex.`}, + {"Materialize", commandMaterialize, + `, example : '{"workflow": "aaa", "source_keyspace": "source", "target_keyspace": "target", "table_settings": [{"target_table": "customer", "source_expression": "select * from customer", "create_ddl": "copy"}]}'`, + "Performs materialization based on the json spec."}, {"SplitClone", commandSplitClone, " ", "Start the SplitClone process to perform horizontal resharding. Example: SplitClone ks '0' '-80,80-'"}, @@ -1784,6 +1800,83 @@ func commandValidateKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlag return wr.ValidateKeyspace(ctx, keyspace, *pingTablets) } +func commandReshard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { + skipSchemaCopy := subFlags.Bool("skip_schema_copy", false, "Skip copying of schema to targets") + if err := subFlags.Parse(args); err != nil { + return err + } + if subFlags.NArg() != 3 { + return fmt.Errorf("three arguments are required: , source_shards, target_shards") + } + keyspace, workflow, err := splitKeyspaceWorkflow(subFlags.Arg(0)) + if err != nil { + return err + } + source := strings.Split(subFlags.Arg(1), ",") + target := strings.Split(subFlags.Arg(2), ",") + return wr.Reshard(ctx, keyspace, workflow, source, target, *skipSchemaCopy) +} + +func commandMigrate(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { + workflow := subFlags.String("workflow", "", "Workflow name. Will be used to later migrate traffic.") + cell := subFlags.String("cell", "", "Cell to replicate from.") + tabletTypes := subFlags.String("tablet_types", "", "Source tablet types to replicate from.") + if err := subFlags.Parse(args); err != nil { + return err + } + if *workflow == "" { + return fmt.Errorf("a workflow name must be specified") + } + if subFlags.NArg() != 3 { + return fmt.Errorf("three arguments are required: source_keyspace, target_keyspace, tableSpecs") + } + source := subFlags.Arg(0) + target := subFlags.Arg(1) + tableSpecs := subFlags.Arg(2) + return wr.Migrate(ctx, *workflow, source, target, tableSpecs, *cell, *tabletTypes) +} + +func commandCreateLookupVindex(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { + cell := subFlags.String("cell", "", "Cell to replicate from.") + tabletTypes := subFlags.String("tablet_types", "", "Source tablet types to replicate from.") + if err := subFlags.Parse(args); err != nil { + return err + } + if subFlags.NArg() != 2 { + return fmt.Errorf("two arguments are required: keyspace and json_spec") + } + keyspace := subFlags.Arg(0) + specs := &vschemapb.Keyspace{} + if err := json2.Unmarshal([]byte(subFlags.Arg(1)), specs); err != nil { + return err + } + return wr.CreateLookupVindex(ctx, keyspace, specs, *cell, *tabletTypes) +} + +func commandExternalizeVindex(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { + if err := subFlags.Parse(args); err != nil { + return err + } + if subFlags.NArg() != 1 { + return fmt.Errorf("one argument is required: keyspace.vindex") + } + return wr.ExternalizeVindex(ctx, subFlags.Arg(0)) +} + +func commandMaterialize(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { + if err := subFlags.Parse(args); err != nil { + return err + } + if subFlags.NArg() != 1 { + return fmt.Errorf("a single argument is required: ") + } + ms := &vtctldatapb.MaterializeSettings{} + if err := json2.Unmarshal([]byte(subFlags.Arg(0)), ms); err != nil { + return err + } + return wr.Materialize(ctx, ms) +} + func commandSplitClone(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err diff --git a/go/vt/vtctld/rice-box.go b/go/vt/vtctld/rice-box.go new file mode 100644 index 00000000000..860d92bc0ff --- /dev/null +++ b/go/vt/vtctld/rice-box.go @@ -0,0 +1,215 @@ +package vtctld + +import ( + "time" + + "github.com/GeertJohan/go.rice/embedded" +) + +func init() { + + // define files + file2 := &embedded.EmbeddedFile{ + Filename: "16e1d930cf13fb7a956372044b6d02d0.woff", + FileModTime: time.Unix(1576651902, 0), + + Content: string("wOFF\x00\x01\x00\x00\x00\x00HX\x00\x12\x00\x00\x00\x00\u007f\x8c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00GDEF\x00\x00\x01\x94\x00\x00\x00@\x00\x00\x00L\x050\x04\xf2GPOS\x00\x00\x01\xd4\x00\x00\x05\xcb\x00\x00\r\x0e\xce\xf6\xe4IGSUB\x00\x00\a\xa0\x00\x00\x00\\\x00\x00\x00\x88\x94&\x9eROS/2\x00\x00\a\xfc\x00\x00\x00V\x00\x00\x00`\xa0\xa7\xb1\xa6cmap\x00\x00\bT\x00\x00\x01\xa5\x00\x00\x038\xe2\x83!Zcvt \x00\x00\t\xfc\x00\x00\x00L\x00\x00\x00L$A\x06\xe5fpgm\x00\x00\nH\x00\x00\x01;\x00\x00\x01\xbcg\xf4\\\xabgasp\x00\x00\v\x84\x00\x00\x00\f\x00\x00\x00\f\x00\b\x00\x13glyf\x00\x00\v\x90\x00\x006r\x00\x00b&\b\x18.\xfahdmx\x00\x00B\x04\x00\x00\x00d\x00\x00\x00\xe8\x04\x02\xf8\xe2head\x00\x00Bh\x00\x00\x006\x00\x00\x006\xf8F\xab\x0ehhea\x00\x00B\xa0\x00\x00\x00\x1f\x00\x00\x00$\n\xba\x06}hmtx\x00\x00B\xc0\x00\x00\x02E\x00\x00\x03v\x81ZQ\x9floca\x00\x00E\b\x00\x00\x01\xbe\x00\x00\x01\xbe:\xfc!\xa8maxp\x00\x00F\xc8\x00\x00\x00 \x00\x00\x00 \x03\x0e\x02\xf9name\x00\x00F\xe8\x00\x00\x00\x99\x00\x00\x01\x10\x10o,\xa9post\x00\x00G\x84\x00\x00\x00\x13\x00\x00\x00 \xffm\x00dprep\x00\x00G\x98\x00\x00\x00\xbd\x00\x00\x00\xdbt\xa0\x8f\xecx\x01\r\xc1\xb1\x01\xc1P\x18\x06\xc0\xfb\x9e\nְ\x86\xce\x1a\xf6\xd0\x01@\xb2C\xd2e\xa9\xec\x92\xffN\xb0\x034\x1b{\aqt\x12\xe7\xbar\xadq\xaf\xf1\xaa\xf1\xad\xf1\u05cb\xc1\xa8\x99̲\x00\x0f\x01\n#x\x01\x94\xd2\x03p#L\x18\xc6\xf1\xff\xe6Ҟsi\xda϶m\xdb:۶m۶m\xdb6˳m\xb3\xef\xf7\xcc\\\xa6\x97\xe3\xf4v\xe7\xb7xVm\x12\x1c\x90\x86\xacT\xc5\xfb\xf3\xaf\u007fg\xe5\xc9\"\xb5*\x97\xe5\xd5\x12\x95\x8b\x95\xe1ò\x85\xaa\x96\xe7[\xbc\x00f8\b\x19\xbb\x90\xb1'd\x9c\x02o\x99b\x95\xcb\xf3\xe4\xdd-\xe0\x10\xbcx@\xad\xcf\xe3K\xd1ٛ\x19Gc\xcd\xe0k\xd7ҵ$ѵw}\xddT7\xday]\x1a\xe7\xd7\xe8Q\xf7\xbc\xfb\xd1eu\xb3]qwޕ\x95\x9b\xb5\xb6\xbb\xaa\xda2X\xa7\xea\\R\xd5\r\xa3\x83ujR\x9d\xad3wW݁\xe3k\xc2IK$\xaf\xf0\x1a\xaf\xf3\x06o\xf2\x1e\xef\xf3\x11\x1f\xf39_\xf2\x15\xdf\xf0-\u007f\xf0'\u007f\x93\x89\xccd!;\xb9\xc9G\x17\xbaҝ\x1e\x8cd\x14\xa3\x19\xc3X\xc61\x9e\tLd\x12\x93\x99\xc2,f3\x87\xb9\xccc1\xabY\xc3Zֱ\x99-D\x13C,qlg\a\x8eH{^mv;\xa86\x8f-B\xad\r\xc5CN|4\xb2\x01\xa4\xc2k\xf1Z\x9f\xa6|\x05\xe5\x12gR\xd7^\xd7\xca?4\xb7\xf6\xb4\xb2AxIO\x14?\x10\xa1]{)D$JȠ$\x9d\x92cJ|\xe8V;@\x8a\xe0\xce\x00ڥٟڕ\x93\x0fɣ\xb3\xdaAZe/\xd9\x12r\xda)\xed߅\xf6\xdbA~\xb0\xf3\x14R\xe2\xe1O;\xa9\xfc(\x8eFZ\xf5\x91F\xef\xe9F|\xb6\x01ݪ\xf5\xa3z1\x9e\x9c\xea\xf5\x02\xe5l\xb0\xf8;VC\xf7?8\r\xfe\xdd\xc9O\xc1\xba\xd9\x12B\xe7-\x83\xfd2\x82\xaf\xd8z\x9b\x18\xb2\x9e\x9d\xe4\x15\x0f\x91\x84\xabBZU\x87_\xd5C\x80\xc0\xffM\xd6\x03\xce]{\x00E\xf1ut\xed{\xcfy\xaf\xb6m\u007fQm\xbb\x9dL\xa3\xda\x18Am۶9\x99\xee\xec\xa8\xf9\xc5\xf8cE\x9b\x88A\f#f$\x13)2\x95.Z\xcca\x1e\xddX =Y,\xbdX\xc1jz\xb3V\xfa\xb3Q\x06\xb0\x99\xad\fd\x87\f\xe1 \xc7\x18\xcaI\xde1\x9a\xcf\xfc`\xb5\x97\xd0FB&\xf9\xd6\uefb5;\r\xe9AKz0X\x02\x86H\xccP\x89\x18&\t#\x19E\xc8h)1F\xf2\x8c\x95\x02\xe3\x18O\xc8\x04\x89\x98\x88\xdf*9\xa6I\x89\xe9Rf\x86Ԙ)\x15fI\x95.\xa93G\x1a̕\x16\xf3\xa4\u9ff5\xfd\xb7\x8e\x17`\x87U\x92\xb2ZZ\xfe\xe7\u007f\xfeg\xc6f\xf9\x9f-\x92\xb1U\xba\xf9\xcf-o\xc5\xee\x1c\x96\x1eތ\xdd9&=8)\x11\x17$\xe6\"WH\xb8\xcaMBnq\x8f\x88\xfb<\xa2\xc4c\xa9\xf2\x84\x974x%M^\xab]\x9b\xcf\xd2\xe1\x8b\n\xa6.\x98\x112\xd1\x05c\x17\x8c]\xb0FSZVc\x90T\xdc1d\x84\xb8\x1d\xff\xb9\x94\xfaK\xc8\x14\xe9\xb8W\u07bd\"\xf7*\xb9Wν\xaa\xeeU\xfe\xa7W\xca<5j\xb0H\x1an\xd4v\xa3čڬ\x91\x06\xeb$c\x83\x14\xdc+p\xaf\xa6{\x05\xeeUd\x9b\x84쒐\xdd\xd2`?\apAb\x17\xac\xb9`\xec\x825NH\x8bS\x9c\xa7\xe2\x8enG\xe8v\x91ە\xdd.U\xb9w4\\\xad\xedj\t?\xf9C\xc1킿H\xf9&\xa9\x00x\x01M\x89\xc5\x01BA\x10C_\x06w\xe7\xbc\x05l\x1f\xb8C\x01{\xc1\xe1DA\xd0(n\u007f4\xc9C@\x16O\x1b\xed\xc3\xe9H\x9a,\x9a/\xa6\x8e*\xdcn\b>_\xd8~\xb3\n\x14_\xb7\t\x18\xbc\xf8\x8b\x91\xc4\x11\aD\x1a\xe1??\xce\x19c\x10!\xd5\x1f\xb9`\x8c\x11\xa2{\a\x98Q\r\xa0x\x015\xc57\x01\xc2P\x00\x06\xe1/\xbd\x88H\xd1\xc0\xc6Ė1\xa8x6\x98\xd8Y\xe9\x16\xb0\x82\x03\x84\xd0\xdb_\xee$\xe92Z\xc9\xc86ل\xa8\xfd:9\v1b\xff\\ԏ\xb9~\x81\x1e\x86q\x1c\xccx\xdcrwB\xb1\x89u\xa2#\xa4\xd3\xec\xa4Ӊ\x9f\x9aF\x0e\x93\x00\x00x\x01}\xcb\x03\x8cnW\x00\x85\xd1\xf5\xa3\xb6ݞ\xba\rk\xc5\xc9Ĭ\xed\x18\xb5m۶;\xb6\xcd`l{&\xaa\xadۛ\x9c\"|;Y\xd9ч\\\xe4@9\x19\xf1\xb7's\x85|\xa6\x00\xa7\b\xf2\xf6\xc6N\xee\xf1\x9eBEZt\x1b\xb0\xeekI\xe6\xf8\xcc\xd9\xd9\xee\xectv6\xec\x19\xf6\x0f\a\x87\xc3\xc2\x19\xa1 \xdc\x14\n\x0f\xdb=I\xc0N\x82\xf7\xbc\xafH\xb1V=\x06m\xf8&\xedΊ]\xd8#\xec\x1b\x0eL\xbb\xd3\xff\xefd\x92\x9f\x92U['\xed\xc9oI\x1b\xc9fj9uQrƟ\xbd\u007fV\xfdY\xb9x\xcf❋w,\u07bax\xe5\xe2\x05\x8b\xc7.|7\xff\xb4\f\x00\xe0\x18\x9c\x80Kly\x9f\xfb\u0097\n\x15)v\xbf\xcfԪS\xafA\xa3&\x0fxP\xb3\x16\xadڴ{\xc8\xc3:t\xeaҭG\xafGE1Zp-Zх\xcf\xd1\x1d\xb9\x1f=\x18@\t\x06#\x9fa\b\xe3\xa8\xc5\x04&\xf1\x00\xa60\x87f\xccc\x01\x0fa\x11k\xe8\xc0z\xe4\x11l\xe0k\xf4\xe1\x1bѣ\xf8\x16?a\x18?\xe3\x17<\x86_\xf1'&\xf1\x97\xe8\t$\xa292\xc7G\x9e$sV\xeal1\xe2i\x8e\x01x@\x0e\x1e\x00\x18\xb6T\xfe\x89\xb2x\x0f\xbc!\xee9\xc4y\xd1\x13/F\x9c,y\xd6\xed\x13}3\xf4\x8f\xbe\n\x921%\xa0a#d\x15\x12\x84\xc4\xe4\xf8@\u007f9&\x16\xf5\xdf\xe9\xf3\xf1ٔэ\x1b\x8fNA\x1bĀ\xc7\xef\xd6o֬\xdfK/\x01\x86\x1cф\xad2\x80\bz\b\x06\xbb\x10\xa7`O\x81w!ή+\xb7\v\x06\xbbG9}\x9b`5'Hl\x83\x02\"ơ%ȗm\xa5id=\xfa%\x87m\x00\xc3T\x00\xf1\x1a\xa56\x14\"!_\xa5֛\x12\xe8]M\xad\x81\x9e\x18艳\x1f\x86\xaa\x93\x10z\x12\xc2\xfa\x11\xee͈\x9fa\x0f\x8f\vR@\xa8\xee\x93],\xb7\x87\xb3\xb1b[\xafr\xdam\xc5\xc3\xf9\xa3\x97\xc1\xee[ζ\xa6r\xbb\x87\xc1\xee\xcf\xef\n,\xb7\x83\xc1\x1eįD0\xfa\xa3)\xed֤hs4\xfdK\x10\xd8_B\x80\x95\xffY\x05z\x15;ȣ.\xf9]\x1e\"}[BPx\xb7\xfcnȣ\xdb\xf2n\x17\xbek{\xffI\x97\xe5Eȣ-y\x84֓4\xb4>\x17\r\xc9C[\xc8 \xf6\x97G\x8arI\x1a\xb6\xa2!\x00\b\xc6V6\x14\x8d\xf2F\xa8\vij\xef\xf5\xb4[\xfa\xea\x0e\xc7Г\x18\xd6G\x1c\xa3g\xec\xd5\x1b\xec\xde\xe5lk`[Ō\x9ev\b\x1b\x94`\xe7Y\x8c\xc1\x1eYζ\xb1l\xab\xd4~\xfa\v\xedTb\xac-66)19%)! 00\xc0\x9a\x18k\x8d\x91\x03\xfc\x03Ez\xe2/\xeb\x02\xacI\xf4\xe7\x04\xff\xc0\x84\xf8d\xa1\xcf\xdcu\x9f~rl\xe7\x9a]G\x0egO\x98:k!j\xb4\xa7\xeb\xf9\x0fV\x97^+Y\x99=\xbf\x00M}sVB\xab+[߹\xea\xff\xf9\x1d˃\x8bKwd\x8dM\xcb\x1c:\xb5h\xe4\xeeK\xe6cnjߝ\xca+\x98\x05\x12\xa4W\xfe$͗N\x82\x0f\x84@,$Bc\x98\xa6\xf6U\xa0\xdd\x13\xaa\xfbj\xa5'V\xdaW&=\x9e\xe5v\xcf8\xc5(V\x91ͮ)A\xce3\xab\xc1\x1e^NǛ\x1e(u\x9c\x97\xc3\rJ\xa3\xa7gJ\x92\x95KdR\x9c\x92\"X\xd9QJ\\\xc3F\xe6\xc4\xe4\x84\xf8\xc0\x00\xdaQkLl\x92\x85\xf72))1\x96r\x00%&G\xf1_\xa2\\\u007f`\xbc\x91lȒ\xbes\xfe\xc2\xed;\xe7\xce+^ܧS\xfb\u07bdV\xf7\xc2/\xedD\U000ae764\x82]\xe9Ыw\xc7\xf6}\x89.\x1d\x9fN\x17\xd7\xce/ޓ\xd3~\xc1Νy\xbaׇ\x0f\xe9\xd9\xf1\xf5\xb4\xb4n\x15W\xe6\xefޕ\xd7~\xfe\xee\x9dy\xf2\x1bÇ\xf6\xec\xf4ư\xa1=~o-Nh\r\x02\f\xaf| \xfe.\x9d\x80\b\xb0A\x02,|\x8e\x1c\x84ѓ\xb0j\xc1\x0f\xa2'AL(b\u0098P(u\xf4al'\xc4\xd4a;C\x9d\x18\xb63\xaa\x17\xcd\xea-\xc1\xea.\xd0\x18\xcc\x18\x11fP\"\xd1S>EG\x1aU\xd1R\x1a=\xbd\xc8\x19\x95\xc2Ą\xb1\x8b\x89\x85\x0e%S\xa1\xd0Y\xac6\x99\xb2\xae\x86\x14\x9f\x82tLj\x04\u007fKJr\xb2ʨᓷ\x0fn}bW\xc1\x89\xbe\xe3F\xa16mvf\x95\xdf\x1d\xdc\xe9\xf4[\x9f\x12\x82>[5\x9dl\x8a\u07b9.fʔ6\xf1\xc3^\xed6\b-J\xb7O\x9e\xb2\xbc\xfd\x8e\x0f\xf7-쳦\xdb\x1bd\xe6\xbc͕\xbb\xfe\x99غ\xedW\x9dǣ\xddAY\xf3\xa6,\x13\xbe\x1d\xb4\xbc{\xc3\xde\xcd_\xe9;\x0e\x10\xbc%F\x83\x83\xdb\x1c\x83jq\xa4*\x8bC\x89e6\xc6\x110\x17\xad\x91V\x90\xe5\xe8K@\xb0\x90\xd4\xc1k\xe4Q`\x04=\xd8}\xe3\xec\"\x1f|\x93)\xc5\"cAg0\aZt\xb16\xbc0\xf3\xbfscW\x1eѣ\xa5='\xc7.\xcc|\x80\xdf\xf8\nmA=\xdaM\x1fO\x12\xc9\xd7=\xc9,\xf2M\xf1\xa0\x8cN\xef\xa1\x1eLWc\xe9;S\xdcމ\xfc1\xd6ْM\xe6\xa4D\x8cm)\x81&\x13N\x99\xfc\xeb\x02\xdb\xfa#\xb8Ϧ!\xb6\x05\x0f\xa7\xe2\xb6_\x92\xb7Ȏ\x8e\x19SЯ(.\xea*JG\x11]2:\x92b2\f\x10\x84\xe1\xc1BO\xc9\x0e\xbe\x10\xa5\x8e\xbbHGW\xe4\xe3^\x1eL\x1dI\x90]O\xf7\xfa\xb8 \xdaT\xcd\x14\x89\x9a\xe7\x9a\x16ɬ\x13\x04\x1b\xeaD\xae6@\r\xf4\xeb\xf8\x10\b`\x04:r\nr5L\xb4a\xecC\x82\xd0\xf78\xb2\x10\x10,\xa7~l\n\\\x01=\x84\xaa\x9c\xd1Q\xce\xe8\xb81\x94\x9cO\xa50o\x15\xc0\xdc\xd5\xf2&\x13^ziB\x93\xc1\r[\xb6lؠys@`\xaa\x9c/\x18\xb8'4\x03%\xcd\xd5\x15\xd2'-V\x94\xb0\u007f3\x1eT4S\xae\x0f\x80a\"\xd5BO\xaa\x85>\xb4\xbd&j\x8b\x9e\xf4fOz\xb3\xd3X1\x1d\xf44(F\xa4\xb1L\xae\xbd0`k\f\x16\x92\f\xa6\x84x\x93\xd9\xc6\xf5Bg\xe4\xe6$E\xf4\xbc\xfb\xe0\x87{\xe2ݟ\u007f\xba+\x94,\xc8_6\x0f\xe7\xe6\xe5.\x14\xf0\x18r\x84\x9c@I(\xe1o\xd4\n5&\xd7\xc8)\x9f\x9f>\xbbq\x97\xdc|p\xff\xfa7\x80\xa0\x18\x00ߒ>\x00\xb9\x9a.\x89\x92\"=\x1bl\x80\xc4\x14B\x8cS\x04\xa7vc\x81]\xa41\x85\xd5(%\xd5L\xc0\xb7JI\x1e6\x85\x8bWrw\x9df#\x92\n &\xd0^[\xe05\xd0:\\ͻ-.\x9e\xa6\\\x11\f\x16֒\xc1\xa0\xe8\x9d\xd7\r\xcc7)\x01\x16\x83\xda^t\x12\xaa\xb6\v\xd4\xc7\xd4\xe0f\x04\xa1h1\xa1\xa2\x1dz4\xbe\xe7≋ו \xe1\xd6\xf9\a4\xac\x99\x8e?_\x88\x1b\xce\xde\xdcs\xc2\xcaMK\xce>\xfat\xffg\xe43\xd2\x17\x10\f\xa8| \xfcC\xa9\x8b\xad\xf6\x18>\x94 \x9fj\xea\x82\xe9I0\xa3\x0e|\xb8]\x838\xe52\xa0Te3\xa0\f%\x8e\x1d\r\x044\xc1\ue8d1t\x1f\x1e\xb9\x81A\x89u2\xc9\x1c\v\xec\xf9`\x83=\xac\x9cn\x95H\xd7\x01M\xa0\xdd0\xf0^<5\x86\xccS\x8aQ5T/\xc9:i\xb3\xa2\xec\xbc\xf9\x05\x95\xd3\xf2K\x1c\x9f\\\xfa1k\xe4\xb4\xf9\x95@\xd2Hei\xc1\xac\xece\x1bW\xe5\t\xf18{\x02\x82܌w\xbf\xbd\xfd\xf1@\xa5^\xac}\xf6\x89\xff\xdc=4q\xf1\x92\xf9\xb3s0`H\x02\x10\xbbPY\xf5\x04_\xe8\xa8\xf5\x00N\xb3\xc0\xfa\x8a\xf4\"\xa3\x15Q\x03\xe8\xec\x14\x8dr\x10\x8br\x14\x0fً\a\x94\xfc&F|\x80\x95\xab4J@\xd1F\x9d\x90}\xee\\\xa9#\x1d/9阋N\x06\xa2\x1f\n\xc9{\xa8\xdb\x18\xe1\u05ca&\xf8\\-@\xb0\x9e\xea@}JE8\fVi@\xb4YDip2\x9fi\x002(\xa2\x93{:\x1f\xc4(\xd2\xc5)!\u038b\x92.\x84]\xa4\xdc6\x96\xb3\x11\xf0w\x12\xabcޛ\xda\t3\xb57\x02e\xa9)\xc0\x1fSolK\b\xe4\xdcd\"\xa3\xd3]\xea\x84\u007ft\xbc_oT\xce\xe9\x1f\u007f\xbf}\xfc\x0f\xe3>\xe3\xf2)sWm^\x90ٶ\x11\xbe\x8do\xec!\x13[\x90\u007f\xee\xdd'\x8e\x1b\x1f͜m߰r\u007fR-\xc0\xb0\x80\xd2\x1f&\xed\a\u007f\x88\xa66\xcf)\xc2\xee=`\xe3\x8f\\{\x00U=\bp\x15\x14%\xccU\x0e\x02\xac\xb2\xa8{J.$%\x19\xa0\xa6@\x95;\xa0Z\b\x847bnV\x82\xff\xc4\xd3G\xbf\xfe\xf3\xd2\x15R\x81z\xa3\xeeW\an\x89ܖ93\u007f\x85\xb4\u007f\x93\xf8\xe8\xfe\x02\xf2\xc7\xf5\xfb\xe47\xd4\xca\xd1\x1e\xadD\xbb%\xc7\xf8\t\xbd\xda\x1c\xb8sxMA\t \xaa\x81 ֤ܗ!^\xab\xe7Ρ`\xb4K\x06W\x05\x87*\x05G\xc8\xca,\xa8Xӱ\xfdcܷ\xe2\x81pS\xea\xf0\xf8\xb0\x14\xb4\x16@\x80\xf1\x94/\xbe\\ˣ\xa1n\xf5\xd8\x06\xd0\x17\x06з;\x85\x8dɗM\x1f\xc0xa\xa3\xbadC\xa9\xaeC*\x84ؘl\xf9\xd9\xf8\xc8\xea]\xd5\xc4\x1e`Pb\\\x99\xa5*\x89\x1ae\xb9D\x12\x02\x8b\xb48\xbf\x10\x8f9\xe3\x93)\xdb\x1eL\x1c2aae\xf9U\xc7\xdc\t\x83\xc7?8^\xf6s\xe1\x86Dž\xab\xe6\xcf[M~\x1c\xb3h\xe1݅\x8b\xc5\xc41\xc5\r\x1b}8\xf5\xa3{\xf7?\x9cr\xb4Q\xc3\xe2чoެ\xd8:}\xfd\xdaG\xcb\xf2ŐE\x93\xc6\xe5\xe6\xde]\xc2l\xf8\xb0\xcaJ\xe1\x11\xefg\r\xe8\x03\xcet\xa7\xba\x97fzbf\xbd\x14\xccLOX\x18\x01\x02?2kDTc\xd4\xed^n\x16\x81E@\xbcGL\x1a\x8c\x01\x06\x90\xacI\xd4JԤ&>\xa9:\x9a\x16\x9a7\xdd:h֑\xb4q\x17rn\xfeC\xec\xe4\xdd\x1a\xb6o\xff\"\xbf\xa4n\xaaQ\x949}u>\x9eӶnj\xfb9+\u007f\x9cA>\"?$\x93\xde$S\xda(~\xf7xB\x8fN\x87\xbe9\xb2n\xcdq\xa8\xac\x84l\xea\x01Ljm \x16L\u007f\x01\xd2Q\u007f\xf6\xb70\x11\f.\x960\x8892zgm\xea\x95{\xd2;m\xf4\x9e/\x85\x89H\x06\x837\x80\xc1%\xca\xe6w\x02\x82\x0e\xf0\x890]\xec\x042\x04\xba\xc8\x18\xfd\x95\xdau\x1eK!)\x00%\xa1\x00\xe4\x81'T\\\xa2fk\x81\xe3\x04\xcaZ\x89\xa6\x9f`\xfc]\x8b\xf2\x85\xdb\xc2e\x10@\a5\x81*\f\r\x1c8\x13]\xb5[\x11ݼ:\v)\x84\xdb\x15G\x85\xd6\xecOh\xb0\xd5Q\xb6\x05\x00A6\x9c\x10\ue21d\x9d\xb4p\xe7\xcch\x91\xca\xed\x12\xa3\x85S\x92$\x84:F\t\xbd*\x8a\xf1b$\x1c%\xd9+\xc9\xc22\xc0й\xf2Oa\n\x1d\xeb \x88\x86\xae\xcf\xf1]Q\xf4$\x8a\x8du\xa83υP\x03\x13a\xd1\x00/\xf4_\xa0\xfa/\xea\xbcRR\x9e\xfa\xafd\xd5\xf2\xebh\xc8\xebL\x8f\x87\xe3\xf8\xd7\xe6\xf7\x18\x9b\x9e6\xa3\x04\u007f}\xe8\xa3k\xdb\xc6t<^\x95-\xaf\x9f\xba\xb8Ǣ\x81cҧ\x8e\xee\xbf\xed\xf4\xf9\xfd\xfb\x8aGw]K>\xa9J\x9f\x01\xc3H\xf2\x92|C*\x84$h\r#\xc0\x1e\xaf\xc6&\x1e\x94b\x0f\x9e\x01\x95+~\xf1\x1e\x8cD\xbf8E\xf2\xf0cG\x1e\x06\xa5\tv\xea[\xb9=ޠ\x84:/Д\xb5N\xb9\xbdN\x9cbu^\xf33(-\xb1\xab\xdcR\xbbe\xe3\u009b\x92lb=\xb2\b2\x8bKL\x10\x1d#b\x9dl\x12ٙ\x85\a\xf8\xd8l2Q\xa7-\x9a\x90\xccc\x97\x143\xe3\x84|\xce\xfb\xe6\xc1#I\xc9y\x9d\x96\xad4\xfbe\x1eK\xef:\xa7K\xa2yU\xc6\x12\xd9LJ\x88r\x96\x9c9\xe0\xe5\xbd\x1cٮ\xf4;\xf8r\xcd\xe6\x17\xd3\x1f\x93\xb5\xef{{\xdfE3\x1e\xfe\x83\x86\xbd\xf7\xe47߮}^\x1eW\x035h\xdcr\xf2:\xf4\xd7o\xe4\xfb]=\xbb\u007f\u007fq;\x12V\xd7m\xe1\xb8\xf1ݽ\x03h!Z{\x9a\xe4\xfc\xf5\x88\xac:^\xcf:\xd1\x16\u007f\x1f\xedD\xa1Ȍ>xx\x8f\xf4#˗\xadM\x1b\xa8G\u007f\x87\xff¸\x18\x06 \x85KvЁ'\xb4s\x8f\x9e\xdd\xe1\x02\x99\x9e\xc8L\x1c\xf4\"\xe6\xf6\xcbUj\x15O~QM\xf9Q\x023\xa5\x82p\xd1Q\x94{\n\xd7ۅ\xeb\x9ft\xbc\x86\x1e>B3\xc8\x02\n\xbat\xc1!x7\b\xb0\x1b@\xcc\xe1\x91{ DBOw\u007f\xa9\x89\x9e\x80{HK\x9c\xe2\xe7l\xd2Ï\x05Q\xcc\x13\x19\x9cB\x88\xb4\xa6&\xc1\x18\xed\x8c8d+\xa2\xa74\x18\x89\xae\x19\xad\xfa\xc9\xe8\xdd\xe8\xce\xcf\x0f'\r\x9b\x92K\xbe'\xa7Q\xb3\xec\r\xe4+R\x86bf\x15.\xc9'\xdfH\xf6\x13ei\x9b\xeaF\x97\xcc9q\x0f\xefv\xfc\x917\x1d\xe9\xd6\xcf\x1a=m\fӽ\xa9\xd4#ܤ\xda\x13\x06m\xb5vR\x13\xeb2\x84į\x9c\x19@\x93\xc68\x06\xbb\x9c\xb1\xa0\x89\t\x97h\x8d\x02cR\"\x93\x1a\xb0Xc\xa9\xb8`\x9aM\x9bx\xe0{3\x94\xdc\xff\x85\x10rv\x05\xf2\xdc\xf7=\n\xb2\x1c\x0f\xdeYp\xf8\xca)e˞0t\xe9\xbb'h\x02J^r\x1e%n'\x8eo\xdf\xdbH\xfe\xfbd\xe9\xcf\xe4\xfb\x15\a\x00s.\x9f\xa2\\\xf6\x82\x00h\xf2/Bf\f\x808%\xed8%\xaf\x83S\xa2\x9e\x89ϼD\x99\r\xab\x97\xc6(\x8a\x06M\xb4fP<4&\xd2\x18\x1dP\xf5'\xdcs\xe4\xe2/*\x86\n\xab\x1c\xf5\xf1T\xbc\xd5Q\xb1I\xb2\x17\x91zU\xed\xc7\xd1\xf6\xf5\xd0\xf2_d]\xd1c\x91\x8b\xb7{\xfb\xb2\xb6EkU{\x17\x1c\x9bʄlGS<\x14\xcfw\xccdm\xf9\x02\x82\xe9T:\xeeP鈄!\xff\a\xd2\xf1\xe2|H\x89P\xbdkD\xdc\x01\xbf\x88\xc8\b\x9cz\xa0E\xc4\x1bt\xa7\x84\xbbPSS\x16\x99\xc1\xb1р\x8a\x8e\x92Ŋ\xa3c\xb0P%9\xccu\x88w:\x91\xbf\xed\nyP\x88Q\x02\n\xfc\x06\x05F\x96%\x93\xbb\xc7O\xa3{\xc7FoK\"\xfb\xb0\xe1\xd8\xc8\xf4\x9d(\xf1\xfcl\xd4\x11\x8d\xfc\xe1\x06\x8a&\xbf\x92ʩ\u007f\x92/\x1b6A\xed7\xaa\xbc\x93<\xf8\xd8\xf5Ԏ\x9d&\xcd\xd3\b\x94fT\xed\xc0\xb2\x06\xc6\xd4\xcdz4A\x89ӣT\x97\x01\xe5\xd9\x15ci\x02\xdd&H\x1e\xc7\x1d1ee\xf8\xeeq:|\x03%\xbbc\x19\x9e\xc0\xe4\xe7\x03\xba\x99ʳ\xd1\xf0\u007f\x81\x8c\xf9\xbb\x12\xd0Բ2\xc9ΞJ\xa2\x19\xd0\x05z\xe8\a\r\xb4\xf1\xac\xd3y3\xfa(q\x12U\x00M\xdebTï\x045\xf9\x14\xbc\x8e?\xb9r뷲\xdcySW!\xc9\xfe\xe4\x9f+\x0f\ue799\xb9\xa4`\x11T\xf1G\xe2\xfc\x99\xa4\x8d<\x9d\x89\xb7V\xd0ܱd\xc0,\nmi\xec\x04\xfd`$L\x87Ű\x1e\x8a\xa1\x14\x90\xf4T\xeb\x8d\x10\tM\xb4\xf9\xb6\x96\x11>\x06\xd7DItK\x94\xfcq\x95>'\xaa\x11D\x80\x8dc\":\xaeҦ\x14I\xbf\x9c<\xb2\xef%\u007f\xad\xc2+\x91\xd7\xde}\xc8k\xf9\xb1\xf2#\x87\xae\b\xd7JJ/\bx\xf7\rr|\xd7n\xd4\xe4R\xfaU\xd4z\xcfnr\xecS\x8c\x04\x14@~\xfak\xd4\x13r\x1f\xf99\xa0\xca+\x94\xf1l\xd9\f\xaf)\x9e\xfeF\x8a\x8f\xa3\xaf\xfeB\xfaU\xf3Q\xafK\x8e\xb1Ȗ\xbf{\xebZr\x1b\xbf\xe6x_\xb2\u07fb\x91s.\xdeQ\xe0\x8d\u007f\\=c\xd1r\xc44\xa7\v\xf5[\x13\x18^D\xa9\x06[-ږ\xc6\xdck'\x8e\xec2\x83L\x987\xf6uR\x18\x1b\xc2\xddw\xac&\x1d\f\xe1\xd3)!n9.K\x01\x19\xae\xe5>\x87¤\xbf\xda\xec&\xc6\xe2^\u007f\xdfG\xe6;\x05?\xcd=\xbekݲͅh\xd4š\xe4\xc1w\x05\x84\x1a\xa3O\xde^\xbb\xad\x00綿\xbcv\xef\xfdI\x172\x17\x14\xce\x1c\xd77+-\xeb\x9dq\xfb?\x9dxf\xf6\x82u3nLf\xbdj\x04 \x16\xf28\xb7\x81\xb6;Z\xf6\xcb\x06\x8d\xcb/W\x19\xcb=h!\xa9w\x8c\xd4\x17\xd3$\xd3\xe3_$S\x11 XB9UL\xdfi\x82\x97\x15\xc9\xecO\xfb\xac5\x83\x1a\x04J\xe3k\x14_\x8d\xbaȠ\xd3ŀ\x8d\x9ao\x15\a1\x8aňT\xdeIxH\xbe\xc1G\xdf\xdb\xfa\xf6\xbb\x92\xbd\"\xe6\x12yl\xc0\b\u007f%ܫ\x88-\xda\xf7^\x91\xf09\x00b\xf1\xbb\xe8\xe0xGc\x05t,\xdf\xd1\x06xZ\xa3\xa71m\x80\x04n\xd3j\xf2`=\x01\xd3ٵ\xab\x8eo\x8a\x1d\xdf^\xa9\x14\xf7?\xee\xa2\xda\xd1f\x00\xf2ϼ\x8f}\xb5fAc@\x9d\xaa\xa9\x89\a\xaa\x05ڏ\x9e\xf8q\x1b/x2k*\xab;\x1f\xbe\xa3\f\xb0\xa4\xa0\x04\xba13:l:F\f\xfa:\xac6\x8aچ\x82kE~u\x9cl\xdeG\xae[,\xe4\xec>\xb2\xa5\f\x9d/{WxT\xe1a?!|\xf3\xb8\x8bXsܸ'\x9fS\xfa\x104\x01\x10/q\xff;J\xcb\x02'=\xeeFX\v\x89\x03\x12\x99\u007f\xd5gC\x01\xec\x80C R\x97[u)W^'\xef\x96KdzI\x00\x99Ѯ\x97A\xa5\x9d;\\\xfe/\x01/@\xa9_\x91D\xf4\xd97d=Y\xfb5\xbaI\x12\xee\v\xf3p\x03G\x03G\fn\xec8\x83\xef⫌\xa7~\x00\xe2\x11J\xa9\a4\xd2R\xea\xa4GC\xa9\x938\xb5=\xe6\b\x13\xf0p4\xe36\xf1,#\x9ew\xf0\xa7\xf8\xf3\x8aq\x8e\xfb8RX\xc1\xde\xdf\v@\x9c\xce}_\x1bxq\xf0\xe1jSD`\x86\x86\xe1\x0e\x92\xf3\xa2^\xd2ы\xaa\xefOb\x18D\x00j\"\xb4zrG\x88\xa8x(\xfc\xbdi\xd3rq^\xd1R\xd6\xdeJr\x06{\xc9s@\a1@)\xb6\xeb\xdc\xe3f\xc1Uک\xfbdQ3\xf6:v\x8c,B\x99\xd2\xf7\xffL[\xab;\xcc\xdeS\x8b\xce54\xae\x9ek\xc0q\xae\xbaD\x1fd\xd2Qˎ\a\xd9%\xfb?,\x8aѓ3h>o\xb5&\xbf\x1b\xc5ٱ+\xfdv\xa4\r\xd8\xcd\fC\xa1\xc1\x84\x1eM'\xd9Ǐ\xcbs\x1euX+\xe7\xb0v[\xe2[\x82?\xd7!\x9bS\x874\xa2^\xae \x1dS\x16\u0588ČBU\x86[|t/\xaa;\x1b\xd5\xd9#\x1e!\x11\xf83Gm@ V\xa6\vk\x01@\x80P\x97\u05f8\aT\x12\xc3s\xd6V\x8c\x16V\x17\x16\x02\x93^\xf1&\xba-\x11\x10\xc0\nvĒ\\\x94\xfat\xfa\n\x19Td\xe9\x80\x1f\x8eĘ\x05{\xac\xf9ۛ\t\xf9\x92>\x16\v\xdco>\x10~\x14_\x87\b\xa8\x05\x99\x8a\xa5v\x1d\x9e,\x1b\xecQU\xde\xc6B\x89\xb0\x04\xb9˿&\xc3\xc6\x16\x1eyy\xb1\x1d\xf3\xf0\xf4q\xd7\\\xdb\xe4e\xa9\xf2;\x91\x1aX\xcf\xea\x1a\xc3\xc7\xdaX\xbc\xcclz\xc2\xd3y\v\x0e\xfcX\x8c\xfe\x96\x00\x8e\xeeY\xa3\x18\xb4W\xcb\xe09\xf7\xfd-\x17\x11\xfa\xe1\xc0\xa4\x8c\xa1٥\x13ON9r]\x8c%^\xbd7ZW\x90\xbd\x93\xa2\xbae\x1f\xcc\xdb}\xa4\xe7\xe0\x89\xc3\xdaw-\xecs\xe4\x1d⻦\x8fai\xbf\x0ewO\xf7\x1e\x02\x98\xdb\xde(\x19\xc0\x17\x82a\x98b\n\te\xb4\x99\f\x14\xf6\x01j\x95\x9c\x91e\x90\x9b\xd5\xd3\xe2\x18\x92\x87\xc0\x83Mo>\xb8\xde\xee)\xbaE\x13>0\xe4G\xc7b\xec\xe4(\x93\xd1\xc6!v#3\xd7b\xd47e\x17\xc7\xeb\x8bKƣ\xc5\xf7KV\xe6~Х灅\xab\xb1\xf1\x11\xb9\xb6b\xa6\f\x8eO\xf2\xc8\r\xe2\x90>\xbaTL\xea\x15_\x02\x04oұz@\xc7*\x1c:*\x86\x88Hڴ\v\xf4\x16\xe4\x1eۀKD\xc3\xfa\xc7@6\u007f\xb6Ր\xc7X\x9b\xe0KId\xf8\x81\xcaqk,\x1f\x00\xcam\xdc|\xe8j\x8f}Ҕ\x93c\xbf O&\xddZ}\xe8W\x8f}\x1e\xf9\xe9K7\xac\x9f?\xad_\xea\xaeaȆ \xb2诜\xdb\xef\xa5/:_f=r\x8eI\xd4@J\xe5\u007fe\x00?\b\xa1\x1c\x0e\n\rc,\nR9,\xc7iPQM \xaf\xa5^\x12\xbc9\x87َs\xd8\xfc\xc2i?s\"\x8dm-\x94\xbfV&DX- H1\xb2N\f|p\xec踒b\xfd\xb8S\x1f\xfe\\\xb26\xdb\u07b5\xfbޜ\xb58\xf6\x1f\x147\x0f'>\x86I9(\xf1\x91\xeepy\x11\xfau\xddUF{*\xa5\xfdw\xca\xe1\x00\xca\xe3tŃ\xf3\xd8\xeeጽ8yA\xee\n\x10\xe2\x01쾐\xb8\x03\xc7B.\x87\xe0T70\xc4\xe02٥\xde額\xc1$6\xa3Q\x8dhG\a\x06\xaaH \xa2\xf3\x1bѴ\x1e\x04\xbfv\x87<\xc8\xfab\xee\xb5\x1f\x1dV\xf1\xfd\xc5Cr\x122rȭ\xf1kM8\xc2#\xc7\x1fE\xff\x16\xb3ՑO~$\x8e\u05f6\x9c\xecҺ\xcf\x15\xe1\xdc۫|\x97n\x00\x04/\x03\xe0sr\x00\xed\xcdP\xc5/\x90i\xa1K/\"\\\x05<\xc8\xd5\x15\xbb\xf7\x8f\xf1\x1bi\xc2c\x1fWci7\x97S\xb9b8\x0fE\xe2\xf9T\x83E\xa7\n\x10\x9b\x00\xfbnϞ\xd2\xe2\x96-<\xe3\x92\xfa\r\xf9\xee;aO\xfe\xb8\xf7\x8e\x1a\v\xf4\xe9C&\xe4W\xf4\x04\f\x83H/\xe17\xca\xf1`\xa8\x01\U000d561a\xb1\x8c?1,8\x04\ryN\xfd\vr\xcd\u007fM\xea\x89j\xa6T\xb9\xb1\xf0\x89\x12\vKݴ\xf0\x88\x12\xc0\u007fc\xe6)\\#L1\xcf\bSJU\x02oKQkQ\x98\\\xa58\xc5jЏ\xc7O\x8d\xd3\xef\xfe\xe7\xea\xe4{/\r\x9a\xbawQḲ\xa3?\x95\x16,\xda\u05edg\xf1\"*_\x0eTwɴ'\xf7\xae\xfe6\xac\xf7\xb8Uk\x17\xa7\xceA\xf1\xbf\u007fpe3\xfae\x03\xf7\xe3K\x00\x84/e\x00#\xd5cO\x93\x99\x8f\x8b!N\x83\xc2k\xa2>~\xe2KO|\x9d\xe9>\xf3Y\x9e\xaef&9!\x8ae\xba\\wyJ\x8f\xdaf\x9dD\xbd\x85\x12\x94>\xae_NlI\x89\xf0A!\x99\xe9H\xc2\x17&\x8f\x1f\xf4z\x05\xab\xe6\xc0\xc0\xdc\xf0\b\xe9\x04\xafWk\xae\xc8>\xbe\xec\xcd44G\xae\x95u\xcf\xc8\x03\xae.\x12\x92%\r\f\xe3R\xbeֳ\xa4䌊NjMQd\xfd\xe6\xcd\xfb\xbd\xfc2\xe0\xcac\xa43\xeaK\xdb\xf3\x86@f\xc3,A\xeaT\x00uX\xf0\x02\xd3K\a\xd8\x05\xb0\xa3\x86\x80\xc1\xef\x01q\x8aAr\r\x84\r\xd11\xb6$5\x04\x16\x98\x04\xaaDt&\xdf6K\x8cJl\xdeʜ\x92\x94LiI\x16\x9b>\xe9HΘV{\xbc\xd2]<\x82\"\xeb\xb5\xe0d\x01b|\x10\xbde\xa0tMvI\xb2\x98\x8ah\xb5\xfe\xc5\x18\x8c\a\xc7X\x02\x9a\x82;\ns\x0e\xe6\x01\xc8Ӹ\xf7\x98\xaa\x88ܲi5\xec\x05\x06N\xa3n\xd5\xfd\xf6\xa7'\xfe\xd5'\xa1\xf4$\x94G\xe9\x1e|\x02\\\xe2;\xbb\x87\x06\\\x0fbя\x85\x19\x87\xe4*IU\xcb3\u06015\x86\xedPSi깯\xbb%\xbf;\x05\r\x93KF\xce|+ǫ\xf4\xbbC\xaf\x94\x88M\xa7-y\xef\xf5Ad\x91\xa3.>7ib\xd6\bG<>\xf9`Cŏb\xd3j]\xa2\xbd2Bw\xc5\xcbd\xd6\xf6J\xdb\x117'\xee\x9ea\xb0\xf0\x9cY\x03/W\xad\xb2\xb8\xab\x15zI\x9eqƩV\x94\xba\x9c\x8d\xaejE\x89\x02\f\xfdi\x94\x91H\xa9\xf2\x83PxE\xf1\x0e\v\xaf\xaaa5\xbb\xe6\xf0\xee\x0eP1k\x82\xdf`\x8dUb\xde\x01\xa8Of\x13DP]#\xc7Y\xd8\u007f\xe6\x97\xf9_ c\xe6\xfd\x95w\xc8\xc3ҝK\x96\xeeؽ$w\x17\xb6m&\x8b\xc9%\xe2S\xf4d\t\x8a\xaf\xd0\x1f\xb8\xfd\xc5i\xe5\x8b\xdb,\x02\"\x83\xc4\bN[\b\x8cU̪\u007f63\xfcF\xab\x83\xce,T\xc39\x93{:(ykb\xa1\xe7zjM,\xc4D\x9dI\x826\x18\x8a\xf8\xea\xf8Ɍ\x92\xdd\xfa\x8c\xb3\x9f|]\xb21gW\x8f\xee{\x16n\xc2ƿ\xc9ՙ\x8e\xbf\xa5\xdbӖ\x90\xdb\xe4\xb1\xf8\xc1\xf55\x8e'\xab\xaf\xf18\x83\f\x12\x1eV\xf5c\x946\xce\xf8wϡ\n\xb9ɝ\xfb\x9a\x88\xe3\xf9\x9d\xd0z\b\xab\xf1\x99p\xe3Ǔe\xe3\x92\x01A\x0e\xe5\xfb\x1dj\"\f\xd4ZQ\fC\x8b\x91i\xc8rw7\xce@_-\xba\xc2ω\x01j2b8\x1aD)c\xf1\xb0Pk\xf4\x95w\x0f\xa2\x923\xd7ە\xd8G\xcd>{\x12\x979\xda\xfeU$\x98\x9f\x9c\x02@\x10\r \x94Rj\x9e\x8b\x01iD\xce=\x1bR@\xd2`@\xe8W\xe4\xfd\x11\x99\xb1\x94L\xfb\xe8\x89\xd0\xe2\xc9)f\x05\x11\xd4\x05\x90\xae\xd1Co\x18\xa4H>\xbe\xee\xef\xd7ʷV\xf2_\x9cz\x81\x97\xc0\x9d\x8c\xba\xf3\xf4\xaa\xa2\x83c@\x8c\x14\xb39A\xecT^BN\x16\x90\u007f*\xa1\x80\x9c:\xfciŚJ\xe1\xa5'\xa7\x84Ċ\vbӊ\x1bB\x1d@P\x1b@8Gi\xf3\x82\xeeZ\xa2\x9c\xa8Oп\xa3>\x9e<\xeb\x95՝;\xbacf\x8e\\\x10\x18\xba\x83\xfe\xfe\xefMR\x84\xc6\xdcx\xfc\xf834\x86\x14\xdd\xc0\xfbP\x9e\xe3\a\xc7\x17h\r\x19\x85\xad\xd8\x02\b\x02Ig\xc1N\xa9\xf1\xa3Q\x11\x18\x8c\xee\x9cr\x89\x005\xc3bbt\xf8J\xbce\x97\x94\x83\xe9\xa9J\x03\xb6\xdalI\x16VB@\xe9\xf8\xa5\xe2\x14ym\xf8\x1dk\xdb\xf8\x01\xe91\xb5ɬs\xc8O\xa8\xfb$\x92\xfc&\xf8\x14\x88\xaf\x0e\x1f+6\x00\x04}\x00\x84\xf7)%Z\f(\xe8\u007f\x00\x03j\x8a3+\xb6㞎\x03Bbaa\x8e\x10\xbcn>\xc7P\xc8J\\$7\x83 h\xa4\x98\x83Cx\xcf}\xe2\xa8.\xba\x14\x86E\xea\xd8,\x96\xe0̢d\xfer\x8e\x02'%Z\x93ⓒ\x92Y\xc6d\xa4U\"\xb4\x8a\xdcd\xc1\xd3\xf6\xbf\u007f\xfd:\xde\xf7~앝;\x85Kde\xfc\xb7\x1f\x9e\xfe}\xc5o\xe5\x1f\xdcO\x98\xf8\n\xf9Ϲ\xaf\xfb\xf6\xfb\xf6\x12\xf9\xb95\xa3`\x1f\xf9\r\xb5ya\xa5*b1T\x9b5k\xc8o\xf2Qv\xb7\x99\xd2;\xa1\x8a^I\xa5\x97A\x1eA\xb4bދG\xb3FJ\xaf\x91\xd2kr\xd2+\x99\x8c\x9c^K2\xadTN\xa14\x1bh^\x11Hg\xc4\x13\x02b\x98Kי\xcf\xeb\x0e\x1e\xbc\x12\xbb_A\u05ef\x1f\xdc\xf7\xa4\x15\xf2\xbc\xf3]\x8fn?\x9cG!\xafL\x8c\xbf_r\xf5\xe1\x8a\xdf\xcf}\xf8UZ)>\x14b\xc0\x02\xad\x15#\x9f\x1b\x00g \x13\xc81'\xbb\x1fO\xf4\xfd\xe3\\m\x99\x9f\xbb-\xf3b\"\xc2,p\x03\xcc,\xb2\x8e\xd9gJ\x14\x15\x96$\xf1\xe1\x91\xdc\x0esvw\xaa\xf3z\x8f\xad\x87\xf3^]bo\x19\xfe\xea@A_t+iu\x8dQ\x03\xf0\x96K-\xb7z\xe2I\x03\x01C\x1eY\x8b\xd2\xc4\xd7x\xfe\x10\xef\xcc\x1fx<\x8f\xe34*\xadY\U000826760h\xcel5\xb3P\x9d\xe5\rŻ\x9e\xaex\xc1{\x9f<\x90^\xad\xca\x1a\x10\xa4Wz\xd1J\xd4X\x88\x86n\n\xc4XY\x9f\x9dQh\x90;p\xac+w\x85><9\xf4\xe1\xcfl7\xdb\x06\xb1\xad\x12\xea\x0e\x80\xc8\xea\xda\vL\xc5\xc9\xc4\xd7fhP\x90N\xc3(\n\"\x9fZ^\xf2\xfe\x99s\xfbK\n\xcad\x15\x04\xd90?\xb3דּ!?\xfc\x18\x83\xc2\xeeX\xaf\xa3\xf0课\xb4\\/\xa8\x86B\x10\xf4\a\x10Yv\x15\r3\x940w\xba\x9f\x81\xf6#\xfdy^\x17\x19\xa7\f\x8cD\x13\x94\xfcH\x94\xa1\x1c\x8bD\xa9\xce\xdeh\xcb\x0fYO\xe9R\x1fU\xdd푬\x1c\xe0\xf9=D\x16\u007f]\xb4.\x9a\x95ɥ$٨\xab\x124\xbe\xd8Lu\xf3\xb8Gs\xfc\x05z\xf2\xe8\xb5Z\xf1\xd8c\xfb\x16\xfd\x9fg\x8e\xde=6{\\\xfa<=j\x81\xc7\xdeY\xdf\u007f\xd3&\xfd\xfcA\x1e_lB\xe2\xe9_\xae\xef\x1f5c\xfdLR\xb1\t\x00ӱ\xf9V\xea/\xfe\n\xa1P\aZ(\xb8n=\xd5/\xd9m\xe5\xa0\xf5_\x86r\x96\xe3b\r\nH\xb1(\x9b\x9b\xff\xb2\xe9l)\xb1TKl)<\x86I\xb1\xe8X\xed\x97E\x87\xfc\x03\x03\xe3yQ3#Z\x16\xdf\xd8|\xe5\xf2\xe6\xecyy#Ư\x9a\xb7\xaa\xe8\x93\x13\x9b\xd7,(\x1c\x9b\x96\xbf\xa0b\xd0\xc4\x13_\x9d\xc8\xc889>\xe3\xc4\xc4\xf1\v\xe6\xe5,Z\xba\xf1ܥ\xb7\vs\n\xa6e\xae\xcd]\xff\xf6\xf9\x13\x9b\x97\xe7ବ\xebӳ\xaeeM\xbf\x969\xed:ӪH\x00\x91N\x96@`\xf5\x1c@ %;P3\x89\x19\xe6\x1e/\xfa\x99\x85\xba\nx\a\xd2\x0e\x1f\xf03G\x9aq\xaa\xdd̄\x8dn\x15\x13v\x16\x9cp}Ա\xad\xe2\xeb\xbc\xecY\xaeb\xf2\xd4>\x06<\xad\xfdg\xff\xa3\x04\x9c\x86F\u007fN\x06\xa0\xc6d\x0e\x9aC\xe6\x1c'\xd9\fyFMȀ;\x82/\xde\xe6h8s\xfb\fr\x14\xb5\x9e\xb1}&.gc\xb0\x8aZ\xb0\u05f8\x05\xd3A\x10\xb3a\x9a\x89*EBB]\xaak4 `\xa1\xe1\xaa\xd2\xd2Rj\xf2-\x15?\bg\xf0_\x80\xa1\x1f1\x8a\x99TJ\x13\xa9ş\xa3X۶\xa3\x1db\xab|\x928\"\xea\\\x1e\xc4^\x15\xe8ae\xbf\x06\x1a\x94\x16.e\xee\x81-\xaa`2_*\x90\x1aĥ\xa1\x95W\xd254()\u038b\xe1)\ry\x13LH\xf8*\"M\x86\xa0\x16x\xb3@&6)\xe5i\x8dw\x03\xcc,\xa7:\xe9':\xa3\xc8@1\x02פرzl\xe1\xf2!f\x96\xb6\xed@*\xbe\x19\u007f\xb6]^遍9;\x96]9T\x96z\xa8u{\xe4u\xf7{$\x96\xec\xca[\xb6\xb5\xf1\"\x14\xb9;\xa3\xa9\xe3~\xbf\xce]:'/Da\xf5^\uf447\xf6}ԳQΰ]\xa7\x1b7ɸ\x88\xe7\x15N\x1e\xd47\xbdy\xc3q\x1bƕ\xf6\xa1\x97w\x9c\xf9\xea\xe2\xcc\r\x13\x87\xb4\xedҪK\x87\xc1s\xf7\x04\x85\x9a\x87\xb7mץu7\xa3\xff\xf0\xb6}ưqH\x13\xff\x8b\x1fJ'\xc1\x03\x8c\x10\xce*4]VK\xb0\xd9N\x9dA\xd5\x02:\x18\xd5@I\xcdꃴ\xaa\xea\xc5\xf7Խԟ\x16,R\xebW\xb7\xca\b\x82\x00\xfd\xe9J\xae\xffH'\xb8\xa65\x815\x8a\xad\xe9K\xbcX\x98\xc9\x1c\xdb&Wi\\\x03:X\r\xaa\xa55\x99\x9e$\xf3\x18>\xb9\x81Zt{\xc0O\x88\x14(F\xe9\xd9 \x99O\xdc\xc7\x1d\x00O\x83'\xbd\xe0\xeb\xc9#*#\xd6$>OϔP>\xebfO\xa6\xb3\xe3\xcee_\r\xa8\x06\x8b\xae\xc3\xc7\xe3am\xb0_U\xa4]\xd3\xdfD\xeb\xf6M\xb4\xf8\xab\x86\x95\x95<ҙ\xf4(:\x91^U\xb1 \x0e|\xb7h\xd3G\xc76lٻr`\xff\x01\xa3G\x0fx3Ձ\xb6 3j\x89L[\x8a\xc8\xcf[\xb7\x90\a\x9b'\x1eA\x9d\xd1\x1c\xd4\xe9\xc8\x01r\xf0\xd4Ir\xf0\x10\xee\xb9n\xeb\xb5Cc\xed\xd7\xdeY3\xb4\xe7⬌i\x8b{\f_\xb0\x97|\xbec\a\xaa\xb9\xb7\x18\xc5\xec\xdcN\xee\x14\x9fC\xfdN\x9f&;Ν$\xbb\xae\\F}\xb8\xc6\xe0\xf7\x05?\xce˚0Z\U0004dd71\x9e\xf9\xb2\xdaxmy\xb6\"\xc6\x06\xa8\xeb:\xd8\\\x0e\x16ى\xe2\xc5w\xcc\xeb\aP\x95v\xbay\xa3\x17\xbf\xceJ2\x04\u05c9\x8e(W\x06UOt$\xb3\x89\x0e\xc6\x1d\x9b\xca+:͡\xcer0Y\xc6#\xbd\xe5W\xe7L\x9d\xb7s\xef\xe8\x19m\xdfغ7w\xe1\xfa\x10\xf2N\xdd>a\xe3\xbb\xf7\xc5\xc7cb{\xcdxkܴ\xc4E\xc9\t\xdeo\xcd\xcb\xcf&'\x06wͪ\x15\xba\f\xb5H\x18PY\tiP(\f\x13އXX\xff\x98\x80\x0e֣6\x95\x04\x10\xccFS\x85\xa3B\x14H\x10\x02\xacC\xa8\x9c\x1a6Mu\x1c\xa3\x8f\xdb!\xe1h\xa9#Kh\x81\xa6\"\x8f\xad B?*y\xdfRn\xf9B\x04$B3ح$7\xe7*\x9f\xcc\xc2\b\xb65\xf3\xadUS\x01\xe2\x0e\x91\x995+\nC\x9f\x9e)Q<\x86\xa75\xc3J\x8cZ\xb1\x16Ce2\xc6\x10Ce2)*\xa6j\x1d\xe1\xb1$\x94z\x00\x92\fI\xf4j\xa4S(kE&\xf1g\r\xf6\xb8r{\\\x1c[p\xd9\f\xbb\xe6\xea\x1a!K\xf1ge\xb6N\x19\x94\x98\xd9\xe5\xc5\xc5,\x1a\xb3\x04Xc\x13m\xb16[\x82\xbax\xc6\xda\xcf]\xdc&R\x81ܲ\x15\xf9o\xdaD\x1ep\x81DeK\x91\xff\xba\xdds\xa6#\xe3\n_\xc10Ѿ\xb1C\x9fׇ-Ʒ\xdcd\xee4\x93\xc9\xdd(f\xef\x1e\x14\xcdd\xf2O\xf2\x9e\xd0u\xfe̬V\xf1\xeb\x9b\xf5\x8a5\xd4(1\x0e\x12\xe7\xe0\xd6\xc9\x1d\x9b\x01 \x98&E\v\xad\xb9=7\xf29=,hk\xba\x85֎d|N\x8a\xce\a\f\xf3\x842<\x83\x8e\x8d\x17\x04B\x9c\x1b\xfb\xbd˩\xb7R\xf4\x1a\x856i\xb8\xc3E\x8f묥\x1aN\xf2\x0f\x9c\xb7f\xe4\x88U\xabF\xa4\x17T&wꔜҹ\xb3X6b\xe3\x86\xf4\x91\x05\x05\x81\xed\x9b4\xed\xfc\xc6\xe8N\x80a0\x80\xf0\xa7\xf8;m\xd7\x0fڱ\xd5hڌZox\xde:7\xbb\x8f\xa6\xdeC\xf2\x95\x99\xf3\xf4\x92B%\x9c\xaa]\x03Ǻ\x89s\xd1h\xb2z'\x99\x8d\xe6\xeeD\xad*>\x12^\x11z\x15\x92!\xa8\xa8\x10mzⳖq\xaa5ހ\xf7HGh\xdf{(\x1e\x1cM\x06g\xaa\xa4)\xd0\xf2g\xde\vk\x16R\xf9\x06\xaaZ\xafx8\xaf\xfb\xf2\x95<\xfe\x81,\x90\xe5\xccF\xceuTl\x89\xaa\xbf\x1f\x8e\xc6{\x1c\xbbQ\xbd1-_\xee\xdc~\xd3N\xe4\xb1~T\x0f;\xca\xc7\x1bF\xa3\x90\xb4\xb6\x8d\x9a\xbd\xdad\xc2\xea\xd9cG\x8czc\x05 h\x8e\xf3\xf1z\xa9\x14b!W\x89\xb2\xd5\xd2ҧYJ\xc5\xe8\x83`\xd6,\xa5\xf7\xd08\x98\r\xf9 \xa4*-\x00e\x1c\xf2\x83H\x88\x03A]R\xc5\b\xd69\x15\xc0\xd37\xb8\xaa\x929֩Q\xfe|M\x95\x12\xae\xbe/\x98\x9a \xd7RtեjWUUI\xc1\xd3UU6+\xd2\xf7\xe8ԡE\xbb&\x9d7\xbd=#wc\xbb\xd6k\x8as\x16\xec(z\xe3\x95v\x1d7\xf6\x11\x877kX\xbfiB\xed!Y\x99#R\xfa\a\xd7\xce\x1f9s֨\xfa/\xbf\x9c\x90\xc1\xabu\xb3ě8\xaczN\x1a\xd39i\x8cRU\x80\xe5\x00\xeb\n\r\x940sZ\xc1v\x81/\xadd\x99\xfb\xcb\xf7\xc8\x1fk$Bn\xb3\xe7\xd7Sd\xef\x17\x9a\x83\x9a\xa0\x8b\xe2㬏\xd1¸\x9a\xbc\x94\x03#&\xf72(ѥ\xf8I磎\xa81\x90\xa3u|\xb2P\xc5\"Qw\xf4֤\xd3\xcdKw\xeaS\x8bWu\xa5\x80\xaec\xd1\xdb\x1b\xd7\nQONM\\ԑԕn\x03\x82W\x00\x84\x96\xbc歮\x82\xbd\xbc\x19E/.\x04T\x10x\xa8E\u007fFjtX\xc8\x12m\xc4\xd9=\xfeC\xfeF\x9e\xffA>\u0603\xdc\xf8\xb4\xf2q\x17\xd6\xd3Ux\x14\xca\x14:\x82\x1e\x02\x15\xa1\xaa\xda\x10\xc7\xed\xf7\xa0t\xdf\f\xbd\xc3T\xf4\xe9\x12\xcbU\xea\x12K|\x8b\xad\xb1\x8ckA\x05\x03&\x91\xd7P1\xb0\xb9\xecV\x8a\xe4g\xd0\xf2\xc9\xe0\x06\xda\x1e0\xcbV\x99\x1aO\xc4!\x8a\xfd\xba\xaa&\xecHE\v\xa2U\x11\xb0\xa9\xe1V\n\n\xf7^\xb7%_\xf7F\xef\x96C\xa2\x12CW\x0e\xce\x18\x95\x18W\xaf\x8e>\x9b\xd5'\xe3m\xe8!_\x11\xd9RA\f5z\xe1\xc2H\u007f\xed\xc2H\xec\xbe0\x92y\x1b\x1d]\x18\x89\x1en\xba\x89\x86\x9a\xf06ܷɜ\xc9\x00\x98\xb6\xa1\b6>O\x14B[\x11TlW`\xe1\x93\xd6\xc4)\x9e\xa1\x82\x1a\xc5(\x06A3\x03/\xb8\x9b\xb9\xe7\xad.\xd7M\xffp\xfd\x86\x0f\x8f\x90\vG\xdf\x1eܣ\xfb\xc0\xc1ݻ\x0e\xc2\xe2ТO\x8e\xef\xe8\xb4\xf9㏷\xcb\xc3&L\x1c\xfe\xfa\xd0\tc\a\x03\xf7\xabk\x85i\xc2A\x88\x85\r>\x00:\u0600F\x02\xbb\xde\x13@Z!\xbd\v6\xd8V\xf99^K\xf7\x1bQ\x10x \x1dl\xc77\x00\xc0\xa0e\x0f_3D\a_:˟\xd9\b\x0f\xc0\x83?{\x03\xaf\xa5ϼ-D\xf0g45`\xfc\x99q\x00\xd2\xcf\xd2\x11\xfe\xfeB\xfe\xccv\x81A\x02:x\a\x1a\xe1\r\xd5\xcfD\xd3g\xa2\xf93\x80\xa1\r\x99-L\xa3\xf9y\x10\xc4@oE\xafVE\xea٪\x016\xe3輟\xe5\xe7`\x88\xe6H\xd6\xffn}\x8e=\x9azo\xd7\xd97_A\xa7S\xb9\x9a \xab\xc1\r[\xbd\xc3\xf3\xfa$&\xbe\xf8UT{\xd0a/\xebHKo\xbc/{\xd3\xc8¢\xad\xb7\xf1f?+!\xea\xcdM\xf9\xceޔ\xde\xdc\xf4rS\xea\v\xa35\x9a_\x139\xd3\n\xf5κ\xe5l>3Nc\a\x93\xa9.JQ6\xd9%\x8d\x8bu\xe6q\x16^\xc5\x13\xa0V\xf1\xa4PLڙ\xd4\x05\xf2\x82\x1e\x06P\xfcB\x9e\xe4\xb4\xfaj\xe9\xce\x0f\xbf\xfe\xe2˱#җ\x1c\xfe\xed\xc8D{|\x8b\xf7ү~逸{o\xcd\xea̸\x96E\x15\xfa\x0eE\xf1\xdfL^2R\xe82q\x8d\x11\x87d\xfb\x1f\xe85\xe0\xdd\xc2M\xef\xf5\x1c\x955\xb6\xab9\xff`\xf7\xeeo\xf4&\x95?L\xb4\x1f{52'\xb3\xa0S\xf2\xcfxl\xf7\xd7R\x85\xc4=y\x91\vV1/:\x8b\xad(\x97\xebA8ԥ\xf1\xb1\xae^}\x15\xa7\xb7\xd7*\ag\xe0\x19\xe1>\xb1\xe1\x17\xac\xabZ\xfdh\xe4GJ\x8c\v\xe2\xa8\x15$d\xa2\x90\xbb\xeb\x8a\\K,\xc3\xef\x98,Q\xe4N\xb0\xa9\x10\xaa\xea\x1b\x84\xc4\u007f&\xdf\xcc^t's\xfc\xe5\xb9og6\\z\xbbcق\x0f\x9a<\xdc\xf7Q\xc7\x118:\xef\xcd\x15\xdbvΙ\xb9N\n \x8f\xc8[\xa9E\x8e\xe5s\xefe\xaf\xfaaބO\x96\xae\x1e:\xbf\u007f\xa3\xcd\xc9ys\x87U\xfc\u07b8Y\xc7c;\x97\x9c\xf8\xea0\xb3k\xeda\xafX_,\xa5G>`\x81\xd7\x15]PpU\xff\xa0\x9cm\x8d\xe5n\x9f\xb9`\xdfx\xf2\xae\n{\xf6\xcb\xce\xf8g\xbf\xa1\xfab`Ձ\x9af\xa1\xa7\xb1\x97\xf1\xe9\x91X\xbf\"D\xf8\x8fc\x8b\x1a\x8c\xa9[\xdc\xe70jʣ\xb2\xe6\xcd+\b;h@\xc33\x8e\xd8L\x17\x13\xc5ü\x9a,\x16\x86*\"\xcf\x00\xec\"3\xa2lku\xaf\x06\xd0T$X\x9d\xe2\x18m\x15\xb9\xe3\xe5\xe8\xae\xe8\x8a\xee*\xc1\xa1~<\xc6g\x15\x9b\xd5u\x02\xdc\xd4\x1a\xf9\xc0p\vlV\x8d\xae\xccm.\x1b\x8b\xfeY\xf7\xf3\xc7\x0e\xe88#\xed\x93\x19\xf7\x96\x8f\xe8\xd5iư\x8b%\x83Q\xef\xe6\x1d\x16\xef\xc2i\xbd\xc9ޔ\xd6y;i\x01\x81#\xaf\xce\xea\x8b\xebIY\x11ɵ\xae9\xbf\x06\xa5|<\x0e\x1f\x8a\xba}\xf0\xd08G\x97\xe0\xcfK\x00\xc3\x1a2H\xb4=\xa7\xd6\xcf۽\x9a\xf2\u007f\xbe\x82\xc0\xf8L\x05\x81\x8dW\x10\x94d|\xfc\x9c\x02\x02\xdd\x16ǹ\x05\xda\n\x02\x04\x1b覧\xd8ԭ\x8e&\xe8\x05u4\xa5\xa5jmLjʟtz\xbe\xce\xdd\n+\x14T\xa3&\xf7\x18\x06{H\xb9\xf6\x13Z\x9aD\xef\xc5+\x85\xec\xbeZ\x8b\x05\xbeܚ\xc7)\xfe\x1a\xe3\x14\xf8\x02\x960v\x85\xbb\xda\xf6h\xa6\x8e\xd8fL41Ix\xba\xb8Q\xa2IO\xf5\xf7Pt\xfa\n\xbb2a\x1bY\x82\xf2ȶ\x19\xc5B;\xb6ޑ\xad}|\xb2$#m\xcc\xe8w?Ɵ\x04\x14 \xbf=(i/2\x16\xfa\xd3%\x90\x9b\x1c\x15\xa1\xbe\xe22\xbfo/\x93\xd3\xd7~b\xb2=\xb8\xf2\x81\x0e\xa8]\x8f\x82z\x90\b\x05\x8a\x9c\xc4\xe1D\x99\xc5\x13l\xdbP+\xdb\xdaiUMɞ\xd3\xe23Y\xd0yr\x8b݈\xef\xec\x8d\xe2\\\x1c.\xb3\xed&\xe4Lr\xd5;C\xf8\xae*\x04\xa9㼹\xbe\xaa\x0eO\x8dr`\xb5Q\xb6po\xf7l\x1dM\xcd*\xf3<8\xf3\xf3e\xb9g\x9b\xb5:1\xfe\xf2\x8f\x8ex\xdd;\xd9\x1fN\xeb\x94\xfb碋-\x9a\x9fξC\x1e\x95l\xc9\xcbݲu\xf1\xa2mb\xfd\xa1\x05\x81\xd87\x17۶\x90\xdc\xc9\xc3\xd2&\x92\x9f&\x15\x9f\x1c=k\xc1\xf8aC3PC\xa2\xff\xe0\xe6g\x97\x0eݺq\xe3\xed\xc5!3\v\xf8\xda2\xf1\x1bA\x96\x01< Q\xadw\xa7v\x8a\xa6ĺH\x1d\xf5E\x92Ȍm\xb0]bu\xdb47Ft/\x1a8P\xc1\u007f\xe1_\xc1\xa0\xea\x9cdN\x10\xe4u\x05k\xd6\xfd5^\xfcų\xb8\xd8\x1b\x19\x98Tf\x8a\a\xb0M\xee\x02z\xf0\x87:\x8a\x10\xc0\xb1\rA\xfdF\x9ePՔ\xd2B\x87R\xf9En M\xd53\x80|\xfaM\xe2\xac\xe0\x9c\xc0\xb6\x19\xfd\xdf\xcc\xca:\x9cE\x0e\xbeҨa\x9bW\x1aŷ\x96\xe6\xf4\x9e\xc0O\x93\x99\xf9;\xcf輈E;\vɝh\x04\xe6\xfe\xa2y֛\xb5_\x1e\\7\xacv\xd3\x19\x99\xa9\xd6ƃ\x12\"\xeb6\x91\xee\x8c\xce\xf6o\xeeӢ\x91n\xd4\x12\xff\xa6\xa66\xf5i^\xb4\r\xe7\x89K\x85\x18h\a\x9bo\xc1\xab\x17[\x02\xbd\xb6\x1c\xe7Ig\xd5k\v -\xad%\xa3w\x90\xd8\bM\x93͔\xfbъ\x87\xdeS\x9b-G03\xa4\xe7N\x9f\u007f\xfc\xc0\xc2'\x04\x13\x93\x91\xef\xc8T\xe1\xf0`\xd9\xdca\xf6\xaa\x9cIig\x00AC1\x10\xb5\x97\xc1\xf5=\x9a\x92A\x05\xf8\a`\\\xbf\xc7$\xcb\xeb\xd2S\x85\x0f\xd0`1\xb0ü\xe5\xcb\xe7\r;\r\bj\x90o\xd1Kp\x90\xbe'\xe2\xe9{\xfe\xfd\xa3NK\xd3\xfb\v%Cɷ\x1dg\xaf\x9c2l\xf89\xda\xcf\x11b#|\x84\xf6)\x16Vy\xb0\x9ct\x15z\x05X\xff_\x16\x03q\xb6\f\xf4\xfajov}5j\x01\x00\x98\xb6y\r\x0f\x83\xbf\xf8\fEê\xdaS6E*Q)1=۶\xba\xee\xd6.2\x89q\xa1â%\xe8\v\xba-\x1dL\xaeu\xc8]W\xf2\xce\xe8k-\xf9~\xd4\x15\xc6\xf3\xc5\u0602c\x84\xf3,\nW<\xab*\x9c\x84\xb8\xfd\x9eN|C\xf3M\xb8\xc5\xe3\xde\xec?a\xec\x80\xd4q\x82\xd8{\xfc\x98Ԛ\xbdǎ\xeb\x03\bF\xc3:\x1c%\x1c\x04\x19\f@\x87G\xc1:\xa9\xfa\xebc\xac\xe4\x83}`'\x02\xe1\xa5\xe4\x16\xb2-űd\"Z`F\vyֵ\x16\xfbV?\a\x14\x81\xd0\x01\xd7\n\xc6S\x14@\x9fD\xdf!\x1b\xb9\xb5\faB\x84\x83$\xcbL\xb2\xd02\x94\x0f\b^\x82\xb1\xc2H)\x06\x04г'yS)6dy{\x04>=b,\xfbt\x1c\xe3r2^\x8e\x8fH\xdb\x05\x9a\xe9\x03\xe0\xe5`\xd6f\xed\x9ci\xa0V[\x89a\xd4cXa\x91\x12\xc0\xfd\x85v\x92Q\xfb\x11\x18\xab\x9e\xeb\xae5N\x01'.\xa9w\xfd\xb2\x87\x1d\x98\x87eɘ\x1f\xdfF\x96\xd3Y\xe3C~\x91\x91\x91q\x91B\xaa\x13\xec㓮\x91\x1c\x9d\x0ft\x9b\x12v\x9aB\x10X\xd96\xfd3Au嶎OI\n]\xc9\x1c\xf1\xc0\xf6Ii\xfeӦ=\"_\xcb\n\xfd\xcf\x13\x85\xff>r\x91\xff\x98\xb1\xef\xec\x97\xd1l6?\x89\xc3?\xb9\x1a\xb3%\x02\xd5D\xde3rg\"\x19EFn\xb3\x9e\xffpf. \u0605\xf3\x84\x9f\x04\xc6\xc5P\x17\xff\x1a\xc8\xf2,\xe4\x86h\xff\xc4\xe0]\x9cW\b\x98\xcd\xc5\n\x17y\xd5z0\xccW<\xd4\x15\x1a\x1e\xccT\xfc\x9fV\xaf;\xbf\xd4\xe7\xee˝l\xff\xff\xadkg1\xc1\xb9={.\u007f4~O\xe4̌\xa9\xe9_|\x81;\x96\x96\xd2\xfa\xf67\x0f\x9ek\xb61~Ԩ\x01\xf9\x15,\xb6\xe0U\xf8\xc2\x0f\xb4?\x81\xf0\xa6\xda\x01\x13m\xdf\x14\xa1-L\xd4ʀ\x96L\x93\xfb\a\ft\xc8uVQf\xf3\xaej\xed\x9fJ\x9a\x95\x13\xcc|\x1e\x9d\xdf\x10\x1a\xcex\xf5\xccwߕ\xecك\xca\xf6\x0fGuK\xa4\xa1\xfeWGQ\xda(\xa9S\xde=\xdc\xecq-`\x98\x1e\xdd<\x14\x02@\x86$\x97\xf43\xd0}\x11\xaf(\xa1g\xc0<;f\xe8\xa1\x16\xc8\xe30\x1e\x82\xd6\x00x\x8f\x10\xf5|t>\xd0=\x9d\rР\xf3\xfe\x01\xbe\x1c\x8d\xf2\xf5\u007f>H\xcf\x1a\xfd?G矋\xcdW\xfe\x89\xd7S\xeab!CK\x96\xf6\xfbf*(?\x83\xad\xa7:4\a\x96\xc3\x16\x10R\xdd1x\xd0Uc\xf0X\x83\xc1\xbb\x83\xefJxl\x14\xbd\xf8?\x82\xc1\xa3\xf3\xff\x82\xc1cH\xa6\x9b#B\xc03\xdf4\v\xfc\x97o\x9a\xe1\xe7|\xd3\xccKv\xff\xa6\x19\xf5\x8b\xd16\x94\x80\x12\x8c:\xdceԨM$WF\x99[ɂ/\x8d\xa8\xee\xbcݻӰL\x02QtXee\xf5\x17\a\xb1\fF\xee}j\x02\x88\xdfp,/\x1c\xd2\xfeϾ\xa6wYD\xa9J\x1c\xdbl\x16Q\x86\x8b\xba\xb2z\x1eЬ\xbb\x92\\M\x1c\xf3YaU\xca\xeb\xfa\x01\x12\xba\x98\x8f\x81N\xec\v$T\x87Oo\xdb\xe6\xf2\x19\x92\xf6\xe4?g\xef\xfe\x8d~\xb8q\x0f\x85\xe0\xf5\x85x\xb6\xf3{$x=\x11\x90\xe9\x9fT\xf6=\x12\x12\xc9l?\xff\xfe\x8d.\x11Dz^!\x1d\xb4A\rQ2\xf8k\x97h\xef\xf7\xf6\xa0\x9f\x14~\xceݓ\xd11v\xb7\x96\a\xfb}4w'?\xbd{\x19\x9c}λ\xfdd\u05fbc\x9e\u07bd\x1cN\xa2\xa6ϼ\xdbWt\xb9[~\xf2\xf4\xee\x91\xf0\x0f}\xb7\xc5\xed\xddF\xf1\x0f{(e\x9f\xb3\xa7+\x9e>\x91\x8f\xba\xa0V\xcf<\xe1+\xffa\x0f\xaazb*iþoC\x9f\xb0\x01\x8b>2\xd1\xd5\xff\xd5\xc6]CK\rDa\x00\xbe\xf3\xde\xee\xe0\xee\xee\xee\xee\xee\x1d\xee\xee\xee\xe9\x0f\x15\x1e\x16\xa7\xa2\xa5})\x91\xeeYI\x0554x\x87\xeb0\x99{ϟ\xc9f\xda=_\xee\xf9\xf7\x8e\xacN\xccwc\xf8..-\x16\xda\xc7Gq\xcf\xe8\xb7Z\xccIe#D\x17\x02:RW\x02\xba}N/\x86\x8e\xe9N@wԾn\x01}\x94\x1a\xac\xeeQ\xa5;g]0\xaf\xac\xbb\xe0Ҍ\xe3\xec\xe6\x11\xea\xe3\xef\x82IY\xd2\xd4\xd9\xe9\xbe\xc6\xd3\x11M\x83Ə\x17\x89fm\xde[\xcd\xd9Y\xc7fa\xa0vK\xcd\xfa\xa5ջ\\v\xd6G\xcd\xe9,;tk\x9b\xbd+g\xe7{Z\xb8\x192Yf\xc8o5\xbb\xd8w\x9e!|'\n7\xfb\xa6\xc8\xcc^\xabf\x8a\xc6=)\x92A-\xc3:R\xaf\x03zpNτ\x8e\xe9cHk_\x0f\x85\xae\xd0[5\xb7\xa0\x87\xf8\xb9\xf5_裪\x8f\xadݣJ\x8f\xb0}\x99\xc8}\xe1s\xf8nUΒg:\x06\xeb\f\a\xbf\x93\xae\x9c\xbd\xa0#\xf5\x04\x9a_\xd3S\xdd-\xa7\xa7C\xc7\xd4\x10\xa8\xddC{Z\xff\x86>J_\xb0*3\xdd\xcbf\x1f\xc2\xd9\xf9,\xb8K3O\xd2\\B}\xfca-i\xc3i\xf8\x94o\xf9\x9f\xd5\xcbd\xe5\xbd \x12\x8d\xaf^\x93ѭ\xc2:R\xfb\x03z\x8c\xaf5\x89\xd6\x14\x9f\fX\xe5W\xfe\x04[9Z*ر9ۈ\x14G\xe9!\x11\xf5\xa8\xd2\x13\u0557\xbaY\xd2\x13N\xb2\rWܠ\xafԦp\xc5X\xdb\xc5\xe9r\xc5\xf6\u007fK\xd3\x13\xb5\xf6\x8a\x15\xb2S-Hw*>\a\xea:\xb0J\xfaՈ\x0e\xe0\x1f\xeb\xc9\x00\xee@AGj}@\x0f\xf4\xb5&њ\xe2\x9d\x01\xab\xfcʍ\xa8|\x94\xe2\xac\a\xd0\xc3l\x0f\xc6\xcb>\xd5dݡr\xba\n\xae\xba\xeaK\xaf\x9b\xdcN\x92\xfa\xb2$\xb9GT3óQ\x1f\x93ۣR\xabٚ\xe7֎-\x1bgy\x8f\x1an\x8a\x95[*\xd6Ϭ^Vn\x80>j6ZݣJ\xb7Qأ\xf8\x1c\x97\x9b\x19kyf\xec)\x15\xb2t\xe3\xea|\xba\xca\xf5{\x9d\x8c\x8eM\x97{}Lu\xbfVa\x1d\xa9\x9d\x01\xdd\xdfךDk\x8a\x0f\al.\xc7'\xd8\xca\xfeR\xc1\x0e\xc8\xd9F\xa48J\x0f\xb2\x91\x84\x1eb;2\x96;\xc2gE\\\xee-\xf2,\x9b\x91\x1b\xff~H:s\ue08e\xd4Fh\x9c(I\xba\xf8Z\x93hM\xf1\xeeBe\xee6*7\xa2\xf2Q\xaadɡ{\xda\xe4\x8389\x9ffpYvH\x96>D\xb9\xbd\tɡ\x1bEk:\xba\x01\xd5\xddw\xe1\xa9\xeda\xab\x0fL\xab\xff\a\"\x880\x93\x00\x00x\x01MLJ\x81\x031\x10BQ\xdd\aF\xda\xfe\x1b\xbcR\x8c\xb3\xdfD\xd6Z\u007f\x9d\xff\xeb\xf2Z\x80&{\x90\x1c\xc0\xf9\x80.\x9f\xa9d\x86L\x1a^\xe9tcl%\xd5\r\xe1\xa4\xd4\xf2\xb6-4$\x13\xc6\xcd\xd9V$\xc5 {\xef\xed\x93IN\x8a\xebX\x9e\r\xe8\xc1J\xa9`^R\xd4|\xe4\a\x95\x0f\xfb\x06\x85\xcc\x04\xdf\x00\x01\x00\x00\x00\x02\x00\x000\x1bQ\xae_\x0f<\xf5\x00\x1b\b\x00\x00\x00\x00\x00\xc4\xf0\x11.\x00\x00\x00\x00\xd0\xdbN\x9a\xfa\x1b\xfd\xd5\t0\bs\x00\x00\x00\t\x00\x02\x00\x00\x00\x00\x00\x00x\x01c`d``\xcf\xf9\xc7\xc3\xc0\xc0\xe9\xf9K\xfa\x9f\x17\xa7\x01P\x04\x15\xdc\x05\x00p[\x05E\x00x\x01m\x92\x03\f&M\x10D\xdf\xce\xf4\xee\xf7۶m\xf3l۶m۶m۶m\x87g\xdbWg&y\x99v:\xd3\xe5[Q\b\x00 \xb8,\x84{\x91~\xae-\xcd\xec(U\xad\x0ee\xc2]\x14\xb7\x8b\x14\x0e\nS\xd4͢\xb1[\xc6\x17\xbe\x02\xefYs\xd2\x04\x1dx\xdf\xfd\xce\xe7\xee]\xda\xf9T\xbc\xa2\xfa\x8ab\x84\xc8-\xf2\x88\xdfE\x0f\xd1H\xa4\x16\xe5D\xa1\xe0\x04M\x82\xf1|m/\x93\xcc\n\xd1\xcd~\xa0\x89_J\xca؏\x94\b\xff\xd2\xec\xcb\f\x0f\u007f\xa7j\x18\x97\xe1\xd6J\x94\x92_\x91\x1a\xe1$\x86\xbb\xef\x99j%\xf8=4\xc5\xd30<\xba\xa2\xdc$Q\x8f*\xe1s\xb7\xde\xd2\xda}\x98\xcd%\x9d-\xe1\xe7\xf0'Z\x85o\xf2^\xecm\xfe\x0f\x8d\xbfm\r/\xda\n\xb2\xb8\x0f\xe9\xe0\x93\xf1\x95ާ}6\xe2\xf9^\x98\xab\xae|\x0e\xf5צ\x95\xfdD.kH^\xfb\x9f\xdcn)\xff)\x96ϊ\xd1*8I\xeb\xe0\xe0\xf5\xb9\xf6\x82ޓ\xf4\x8ayZZ\tշ#签V\xe4u\x93\xf5~\xa4\xb77O[q\x9a\xf9}|\x1cy\xbe\xf5\xe7\xf9\xda/\xe7\r\xbd\xd9T\x13/8\xcdX\xbd\xaf\x86\xe5i(\xbb\xa5壸\r!g8I\xef6>\f\x0e\xd3\xd1\x0e\x90C\xfb\x15\x89\x92\x93\xd3w\xa4\xa3\x9fO\x11+C\xdd(\x85\xe2#\xa8\xe6\xae\xd2\xc0\x92\x90\xdf\x1d'\x81\x88\xe3\x1aPӚ\xd1\xc3\x1f$\xa1{\x83\x8e\xbai%\xc5k\xf8\x81b\x1eEt\xcf\xcc\xd1喇\xfe\xa6\xacvI\x14\xabq\xfd\x94%\"\xfb\xcd\xff\xb3\x19\f\xb1\x05\xb4\x8c\xe6\x93\xc6\xc6Q\xc7ړT\xb3rZ/:\a\x97\xe8\x19\xebO\xb1X\"\xf2\xfbE\fw\xa3\xa9\xee\x97P3\x8cǀ(.\xed\x82\xee\xe4\x13?\x05]\xf9\xccm\xa2\x98\xdb\xc9\u007fn\xbe\xec\t\xb4pE(%\xb2k\x87\u007f\xb5\xcb\x1f\xd2@^\xeb\xa0\x1b\x95\xe1Ck\xa9:\xedwo\u007f\xe5o\xe9P\xba\ns\v\xe9\xe1\x89H\x1f&m<\x88\xfb\xfe\xfa>\xe9c\x9cރb\xcb=]<\x8a4\xf1 \xb74\xa1\xbb?\x11\xe9\xc0\xa4\x81\a\t.]_\x12\\\xa2\x8b\u07b5bֽ\xfb?\x8an\xff 7o\xcf\x1b7\x00\x1c\x98\xd7\xf8\x00\x00\x00\x00\x00\x00a\x00a\x00a\x00a\x00a\x00\x93\x00\xb8\x018\x01\xaa\x02:\x02\xcd\x02\xe4\x03\x0e\x038\x03k\x03\x90\x03\xaf\x03\xc5\x03\xe6\x03\xfd\x04J\x04x\x04\xc7\x05<\x05\u007f\x05\xdf\x06>\x06k\x06\xdf\aF\a[\ap\a\x8f\a\xb6\a\xd5\b3\b\xd6\t\x15\tt\t\xc8\n\r\nM\n\x83\n\xeb\v-\vH\v{\v\xd0\v\xf4\fB\f~\f\xd3\r\x1e\r\x83\r\xdf\x0eJ\x0et\x0e\xb6\x0e\xe6\x0f;\x0f\x90\x0f\xc0\x0f\xf8\x10\x1c\x103\x10X\x10\u007f\x10\x9a\x10\xba\x112\x11\x90\x11\xe3\x12A\x12\xa8\x12\xfa\x13t\x13\xb9\x13\xf1\x14=\x14\x94\x14\xaf\x15\x1a\x15e\x15\xb3\x16\x17\x16x\x16\xb5\x17\x1f\x17q\x17\xb8\x17\xe8\x186\x18}\x18\xc2\x18\xfa\x19;\x19R\x19\x92\x19\xd9\x1a\f\x1ah\x1a\xda\x1b=\x1b\x9c\x1b\xbb\x1c`\x1c\x8f\x1d5\x1d\xa3\x1d\xaf\x1d\xcc\x1e\x84\x1e\x9a\x1e\xd6\x1f\x19\x1fi\x1f\xe4 \x04 M y \x98 \xd3!\x05!O![!u!\x8f!\xa9\"\n\"m\"\xab#&#z#\xea$\xa8%\x17%h%\xd9&8&S&\xd6'p'\x9e'\xd7(\x1b(%(/(S(w(\x99(\xa5(\xb1(\xe9)\f)()E)X)l)\xe8*\x03*k*\xbd*\xe8+7+\xa6+\xe8+\xe8+\xf0,V,m,\x84,\x9b,\xb2,\xcb,\xe4,\xf0-\a-\x1e-5-N-e-|-\x93-\xac-\xc3-\xda-\xf1.\b.\x1f.8.O.f.}.\x96.\xad.\xc4.\xdb.\xf1/\a/ /9/E/\\/s/\x89/\xa2/\xb8/\xce/\xe5/\xfe0\x140+0B0X0n0\x870\x9e0\xb50\xcb0\xe40\xfb1\x13\x00\x00\x00\x01\x00\x00\x00\xde\x00\x8f\x00\x16\x00T\x00\x05\x00\x01\x00\x00\x00\x00\x00\x0e\x00\x00\x02\x00\x02\x14\x00\x06\x00\x01x\x01]\x8e3{\x03\x00\x18\x84\xdf\xda\xdd\xeb\xeee0%[l{\x8am\xfe\xfd\\\x8c\xe73\xef\x80+r\x9cqr~\xc3\t\xf7\xb0\xceOyT\xb5\xca\xcf\xf6\xfa\xe7{\xf9\x05\xdf<\xaf\xf3K^q\xad\xf3G\x12\x14\x89ѓ\xef1\x96ŨPcB\x9b\x02CRT\xe4G44\xe9\xf2\x89\x91_\xfe%\x06\x89Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x10>Y\xb2\x04\x02\x00\x11\x129\xb2\x05\x02\x00\x11\x129\xb2\a\x02\x00\x11\x129\xb2\b\x02\x00\x11\x129\xb1\n\f\xf4\xb2\f\x02\x00\x11\x129\xb2\r\x02\x00\x11\x129\xb0\x02\x10\xb1\x0e\f\xf401!!\x11!\x03\x11\x01\x01\x11\x01\x03!\x015\x01!\x03(\xfd<\x02\xc46\xfe\xee\xfe\xba\x01\f\xe4\x02\x03\xfe\xfe\x01\x02\xfd\xfd\x05\xb0\xfa\xa4\x05\a\xfd}\x02w\xfb\x11\x02x\xfd^\x02^\x88\x02^\x00\x02\x00\xa0\xff\xf5\x01{\x05\xb0\x00\x03\x00\f\x00/\x00\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x1c>Y\xb0\x00EX\xb0\v/\x1b\xb1\v\x10>Y\xb2\x06\x05\n+X!\xd8\x1b\xf4Y\xb2\x01\x06\x02\x11\x12901\x01#\x033\x03462\x16\x14\x06\"&\x01[\xa7\r\xc2\xc97l88l7\x01\x9b\x04\x15\xfa\xad-==Z;;\x00\x02\x00\x88\x04\x12\x02#\x06\x00\x00\x04\x00\t\x00\x19\x00\xb0\x03/\xb2\x02\n\x03\x11\x129\xb0\x02/\xb0\aа\x03\x10\xb0\b\xd001\x01\x03#\x133\x05\x03#\x133\x01\x15\x1eo\x01\x8c\x01\x0e\x1eo\x01\x8c\x05x\xfe\x9a\x01\xee\x88\xfe\x9a\x01\xee\x00\x02\x00w\x00\x00\x04\xd3\x05\xb0\x00\x1b\x00\x1f\x00\x8f\x00\xb0\x00EX\xb0\f/\x1b\xb1\f\x1c>Y\xb0\x00EX\xb0\x10/\x1b\xb1\x10\x1c>Y\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x10>Y\xb0\x00EX\xb0\x1a/\x1b\xb1\x1a\x10>Y\xb2\x1d\f\x02\x11\x129|\xb0\x1d/\x18\xb2\x00\x03\n+X!\xd8\x1b\xf4Y\xb0\x04а\x1d\x10\xb0\x06а\x1d\x10\xb0\vа\v/\xb2\b\x03\n+X!\xd8\x1b\xf4Y\xb0\v\x10\xb0\x0eа\v\x10\xb0\x12а\b\x10\xb0\x14а\x1d\x10\xb0\x16а\x00\x10\xb0\x18а\b\x10\xb0\x1e\xd001\x01!\x03#\x13#5!\x13!5!\x133\x03!\x133\x033\x15#\x033\x15#\x03#\x03!\x13!\x02\xfd\xfe\xf8P\x8fP\xef\x01\tE\xfe\xfe\x01\x1dR\x8fR\x01\bR\x90R\xcc\xe7E\xe1\xfbP\x90\x9e\x01\bE\xfe\xf8\x01\x9a\xfef\x01\x9a\x89\x01b\x8b\x01\xa0\xfe`\x01\xa0\xfe`\x8b\xfe\x9e\x89\xfef\x02#\x01b\x00\x00\x01\x00n\xff0\x04\x11\x06\x9c\x00+\x00f\x00\xb0\x00EX\xb0\t/\x1b\xb1\t\x1c>Y\xb0\x00EX\xb0\"/\x1b\xb1\"\x10>Y\xb2\x02\"\t\x11\x129\xb0\t\x10\xb0\fа\t\x10\xb0\x10а\t\x10\xb2\x13\x01\n+X!\xd8\x1b\xf4Y\xb0\x02\x10\xb2\x19\x01\n+X!\xd8\x1b\xf4Y\xb0\"\x10\xb0\x1fа\"\x10\xb0&а\"\x10\xb2)\x01\n+X!\xd8\x1b\xf4Y01\x014&'&&546753\x15\x16\x16\x15#4&#\"\x06\x15\x14\x16\x04\x16\x16\x15\x14\x06\a\x15#5&&53\x14\x16326\x03X\x81\x99\xd5ÿ\xa7\x95\xa8\xbb\xb8\x86rw~\x85\x011\xabQ˷\x94\xbaӹ\x92\x86\x83\x96\x01w\\~3Aѡ\xa4\xd2\x14\xdb\xdc\x17\xec͍\xa6{nfycw\x9ej\xa9\xce\x13\xbf\xbf\x11\xe7Ƌ\x96~\x00\x05\x00i\xff\xeb\x05\x83\x05\xc5\x00\r\x00\x1a\x00&\x004\x008\x00x\x00\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x1c>Y\xb0\x00EX\xb0#/\x1b\xb1#\x10>Y\xb0\x03\x10\xb0\nа\n/\xb2\x11\x04\n+X!\xd8\x1b\xf4Y\xb0\x03\x10\xb2\x18\x04\n+X!\xd8\x1b\xf4Y\xb0#\x10\xb0\x1dа\x1d/\xb0#\x10\xb2*\x04\n+X!\xd8\x1b\xf4Y\xb0\x1d\x10\xb21\x04\n+X!\xd8\x1b\xf4Y\xb25#\x03\x11\x129\xb05/\xb27\x03#\x11\x129\xb07/01\x134632\x16\x15\x15\x14\x06#\"&5\x17\x14\x16326554&\"\x06\x15\x0146 \x16\x15\x15\x14\x06 &5\x17\x14\x16326554&#\"\x06\x15\x05'\x01\x17i\xa7\x83\x85\xa5\xa7\x81\x82\xaa\x8aXJGWV\x94V\x02;\xa7\x01\x06\xa8\xa7\xfe\xfc\xaa\x8aXJHVWIGY\xfe\ai\x02\xc7i\x04\x98\x83\xaa\xab\x88G\x84\xa7\xa7\x8b\aNebUINffR\xfcу\xa9\xa8\x8bG\x83\xa9\xa7\x8b\x06OecUJOdcT\xf3B\x04rB\x00\x03\x00e\xff\xec\x04\xf3\x05\xc4\x00\x1e\x00'\x003\x00\x85\x00\xb0\x00EX\xb0\t/\x1b\xb1\t\x1c>Y\xb0\x00EX\xb0\x1c/\x1b\xb1\x1c\x10>Y\xb0\x00EX\xb0\x18/\x1b\xb1\x18\x10>Y\xb2\"\x1c\t\x11\x129\xb2*\t\x1c\x11\x129\xb2\x03\"*\x11\x129\xb2\x10*\"\x11\x129\xb2\x11\t\x1c\x11\x129\xb2\x13\x1c\t\x11\x129\xb2\x19\x1c\t\x11\x129\xb2\x16\x11\x19\x11\x129\xb0\x1c\x10\xb2\x1f\x01\n+X!\xd8\x1b\xf4Y\xb2!\x1f\x11\x11\x129\xb0\t\x10\xb21\x01\n+X!\xd8\x1b\xf4Y01\x13467&&54632\x16\x15\x14\x06\a\a\x01653\x14\a\x17#'\x06\x06#\"$\x0527\x01\a\x06\x15\x14\x16\x03\x14\x1776654&#\"\x06eu\xa5aBĨ\x96\xc4Yok\x01DD\xa7{\xd0\xdeaJ\xc7g\xd5\xfe\xfe\x01דz\xfe\x9d!\xa7\x99\"vvD2dLR`\x01\x87i\xb0uv\x90G\xa6\xbc\xaf\x85X\x95RO\xfe}\x82\x9f\xff\xa8\xf9sBE\xe2Kp\x01\xa9\x18{\x82v\x8e\x03\xe5`\x90S0W>CYo\x00\x01\x00g\x04!\x00\xfd\x06\x00\x00\x04\x00\x10\x00\xb0\x03/\xb2\x02\x05\x03\x11\x129\xb0\x02/01\x13\x03#\x133\xfd\x15\x81\x01\x95\x05\x91\xfe\x90\x01\xdf\x00\x01\x00\x85\xfe*\x02\x95\x06k\x00\x11\x00\t\x00\xb0\x0e/\xb0\x04/01\x134\x12\x127\x17\x06\x02\x03\a\x10\x13\x16\x17\a&'\x02\x85y\xf0\x81&\x92\xbb\t\x01\x8dUu&\x85y\xec\x02O\xe2\x01\xa0\x01TFzp\xfe4\xfe\xe3U\xfe~\xfe\xe4\xaa`qJ\xae\x01T\x00\x00\x01\x00&\xfe*\x027\x06k\x00\x11\x00\t\x00\xb0\x0e/\xb0\x04/01\x01\x14\x02\x02\a'6\x12\x1354\x02\x02'7\x16\x12\x12\x027u\xf1\x84'\x9a\xbb\x02X\x9db'\x84\xefw\x02E\xdf\xfeg\xfe\xa6Iqv\x01\xf1\x01/ \xd2\x01i\x01\x1ePqI\xfe\xaa\xfed\x00\x01\x00\x1c\x02a\x03U\x05\xb0\x00\x0e\x00 \x00\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x1c>Y\xb0\x00\xd0\x19\xb0\x00/\x18\xb0\t\xd0\x19\xb0\t/\x1801\x01%7\x05\x033\x03%\x17\x05\x13\a\x03\x03'\x01J\xfe\xd2.\x01.\t\x99\n\x01).\xfe\xcd\xc6|\xba\xb4}\x03\xd7Z\x97p\x01X\xfe\xa3n\x98[\xfe\xf1^\x01 \xfe\xe7[\x00\x00\x01\x00N\x00\x92\x044\x04\xb6\x00\v\x00\x1a\x00\xb0\t/\xb0\x00а\t\x10\xb2\x06\x01\n+X!\xd8\x1b\xf4Y\xb0\x03\xd001\x01!\x15!\x11#\x11!5!\x113\x02\x9e\x01\x96\xfej\xba\xfej\x01\x96\xba\x03\r\xaf\xfe4\x01̯\x01\xa9\x00\x01\x00\x1d\xfe\xde\x014\x00\xdb\x00\b\x00\x17\x00\xb0\t/\xb2\x04\x05\n+X!\xd8\x1b\xf4Y\xb0\x00а\x00/01\x13'6753\x15\x14\x06\x86i^\x04\xb5c\xfe\xdeH\x83\x8b\xa7\x91e\xca\x00\x00\x01\x00%\x02\x1f\x02\r\x02\xb6\x00\x03\x00\x11\x00\xb0\x02/\xb2\x01\x01\n+X!\xd8\x1b\xf4Y01\x01!5!\x02\r\xfe\x18\x01\xe8\x02\x1f\x97\x00\x01\x00\x90\xff\xf5\x01v\x00\xd1\x00\t\x00\x1b\x00\xb0\x00EX\xb0\a/\x1b\xb1\a\x10>Y\xb2\x02\x05\n+X!\xd8\x1b\xf4Y017462\x16\x15\x14\x06\"&\x909r;;r9a0@@0.>>\x00\x01\x00\x12\xff\x83\x03\x10\x05\xb0\x00\x03\x00\x13\x00\xb0\x00/\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x1c>Y01\x17#\x013\xb1\x9f\x02`\x9e}\x06-\x00\x00\x02\x00s\xff\xec\x04\n\x05\xc4\x00\r\x00\x1b\x009\x00\xb0\x00EX\xb0\n/\x1b\xb1\n\x1c>Y\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x10>Y\xb0\n\x10\xb2\x11\x01\n+X!\xd8\x1b\xf4Y\xb0\x03\x10\xb2\x18\x01\n+X!\xd8\x1b\xf4Y01\x01\x10\x02#\"\x02\x035\x10\x1232\x12\x13'4&#\"\x06\a\x11\x14\x163267\x04\n\xde\xec\xe9\xe0\x04\xde\xed\xeb\xde\x03\xb9\x84\x8f\x8e\x82\x02\x89\x8b\x89\x85\x03\x02m\xfe\xbb\xfe\xc4\x015\x013\xf7\x01A\x018\xfe\xd3\xfe\xc6\r\xeb\xd7\xd6\xde\xfe\xd8\xec\xe1\xd4\xe4\x00\x01\x00\xaa\x00\x00\x02\xd9\x05\xb7\x00\x06\x009\x00\xb0\x00EX\xb0\x05/\x1b\xb1\x05\x1c>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x10>Y\xb2\x04\x00\x05\x11\x129\xb0\x04/\xb2\x03\x01\n+X!\xd8\x1b\xf4Y\xb2\x02\x03\x05\x11\x12901!#\x11\x055%3\x02ٺ\xfe\x8b\x02\x12\x1d\x04щ\xa8\xc7\x00\x00\x01\x00]\x00\x00\x043\x05\xc4\x00\x17\x00M\x00\xb0\x00EX\xb0\x10/\x1b\xb1\x10\x1c>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x10>Y\xb2\x17\x01\n+X!\xd8\x1b\xf4Y\xb0\x02в\x03\x10\x17\x11\x129\xb0\x10\x10\xb2\t\x01\n+X!\xd8\x1b\xf4Y\xb0\x10\x10\xb0\fв\x15\x17\x10\x11\x12901!!5\x016654&#\"\x06\x15#4$32\x16\x15\x14\x01\x01!\x043\xfcF\x01\xf8pU\x8as\x8a\x99\xb9\x01\x03\xd9\xcb\xec\xfe\xee\xfez\x02ۅ\x020\u007f\x9fUr\x92\x9d\x8c\xc9\xf8ձ\xd7\xfe\xd7\xfeY\x00\x01\x00^\xff\xec\x03\xf9\x05\xc4\x00&\x00x\x00\xb0\x00EX\xb0\r/\x1b\xb1\r\x1c>Y\xb0\x00EX\xb0\x19/\x1b\xb1\x19\x10>Y\xb2\x00\r\x19\x11\x129\xb0\x00/\xb2\xcf\x00\x01]\xb2\x9f\x00\x01q\xb2/\x00\x01]\xb2_\x00\x01r\xb0\r\x10\xb2\x06\x01\n+X!\xd8\x1b\xf4Y\xb0\r\x10\xb0\tа\x00\x10\xb2&\x01\n+X!\xd8\x1b\xf4Y\xb2\x13&\x00\x11\x129\xb0\x19\x10\xb0\x1cа\x19\x10\xb2\x1f\x01\n+X!\xd8\x1b\xf4Y01\x013665\x10#\"\x06\x15#4632\x16\x15\x14\x06\a\x16\x16\x15\x14\x04 $53\x14\x1632654&'#\x01\x86\x8b\x83\x96\xffx\x8f\xb9\xfd\xc3\xce\xea{jx\x83\xff\x00\xfef\xfe\xff\xba\x96~\x86\x8e\x9c\x93\x8b\x032\x02\x86r\x01\x00\x89q\xad\xe5\xda\xc2_\xb2,&\xb0\u007f\xc4\xe6\u07b6s\x8a\x8c\x83\u007f\x88\x02\x00\x02\x005\x00\x00\x04P\x05\xb0\x00\n\x00\x0e\x00I\x00\xb0\x00EX\xb0\t/\x1b\xb1\t\x1c>Y\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x10>Y\xb2\x01\t\x04\x11\x129\xb0\x01/\xb2\x02\x01\n+X!\xd8\x1b\xf4Y\xb0\x06а\x01\x10\xb0\vв\b\x06\v\x11\x129\xb2\r\t\x04\x11\x12901\x013\x15#\x11#\x11!5\x013\x01!\x11\a\x03\x86\xcaʺ\xfdi\x02\x8c\xc5\xfd\x81\x01\xc5\x16\x01\xe9\x97\xfe\xae\x01Rm\x03\xf1\xfc9\x02\xca(\x00\x01\x00\x9a\xff\xec\x04-\x05\xb0\x00\x1d\x00a\x00\xb0\x00EX\xb0\x01/\x1b\xb1\x01\x1c>Y\xb0\x00EX\xb0\r/\x1b\xb1\r\x10>Y\xb0\x01\x10\xb2\x04\x01\n+X!\xd8\x1b\xf4Y\xb2\a\r\x01\x11\x129\xb0\a/\xb2\x1a\x01\n+X!\xd8\x1b\xf4Y\xb2\x05\a\x1a\x11\x129\xb0\r\x10\xb0\x11а\r\x10\xb2\x14\x01\n+X!\xd8\x1b\xf4Y\xb0\a\x10\xb0\x1d\xd001\x13\x13!\x15!\x03632\x12\x15\x14\x02#\"&'3\x16\x1632654&#\"\a\a\xceJ\x02\xea\xfd\xb3,k\x88\xc7\xea\xf3\xda\xc1\xf4\x11\xaf\x11\x90v\x81\x93\x9f\x84yE1\x02\xda\x02֫\xfes?\xfe\xf9\xe0\xe1\xfe\xfdֽ}\u007f\xb0\x9b\x92\xb15(\x00\x02\x00\x84\xff\xec\x04\x1c\x05\xb1\x00\x14\x00!\x00N\x00\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x1c>Y\xb0\x00EX\xb0\r/\x1b\xb1\r\x10>Y\xb0\x00\x10\xb2\x01\x01\n+X!\xd8\x1b\xf4Y\xb2\a\r\x00\x11\x129\xb0\a/\xb2\x15\x01\n+X!\xd8\x1b\xf4Y\xb0\r\x10\xb2\x1c\x01\n+X!\xd8\x1b\xf4Y01\x01\x15#\x06\x04\a632\x12\x15\x14\x02#\"\x0055\x10\x00%\x03\"\x06\a\x15\x14\x1632654&\x03O\"\xd8\xff\x00\x14sǾ\xe3\xf5\xce\xd1\xfe\xfc\x01W\x01S\xd2_\xa0\x1f\xa2y}\x8f\x91\x05\xb1\x9d\x04\xf8\xe1\x84\xfe\xf4\xd4\xe1\xfe\xf2\x01A\xfdG\x01\x92\x01\xa9\x05\xfdprVD\xb4ܸ\x95\x96\xb9\x00\x01\x00M\x00\x00\x04%\x05\xb0\x00\x06\x002\x00\xb0\x00EX\xb0\x05/\x1b\xb1\x05\x1c>Y\xb0\x00EX\xb0\x01/\x1b\xb1\x01\x10>Y\xb0\x05\x10\xb2\x03\x01\n+X!\xd8\x1b\xf4Y\xb2\x00\x03\x05\x11\x12901\x01\x01#\x01!5!\x04%\xfd\xa5\xc2\x02Y\xfc\xec\x03\xd8\x05H\xfa\xb8\x05\x18\x98\x00\x00\x03\x00p\xff\xec\x04\x0e\x05\xc4\x00\x17\x00!\x00+\x00a\x00\xb0\x00EX\xb0\x15/\x1b\xb1\x15\x1c>Y\xb0\x00EX\xb0\t/\x1b\xb1\t\x10>Y\xb2'\t\x15\x11\x129\xb0'/\xb2\xcf'\x01]\xb2\x1a\x01\n+X!\xd8\x1b\xf4Y\xb2\x03\x1a'\x11\x129\xb2\x0f'\x1a\x11\x129\xb0\t\x10\xb2\x1f\x01\n+X!\xd8\x1b\xf4Y\xb0\x15\x10\xb2\"\x01\n+X!\xd8\x1b\xf4Y01\x01\x14\x06\a\x16\x16\x15\x14\x06#\"&5467&&54632\x16\x034&\"\x06\x14\x16326\x01\"\x06\x15\x14\x16264&\x03\xecsbr\x85\xff\xd0\xd2\xfd\x81rap\xec\xc1\xc0헛\xfa\x97\x93\x83\x82\x94\xfe\xeam\x87\x85ޅ\x8a\x044m\xaa01\xbcw\xbd\xe0\xe1\xbcv\xbe10\xaal\xb8\xd8\xd8\xfc\xa1z\x9a\x98\xf8\x8e\x8f\x04\x1a\x87to\x89\x89ތ\x00\x00\x02\x00d\xff\xff\x03\xf8\x05\xc4\x00\x17\x00$\x00X\x00\xb0\x00EX\xb0\v/\x1b\xb1\v\x1c>Y\xb0\x00EX\xb0\x13/\x1b\xb1\x13\x10>Y\xb2\x03\x13\v\x11\x129\xb0\x03/\xb2\x00\x03\v\x11\x129\xb0\x13\x10\xb2\x14\x01\n+X!\xd8\x1b\xf4Y\xb0\x03\x10\xb2\x18\x01\n+X!\xd8\x1b\xf4Y\xb0\v\x10\xb2\x1f\x01\n+X!\xd8\x1b\xf4Y01\x01\x06\x06#\"&&546632\x12\x11\x15\x10\x00\x05#5366%26754&#\"\x06\x15\x14\x16\x03>:\xa1`~\xbbfö\xd8\xf9\xfe\xb0\xfe\xad$'\xe5\xf6\xfe\xee]\x9d$\x9eyz\x94\x8f\x02\x80ET|ሒ\xea|\xfe\xbd\xfe\xe96\xfeW\xfey\x05\x9c\x04\xe7\xfarTJ\xb6仙\x95\xc1\x00\xff\xff\x00\x86\xff\xf5\x01m\x04D\x00&\x00\x12\xf6\x00\x01\a\x00\x12\xff\xf7\x03s\x00\x10\x00\xb0\x00EX\xb0\r/\x1b\xb1\r\x18>Y01\xff\xff\x00)\xfe\xde\x01U\x04D\x00'\x00\x12\xff\xdf\x03s\x01\x06\x00\x10\f\x00\x00\x10\x00\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x18>Y01\x00\x01\x00H\x00\xc3\x03z\x04J\x00\x06\x00\x16\x00\xb0\x00EX\xb0\x05/\x1b\xb1\x05\x18>Y\xb0\x02а\x02/01\x01\x05\x15\x015\x01\x15\x01\b\x02r\xfc\xce\x032\x02\x84\xfd\xc4\x01{\x92\x01z\xc4\x00\x00\x02\x00\x98\x01\x8f\x03\xda\x03\xcf\x00\x03\x00\a\x00%\x00\xb0\a/\xb0\x03а\x03/\xb2\x00\x01\n+X!\xd8\x1b\xf4Y\xb0\a\x10\xb2\x04\x01\n+X!\xd8\x1b\xf4Y01\x01!5!\x11!5!\x03\xda\xfc\xbe\x03B\xfc\xbe\x03B\x03.\xa1\xfd\xc0\xa0\x00\x00\x01\x00\x86\x00\xc4\x03\xdc\x04K\x00\x06\x00\x16\x00\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x18>Y\xb0\x05а\x05/01\x01\x015\x01\x15\x015\x03\x1b\xfdk\x03V\xfc\xaa\x02\x8a\x01\x03\xbe\xfe\x86\x92\xfe\x85\xc0\x00\x02\x00K\xff\xf5\x03v\x05\xc4\x00\x18\x00!\x00Q\x00\xb0\x00EX\xb0\x10/\x1b\xb1\x10\x1c>Y\xb0\x00EX\xb0 /\x1b\xb1 \x10>Y\xb2\x1b\x05\n+X!\xd8\x1b\xf4Y\xb2\x00\x1b\x10\x11\x129\xb2\x04\x10\x00\x11\x129\xb0\x10\x10\xb2\t\x01\n+X!\xd8\x1b\xf4Y\xb0\x10\x10\xb0\fв\x15\x00\x10\x11\x12901\x016677654&#\"\x06\x15#6632\x16\x15\x14\a\a\x06\x15\x03462\x16\x14\x06\"&\x01e\x022M\x83Tnif|\xb9\x02㶽ӢmI\xc17l88l7\x01\x9aw\x8aT\x87_miwl[\xa2\xc7˱\xaf\xaalQ\x98\xfe\xc3-==Z;;\x00\x00\x02\x00j\xfe;\x06\xd6\x05\x97\x005\x00B\x00h\x00\xb02/\xb0\x00EX\xb0\b/\x1b\xb1\b\x10>Y\xb0\x03в\x0f2\b\x11\x129\xb0\x0f/\xb2\x05\b\x0f\x11\x129\xb0\b\x10\xb29\x02\n+X!\xd8\x1b\xf4Y\xb0\x15а2\x10\xb2\x1b\x02\n+X!\xd8\x1b\xf4Y\xb0\b\x10\xb0*а*/\xb2#\x02\n+X!\xd8\x1b\xf4Y\xb0\x0f\x10\xb2@\x02\n+X!\xd8\x1b\xf4Y01\x01\x06\x02#\"'\x06\x06#\"&76\x12632\x16\x17\x03\x063267\x12\x00!\"\x04\x02\a\x06\x12\x043267\x17\x06\x06#\"$\x02\x13\x12\x12$32\x04\x12\x01\x06\x1632677\x13&#\"\x06\x06\xca\fص\xbb56\x8bJ\x8e\x92\x13\x0fy\xbfiQ\x80P4\x13\x93q\x8c\x06\x13\xfe\xb9\xfe\xb2\xc9\xfeȴ\v\f\x90\x01'\xd1Z\xb5<%>\xcdi\xfa\xfe\x98\xb3\f\f\xde\x01|\xef\xf9\x01d\xae\xfb\xf2\x0eQXY\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x10>Y\xb0\x00EX\xb0\x06/\x1b\xb1\x06\x10>Y\xb2\t\x04\x02\x11\x129\xb0\t/\xb2\x00\x01\n+X!\xd8\x1b\xf4Y\xb2\n\x04\x02\x11\x12901\x01!\x03#\x013\x01#\x01!\x03\x03\xcd\xfd\x9e\x89\xc6\x02,\xa8\x02-\xc5\xfdM\x01\xef\xf8\x01|\xfe\x84\x05\xb0\xfaP\x02\x1a\x02\xa9\x00\x03\x00\xa9\x00\x00\x04\x88\x05\xb0\x00\x0e\x00\x16\x00\x1f\x00U\x00\xb0\x00EX\xb0\x01/\x1b\xb1\x01\x1c>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x10>Y\xb2\x17\x00\x01\x11\x129\xb0\x17/\xb2\x0f\x01\n+X!\xd8\x1b\xf4Y\xb2\b\x0f\x17\x11\x129\xb0\x00\x10\xb2\x10\x01\n+X!\xd8\x1b\xf4Y\xb0\x01\x10\xb2\x1f\x01\n+X!\xd8\x1b\xf4Y013\x11!2\x16\x15\x14\x06\a\x16\x16\x15\x14\x06#\x01\x11!265\x10!%!2654&#!\xa9\x01\xdc\xed\xeftdv\x89\xfe\xe8\xfe\xc7\x01=\x86\x9b\xfe\xe2\xfe\xc0\x01\"~\x97\x8c\x8f\xfe\xe4\x05\xb0\xc4\xc0f\x9d+!\xb9\x80\xc4\xe0\x02\xa9\xfd\xf4\x8bz\x01\a\x9a~lxm\x00\x00\x01\x00w\xff\xec\x04\xd8\x05\xc4\x00\x1c\x00E\x00\xb0\x00EX\xb0\v/\x1b\xb1\v\x1c>Y\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x10>Y\xb0\v\x10\xb0\x0fа\v\x10\xb2\x12\x01\n+X!\xd8\x1b\xf4Y\xb0\x03\x10\xb2\x19\x01\n+X!\xd8\x1b\xf4Y\xb0\x03\x10\xb0\x1c\xd001\x01\x06\x04# \x00\x1154\x12$32\x00\x17#&&#\"\x02\x15\x15\x14\x123267\x04\xd8\x1b\xfe\xe1\xee\xfe\xfe\xfeɑ\x01\n\xaf\xe8\x01\x18\x17\xc1\x19\xa7\x96\xb8\xd1Ʋ\xa0\xab\x1c\x01\xce\xe7\xfb\x01r\x016\x8c\xcb\x014\xa5\xfe\xfd宜\xfe\xf0\xfb\x8d\xed\xfe葴\x00\x02\x00\xa9\x00\x00\x04\xc6\x05\xb0\x00\v\x00\x15\x009\x00\xb0\x00EX\xb0\x01/\x1b\xb1\x01\x1c>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x10>Y\xb0\x01\x10\xb2\f\x01\n+X!\xd8\x1b\xf4Y\xb0\x00\x10\xb2\r\x01\n+X!\xd8\x1b\xf4Y013\x11!2\x04\x12\x17\x15\x14\x02\x04\a\x03\x1132\x12554\x02'\xa9\x01\x9b\xbe\x01$\x9f\x01\x9f\xfe\xd9\xc4\xd3\xca\xde\xf7\xe9\xd6\x05\xb0\xa8\xfe\xca\xc9]\xce\xfeʦ\x02\x05\x12\xfb\x8b\x01\x14\xffU\xf8\x01\x13\x02\x00\x00\x01\x00\xa9\x00\x00\x04F\x05\xb0\x00\v\x00N\x00\xb0\x00EX\xb0\x06/\x1b\xb1\x06\x1c>Y\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x10>Y\xb2\v\x04\x06\x11\x129\xb0\v/\xb2\x00\x01\n+X!\xd8\x1b\xf4Y\xb0\x04\x10\xb2\x02\x01\n+X!\xd8\x1b\xf4Y\xb0\x06\x10\xb2\b\x01\n+X!\xd8\x1b\xf4Y01\x01!\x11!\x15!\x11!\x15!\x11!\x03\xe0\xfd\x89\x02\xdd\xfcc\x03\x93\xfd-\x02w\x02\xa1\xfd\xfc\x9d\x05\xb0\x9e\xfe,\x00\x01\x00\xa9\x00\x00\x04/\x05\xb0\x00\t\x00@\x00\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x1c>Y\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x10>Y\xb2\t\x02\x04\x11\x129\xb0\t/\xb2\x00\x01\n+X!\xd8\x1b\xf4Y\xb0\x04\x10\xb2\x06\x01\n+X!\xd8\x1b\xf4Y01\x01!\x11#\x11!\x15!\x11!\x03\xcc\xfd\x9d\xc0\x03\x86\xfd:\x02c\x02\x83\xfd}\x05\xb0\x9e\xfe\x0e\x00\x01\x00z\xff\xec\x04\xdc\x05\xc4\x00\x1f\x00b\x00\xb0\x00EX\xb0\v/\x1b\xb1\v\x1c>Y\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x10>Y\xb0\v\x10\xb0\x0fа\v\x10\xb2\x11\x01\n+X!\xd8\x1b\xf4Y\xb0\x03\x10\xb2\x18\x01\n+X!\xd8\x1b\xf4Y\xb2\x1e\x03\v\x11\x129\xb0\x1e/\xb4\x0f\x1e\x1f\x1e\x02]\xb4?\x1eO\x1e\x02]\xb2\x1d\x01\n+X!\xd8\x1b\xf4Y01%\x06\x04#\"$\x02'5\x10\x00!2\x04\x17#\x02!\"\x02\x03\x15\x14\x123267\x11!5!\x04\xdcJ\xfe\xf7\xb0\xb2\xfe\xec\x97\x02\x013\x01\x16\xe4\x01\x16\x1f\xc06\xfe\xde\xc1\xc7\x01\xe0\xbfl\xa25\xfe\xaf\x02\x10\xbfji\xa7\x014\xcb\u007f\x01I\x01j\xe9\xd6\x01!\xfe\xf1\xfe\xffw\xf5\xfe\xdf09\x01G\x9c\x00\x01\x00\xa9\x00\x00\x05\b\x05\xb0\x00\v\x00U\x00\xb0\x00EX\xb0\x06/\x1b\xb1\x06\x1c>Y\xb0\x00EX\xb0\n/\x1b\xb1\n\x1c>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x10>Y\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x10>Y\xb0\x00\x10\xb0\tа\t/\xb2\x9f\t\x01r\xb2/\t\x01]\xb2\x02\x01\n+X!\xd8\x1b\xf4Y01!#\x11!\x11#\x113\x11!\x113\x05\b\xc1\xfd\"\xc0\xc0\x02\xde\xc1\x02\xa1\xfd_\x05\xb0\xfd\x8e\x02r\x00\x00\x01\x00\xb7\x00\x00\x01w\x05\xb0\x00\x03\x00\x1d\x00\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x1c>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x10>Y01!#\x113\x01w\xc0\xc0\x05\xb0\x00\x00\x01\x005\xff\xec\x03\xcc\x05\xb0\x00\x0f\x00.\x00\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x1c>Y\xb0\x00EX\xb0\x05/\x1b\xb1\x05\x10>Y\xb0\tа\x05\x10\xb2\f\x01\n+X!\xd8\x1b\xf4Y01\x013\x11\x14\x06#\"&53\x14\x163267\x03\v\xc1\xfb\xd1\xd9\xf2\xc0\x89\x82w\x93\x01\x05\xb0\xfb\xf9\xd1\xec\xde\xc8}\x8c\x96\x87\x00\x00\x01\x00\xa9\x00\x00\x05\x05\x05\xb0\x00\v\x00t\x00\xb0\x00EX\xb0\x05/\x1b\xb1\x05\x1c>Y\xb0\x00EX\xb0\a/\x1b\xb1\a\x1c>Y\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x10>Y\xb0\x00EX\xb0\v/\x1b\xb1\v\x10>Y\xb2\x00\x02\x05\x11\x129@\x11J\x00Z\x00j\x00z\x00\x8a\x00\x9a\x00\xaa\x00\xba\x00\b]\xb29\x00\x01]\xb2\x06\x05\x02\x11\x129@\x136\x06F\x06V\x06f\x06v\x06\x86\x06\x96\x06\xa6\x06\xb6\x06\t]01\x01\a\x11#\x113\x11\x013\x01\x01#\x02\x1b\xb2\xc0\xc0\x02\x87\xe8\xfd\xc3\x02j\xe6\x02\xa5\xb9\xfe\x14\x05\xb0\xfd0\x02\xd0\xfd}\xfc\xd3\x00\x01\x00\xa9\x00\x00\x04\x1c\x05\xb0\x00\x05\x00(\x00\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x1c>Y\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x10>Y\xb2\x00\x01\n+X!\xd8\x1b\xf4Y01%!\x15!\x113\x01j\x02\xb2\xfc\x8d\xc1\x9d\x9d\x05\xb0\x00\x00\x01\x00\xa9\x00\x00\x06R\x05\xb0\x00\x0e\x00Y\x00\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x1c>Y\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x1c>Y\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x10>Y\xb0\x00EX\xb0\b/\x1b\xb1\b\x10>Y\xb0\x00EX\xb0\f/\x1b\xb1\f\x10>Y\xb2\x01\x00\x04\x11\x129\xb2\a\x00\x04\x11\x129\xb2\n\x00\x04\x11\x12901\t\x023\x11#\x11\x13\x01#\x01\x13\x11#\x11\x01\xa1\x01\xdc\x01\xdc\xf9\xc0\x12\xfe\"\x93\xfe#\x13\xc0\x05\xb0\xfb\\\x04\xa4\xfaP\x027\x02d\xfbe\x04\x98\xfd\x9f\xfd\xc9\x05\xb0\x00\x00\x01\x00\xa9\x00\x00\x05\b\x05\xb0\x00\t\x00L\xb2\x01\n\v\x11\x129\x00\xb0\x00EX\xb0\x05/\x1b\xb1\x05\x1c>Y\xb0\x00EX\xb0\b/\x1b\xb1\b\x1c>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x10>Y\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x10>Y\xb2\x02\x05\x00\x11\x129\xb2\a\x05\x00\x11\x12901!#\x01\x11#\x113\x01\x113\x05\b\xc1\xfd#\xc1\xc1\x02\u07ff\x04b\xfb\x9e\x05\xb0\xfb\x99\x04g\x00\x02\x00v\xff\xec\x05\t\x05\xc4\x00\x11\x00\x1f\x009\x00\xb0\x00EX\xb0\r/\x1b\xb1\r\x1c>Y\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x10>Y\xb0\r\x10\xb2\x15\x01\n+X!\xd8\x1b\xf4Y\xb0\x04\x10\xb2\x1c\x01\n+X!\xd8\x1b\xf4Y01\x01\x14\x02\x04#\"$\x02'54\x12$32\x04\x12\x15'\x10\x02#\"\x02\a\x15\x14\x1232\x127\x05\t\x90\xfe\xf8\xb0\xac\xfe\xf6\x93\x02\x92\x01\v\xac\xaf\x01\v\x90\xbfл\xb6\xd1\x03ӹ\xba\xcc\x03\x02\xa9\xd6\xfe\xc1\xa8\xa9\x019\xcei\xd2\x01B\xab\xa9\xfe\xbf\xd5\x02\x01\x03\x01\x15\xfe\xeb\xf6k\xfb\xfe\xe1\x01\x0f\xfd\x00\x00\x02\x00\xa9\x00\x00\x04\xc0\x05\xb0\x00\n\x00\x13\x00M\xb2\n\x14\x15\x11\x129\xb0\n\x10\xb0\f\xd0\x00\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x1c>Y\xb0\x00EX\xb0\x01/\x1b\xb1\x01\x10>Y\xb2\v\x03\x01\x11\x129\xb0\v/\xb2\x00\x01\n+X!\xd8\x1b\xf4Y\xb0\x03\x10\xb2\x12\x01\n+X!\xd8\x1b\xf4Y01\x01\x11#\x11!2\x04\x15\x14\x04#%!2654&'!\x01i\xc0\x02\x19\xef\x01\x0f\xfe\xf7\xf7\xfe\xa9\x01Y\x9a\xa4\xa4\x8f\xfe\x9c\x02:\xfd\xc6\x05\xb0\xf4\xc9\xd4坑\x89\x82\x9c\x03\x00\x02\x00m\xff\n\x05\x06\x05\xc4\x00\x15\x00\"\x00M\xb2\b#$\x11\x129\xb0\b\x10\xb0\x19\xd0\x00\xb0\x00EX\xb0\x11/\x1b\xb1\x11\x1c>Y\xb0\x00EX\xb0\b/\x1b\xb1\b\x10>Y\xb2\x03\b\x11\x11\x129\xb0\x11\x10\xb2\x19\x01\n+X!\xd8\x1b\xf4Y\xb0\b\x10\xb2 \x01\n+X!\xd8\x1b\xf4Y01\x01\x14\x02\a\x05\a%\x06#\"$\x02'54\x12$32\x04\x12\x15'\x10\x02#\"\x02\a\x15\x14\x12 \x127\x05\x01\x86y\x01\x04\x83\xfe\xcdHP\xac\xfe\xf6\x93\x02\x92\x01\v\xac\xb0\x01\v\x90\xc0;\xb5\xd1\x03\xd1\x01t\xcc\x03\x02\xa9\xd3\xfe\xcfV\xccy\xf4\x12\xa9\x019\xcei\xd2\x01B\xab\xaa\xfe\xc1\xd5\x01\x01\x01\x01\x17\xfe\xeb\xf6k\xfa\xfe\xe0\x01\x0f\xfd\x00\x00\x02\x00\xa8\x00\x00\x04\xc9\x05\xb0\x00\x0e\x00\x17\x00a\xb2\x05\x18\x19\x11\x129\xb0\x05\x10\xb0\x16\xd0\x00\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x1c>Y\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x10>Y\xb0\x00EX\xb0\r/\x1b\xb1\r\x10>Y\xb2\x10\x04\x02\x11\x129\xb0\x10/\xb2\x00\x01\n+X!\xd8\x1b\xf4Y\xb2\v\x00\x04\x11\x129\xb0\x04\x10\xb2\x16\x01\n+X!\xd8\x1b\xf4Y01\x01!\x11#\x11!2\x04\x15\x14\x06\a\x01\x15#\x01!2654&'!\x02\xbf\xfe\xaa\xc1\x01\xe2\xf6\x01\t\x93\x83\x01V\xce\xfdn\x01'\x8f\xa9\xa1\x98\xfe\xda\x02M\xfd\xb3\x05\xb0\xe0\u0588\xca2\xfd\x96\f\x02\xea\x94|\x87\x90\x01\x00\x00\x01\x00P\xff\xec\x04r\x05\xc4\x00&\x00a\xb2\x00'(\x11\x129\x00\xb0\x00EX\xb0\x06/\x1b\xb1\x06\x1c>Y\xb0\x00EX\xb0\x1a/\x1b\xb1\x1a\x10>Y\xb0\x06\x10\xb0\vа\x06\x10\xb2\x0e\x01\n+X!\xd8\x1b\xf4Y\xb2&\x1a\x06\x11\x129\xb0&\x10\xb2\x14\x01\n+X!\xd8\x1b\xf4Y\xb0\x1a\x10\xb0\x1fа\x1a\x10\xb2\"\x01\n+X!\xd8\x1b\xf4Y01\x01&&54$32\x16\x16\x15#4&#\"\x06\x15\x14\x16\x04\x16\x16\x15\x14\x04#\"$&53\x14\x163264&\x02V\xf7\xe1\x01\x13ܖ\xeb\x81\xc1\xa8\x99\x8e\x9f\x97\x01k\xcdc\xfe\xec\xe7\x96\xfe\xfc\x8d\xc1ã\x98\xa2\x96\x02\x89GϘ\xac\xe1t\xccy\x84\x97}oY{f{\xa4o\xb1\xd5s\xc8\u007f\x84\x99|\xd6u\x00\x00\x01\x001\x00\x00\x04\x97\x05\xb0\x00\a\x00.\x00\xb0\x00EX\xb0\x06/\x1b\xb1\x06\x1c>Y\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x10>Y\xb0\x06\x10\xb2\x00\x01\n+X!\xd8\x1b\xf4Y\xb0\x04\xd001\x01!\x11#\x11!5!\x04\x97\xfe,\xbf\xfe-\x04f\x05\x12\xfa\xee\x05\x12\x9e\x00\x01\x00\x8c\xff\xec\x04\xaa\x05\xb0\x00\x12\x00<\xb2\x05\x13\x14\x11\x129\x00\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x1c>Y\xb0\x00EX\xb0\t/\x1b\xb1\t\x1c>Y\xb0\x00EX\xb0\x05/\x1b\xb1\x05\x10>Y\xb2\x0e\x01\n+X!\xd8\x1b\xf4Y01\x01\x11\x06\x00\a\a\"\x00'\x113\x11\x14\x163265\x11\x04\xaa\x01\xfe\xff\xdc3\xef\xfe\xe4\x02\xbe\xae\xa1\xa3\xad\x05\xb0\xfc\"\xce\xfe\xfa\x10\x02\x01\x02\xe2\x03\xe0\xfc&\x9e\xaf\xae\x9e\x03\xdb\x00\x00\x01\x00\x1c\x00\x00\x04\xfd\x05\xb0\x00\x06\x008\xb2\x00\a\b\x11\x129\x00\xb0\x00EX\xb0\x01/\x1b\xb1\x01\x1c>Y\xb0\x00EX\xb0\x05/\x1b\xb1\x05\x1c>Y\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x10>Y\xb2\x00\x01\x03\x11\x12901%\x013\x01#\x013\x02\x8b\x01\xa0\xd2\xfd\xe4\xaa\xfd\xe5\xd1\xff\x04\xb1\xfaP\x05\xb0\x00\x00\x01\x00=\x00\x00\x06\xed\x05\xb0\x00\x12\x00Y\x00\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x1c>Y\xb0\x00EX\xb0\b/\x1b\xb1\b\x1c>Y\xb0\x00EX\xb0\x11/\x1b\xb1\x11\x1c>Y\xb0\x00EX\xb0\n/\x1b\xb1\n\x10>Y\xb0\x00EX\xb0\x0f/\x1b\xb1\x0f\x10>Y\xb2\x01\x03\n\x11\x129\xb2\x06\x03\n\x11\x129\xb2\r\x03\n\x11\x12901\x01\x177\x013\x01\x177\x133\x01#\x01'\a\x01#\x013\x01\xe3\x1c)\x01 \xa2\x01\x19(\x1f\xe2\xc1\xfe\x9f\xaf\xfe\xd4\x17\x17\xfeɯ\xfe\xa0\xc0\x01\xcb\xc0\xad\x03\xf8\xfc\b\xb0\xc4\x03\xe4\xfaP\x04%oo\xfb\xdb\x05\xb0\x00\x01\x009\x00\x00\x04\xce\x05\xb0\x00\v\x00k\x00\xb0\x00EX\xb0\x01/\x1b\xb1\x01\x1c>Y\xb0\x00EX\xb0\n/\x1b\xb1\n\x1c>Y\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x10>Y\xb0\x00EX\xb0\a/\x1b\xb1\a\x10>Y\xb2\x00\x01\x04\x11\x129@\t\x86\x00\x96\x00\xa6\x00\xb6\x00\x04]\xb2\x06\x01\x04\x11\x129@\t\x89\x06\x99\x06\xa9\x06\xb9\x06\x04]\xb2\x03\x00\x06\x11\x129\xb2\t\x06\x00\x11\x12901\x01\x013\x01\x01#\x01\x01#\x01\x013\x02\x84\x01]\xe2\xfe4\x01\xd7\xe4\xfe\x9a\xfe\x98\xe3\x01\xd8\xfe3\xe1\x03\x82\x02.\xfd.\xfd\"\x028\xfd\xc8\x02\xde\x02\xd2\x00\x00\x01\x00\x0f\x00\x00\x04\xbb\x05\xb0\x00\b\x001\x00\xb0\x00EX\xb0\x01/\x1b\xb1\x01\x1c>Y\xb0\x00EX\xb0\a/\x1b\xb1\a\x1c>Y\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x10>Y\xb2\x00\x01\x04\x11\x12901\x01\x013\x01\x11#\x11\x013\x02e\x01|\xda\xfe\n\xc0\xfe\n\xdc\x02\xd5\x02\xdb\xfco\xfd\xe1\x02\x1f\x03\x91\x00\x00\x01\x00V\x00\x00\x04z\x05\xb0\x00\t\x00D\x00\xb0\x00EX\xb0\a/\x1b\xb1\a\x1c>Y\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x10>Y\xb2\x00\x01\n+X!\xd8\x1b\xf4Y\xb2\x04\x00\x02\x11\x129\xb0\a\x10\xb2\x05\x01\n+X!\xd8\x1b\xf4Y\xb2\t\x05\a\x11\x12901%!\x15!5\x01!5!\x15\x019\x03A\xfb\xdc\x03\x1e\xfc\xef\x03\xf7\x9d\x9d\x90\x04\x82\x9e\x8d\x00\x00\x01\x00\x92\xfe\xc8\x02\v\x06\x80\x00\a\x00\"\x00\xb0\x04/\xb0\a/\xb2\x00\x01\n+X!\xd8\x1b\xf4Y\xb0\x04\x10\xb2\x03\x01\n+X!\xd8\x1b\xf4Y01\x01#\x113\x15!\x11!\x02\v\xbf\xbf\xfe\x87\x01y\x05\xe8\xf9x\x98\a\xb8\x00\x00\x01\x00(\xff\x83\x038\x05\xb0\x00\x03\x00\x13\x00\xb0\x02/\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x1c>Y01\x133\x01#(\xb0\x02`\xb0\x05\xb0\xf9\xd3\x00\x01\x00\t\xfe\xc8\x01\x83\x06\x80\x00\a\x00%\x00\xb0\x02/\xb0\x01/\xb0\x02\x10\xb2\x05\x01\n+X!\xd8\x1b\xf4Y\xb0\x01\x10\xb2\x06\x01\n+X!\xd8\x1b\xf4Y01\x13!\x11!53\x11#\t\x01z\xfe\x86\xc1\xc1\x06\x80\xf8H\x98\x06\x88\x00\x00\x01\x00@\x02\xd9\x03\x14\x05\xb0\x00\x06\x00'\xb2\x00\a\b\x11\x129\x00\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x1c>Y\xb0\x00в\x01\a\x03\x11\x129\xb0\x01/\xb0\x05\xd001\x01\x03#\x013\x01#\x01\xaa\xbe\xac\x01+\u007f\x01*\xab\x04\xbb\xfe\x1e\x02\xd7\xfd)\x00\x01\x00\x04\xffi\x03\x98\x00\x00\x00\x03\x00\x1b\x00\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x10>Y\xb2\x00\x01\n+X!\xd8\x1b\xf4Y01\x05!5!\x03\x98\xfcl\x03\x94\x97\x97\x00\x00\x01\x009\x04\xd8\x01\xda\x05\xfe\x00\x03\x00#\x00\xb0\x01/\xb2\x0f\x01\x01]\xb0\x00\xd0\x19\xb0\x00/\x18\xb0\x01\x10\xb0\x02а\x02/\xb4\x0f\x02\x1f\x02\x02]01\x01#\x013\x01ڟ\xfe\xfe\xdf\x04\xd8\x01&\x00\x00\x02\x00m\xff\xec\x03\xea\x04N\x00\x1e\x00(\x00y\xb2\x17)*\x11\x129\xb0\x17\x10\xb0 \xd0\x00\xb0\x00EX\xb0\x17/\x1b\xb1\x17\x18>Y\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x10>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x10>Y\xb2\x02\x17\x04\x11\x129\xb2\v\x17\x04\x11\x129\xb0\v/\xb0\x17\x10\xb2\x0f\x01\n+X!\xd8\x1b\xf4Y\xb2\x12\v\x17\x11\x129\xb0\x04\x10\xb2\x1f\x01\n+X!\xd8\x1b\xf4Y\xb0\v\x10\xb2#\x01\n+X!\xd8\x1b\xf4Y01!&'\x06#\"&54$3354&#\"\x06\x15#46632\x16\x17\x11\x14\x17\x15%2675# \x15\x14\x16\x03(\x10\n\x81\xb3\xa0\xcd\x01\x01\xe9\xb4tqc\x86\xbas\xc5v\xbb\xd4\x04&\xfe\vW\x9c#\x91\xfe\xact R\x86\xb5\x8b\xa9\xbbUasdGQ\x97X\xbb\xa4\xfe\x0e\x95X\x10\x8dZH\xde\xc7Wb\x00\x02\x00\x8c\xff\xec\x04 \x06\x00\x00\x0e\x00\x19\x00d\xb2\x12\x1a\x1b\x11\x129\xb0\x12\x10\xb0\x03\xd0\x00\xb0\b/\xb0\x00EX\xb0\f/\x1b\xb1\f\x18>Y\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x10>Y\xb0\x00EX\xb0\x06/\x1b\xb1\x06\x10>Y\xb2\x05\b\x03\x11\x129\xb2\n\f\x03\x11\x129\xb0\f\x10\xb2\x12\x01\n+X!\xd8\x1b\xf4Y\xb0\x03\x10\xb2\x17\x01\n+X!\xd8\x1b\xf4Y01\x01\x14\x02#\"'\a#\x113\x116 \x12\x11'4&#\"\a\x11\x16326\x04 \xe4\xc0\xcdp\t\xaa\xb9p\x01\x8aṒ\x89\xb7PU\xb4\x85\x94\x02\x11\xf8\xfeӑ}\x06\x00\xfdË\xfe\xd6\xfe\xfd\x05\xbdΪ\xfe,\xaa\xce\x00\x01\x00\\\xff\xec\x03\xec\x04N\x00\x1d\x00I\xb2\x10\x1e\x1f\x11\x129\x00\xb0\x00EX\xb0\x10/\x1b\xb1\x10\x18>Y\xb0\x00EX\xb0\b/\x1b\xb1\b\x10>Y\xb2\x00\x01\n+X!\xd8\x1b\xf4Y\xb0\b\x10\xb0\x03а\x10\x10\xb0\x14а\x10\x10\xb2\x17\x01\n+X!\xd8\x1b\xf4Y01%2673\x0e\x02#\"\x00\x11546632\x16\x17#&&#\"\x06\x15\x15\x14\x16\x02>c\x94\b\xaf\x05v\xc5n\xdd\xfe\xfbtٔ\xb6\xf1\b\xaf\b\x8fi\x8d\x9b\x9a\x83xZ]\xa8d\x01'\x01\x00\x1f\x9e\xf6\x88ڮi\x87\xcb\xc0#\xbb\xca\x00\x00\x02\x00_\xff\xec\x03\xf0\x06\x00\x00\x0f\x00\x1a\x00d\xb2\x18\x1b\x1c\x11\x129\xb0\x18\x10\xb0\x03\xd0\x00\xb0\x06/\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x18>Y\xb0\x00EX\xb0\f/\x1b\xb1\f\x10>Y\xb0\x00EX\xb0\b/\x1b\xb1\b\x10>Y\xb2\x05\x03\f\x11\x129\xb2\n\x03\f\x11\x129\xb0\f\x10\xb2\x13\x01\n+X!\xd8\x1b\xf4Y\xb0\x03\x10\xb2\x18\x01\n+X!\xd8\x1b\xf4Y01\x134\x1232\x17\x113\x11#'\x06#\"\x025\x17\x14\x16327\x11&#\"\x06_쿾o\xb9\xaa\toƼ\xed\xb9\x98\x86\xb0QS\xac\x88\x98\x02&\xf9\x01/\x82\x024\xfa\x00t\x88\x014\xf8\a\xb8О\x01\xf1\x99\xd2\x00\x00\x02\x00]\xff\xec\x03\xf3\x04N\x00\x15\x00\x1d\x00i\xb2\b\x1e\x1f\x11\x129\xb0\b\x10\xb0\x16\xd0\x00\xb0\x00EX\xb0\b/\x1b\xb1\b\x18>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x10>Y\xb2\x1a\b\x00\x11\x129\xb0\x1a/\xb4\xbf\x1a\xcf\x1a\x02]\xb2\f\x01\n+X!\xd8\x1b\xf4Y\xb0\x00\x10\xb2\x10\x01\n+X!\xd8\x1b\xf4Y\xb2\x13\b\x00\x11\x129\xb0\b\x10\xb2\x16\x01\n+X!\xd8\x1b\xf4Y01\x05\"\x005546632\x12\x11\x15!\x16\x163267\x17\x06\x01\"\x06\a!5&&\x02M\xdc\xfe\xec{݁\xd3\xea\xfd#\x04\xb3\x8ab\x883q\x88\xfe\xd9p\x98\x12\x02\x1e\b\x88\x14\x01!\xf2\"\xa1\xfd\x8f\xfe\xea\xfe\xfdM\xa0\xc5PBX\xd1\x03ʣ\x93\x0e\x8d\x9b\x00\x01\x00<\x00\x00\x02\xca\x06\x15\x00\x15\x00c\xb2\x0f\x16\x17\x11\x129\x00\xb0\x00EX\xb0\b/\x1b\xb1\b\x1e>Y\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x18>Y\xb0\x00EX\xb0\x11/\x1b\xb1\x11\x18>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x10>Y\xb0\x03\x10\xb2\x01\x01\n+X!\xd8\x1b\xf4Y\xb0\b\x10\xb2\r\x01\n+X!\xd8\x1b\xf4Y\xb0\x01\x10\xb0\x13а\x14\xd0013\x11#5354632\x17\a&#\"\x06\x15\x153\x15#\x11竫\xba\xaa@?\n/5Zb\xe7\xe7\x03\xab\x8fo\xae\xbe\x11\x96\tibr\x8f\xfcU\x00\x02\x00`\xfeV\x03\xf2\x04N\x00\x19\x00$\x00\x83\xb2\"%&\x11\x129\xb0\"\x10\xb0\v\xd0\x00\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x18>Y\xb0\x00EX\xb0\x06/\x1b\xb1\x06\x18>Y\xb0\x00EX\xb0\v/\x1b\xb1\v\x12>Y\xb0\x00EX\xb0\x17/\x1b\xb1\x17\x10>Y\xb2\x05\x03\x17\x11\x129\xb2\x0f\x17\v\x11\x129\xb0\v\x10\xb2\x11\x01\n+X!\xd8\x1b\xf4Y\xb2\x15\x03\x17\x11\x129\xb0\x17\x10\xb2\x1d\x01\n+X!\xd8\x1b\xf4Y\xb0\x03\x10\xb2\"\x01\n+X!\xd8\x1b\xf4Y01\x134\x1232\x1773\x11\x14\x06#\"&'7\x1632655\x06#\"\x027\x14\x16327\x11&#\"\x06`\xea\xc1\xc6o\t\xa9\xf9\xd2u\xe0;`w\xac\x87\x97o\xc0\xbe뺖\x87\xafRU\xaa\x87\x98\x02&\xfd\x01+\x8cx\xfb\xe0\xd2\xf2dWo\x93\x98\x8a]\x80\x012\xf3\xb7џ\x01\xee\x9b\xd2\x00\x00\x01\x00\x8c\x00\x00\x03\xdf\x06\x00\x00\x11\x00I\xb2\n\x12\x13\x11\x129\x00\xb0\x10/\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x18>Y\xb0\x00EX\xb0\x05/\x1b\xb1\x05\x10>Y\xb0\x00EX\xb0\x0e/\x1b\xb1\x0e\x10>Y\xb2\x00\x02\x05\x11\x129\xb0\x02\x10\xb2\n\x01\n+X!\xd8\x1b\xf4Y01\x0163 \x13\x11#\x11&&#\"\x06\a\x11#\x113\x01E{\xc5\x01W\x03\xb9\x01ioZ\x88&\xb9\xb9\x03\xb7\x97\xfe}\xfd5\x02\xccup`N\xfc\xfd\x06\x00\x00\x02\x00\x8d\x00\x00\x01h\x05\xc4\x00\x03\x00\f\x00>\xb2\x06\r\x0e\x11\x129\xb0\x06\x10\xb0\x01\xd0\x00\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x18>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x10>Y\xb0\x02\x10\xb0\nа\n/\xb2\x06\x05\n+X!\xd8\x1b\xf4Y01!#\x113\x03462\x16\x14\x06\"&\x01U\xb9\xb9\xc87l88l7\x04:\x01\x1f->>Z<<\x00\x02\xff\xbf\xfeK\x01Y\x05\xc4\x00\f\x00\x16\x00I\xb2\x10\x17\x18\x11\x129\xb0\x10\x10\xb0\x00\xd0\x00\xb0\x00EX\xb0\f/\x1b\xb1\f\x18>Y\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x12>Y\xb2\b\x01\n+X!\xd8\x1b\xf4Y\xb0\f\x10\xb0\x15а\x15/\xb2\x10\x05\n+X!\xd8\x1b\xf4Y01\x01\x11\x10!\"'5\x163265\x11\x034632\x16\x14\x06\"&\x01K\xfe\xe5=4 4>A\x1375688l6\x04:\xfbI\xfe\xc8\x12\x94\bCS\x04\xbb\x01\x1f,?>Z<<\x00\x00\x01\x00\x8d\x00\x00\x04\f\x06\x00\x00\f\x00u\x00\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x1e>Y\xb0\x00EX\xb0\b/\x1b\xb1\b\x18>Y\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x10>Y\xb0\x00EX\xb0\v/\x1b\xb1\v\x10>Y\xb2\x00\b\x02\x11\x129@\x15:\x00J\x00Z\x00j\x00z\x00\x8a\x00\x9a\x00\xaa\x00\xba\x00\xca\x00\n]\xb2\x06\b\x02\x11\x129@\x156\x06F\x06V\x06f\x06v\x06\x86\x06\x96\x06\xa6\x06\xb6\x06\xc6\x06\n]01\x01\a\x11#\x113\x117\x013\x01\x01#\x01\xbat\xb9\xb9c\x01Q\xe1\xfe[\x01\xd6\xd9\x01\xf5y\xfe\x84\x06\x00\xfc_w\x01d\xfe<\xfd\x8a\x00\x01\x00\x9c\x00\x00\x01U\x06\x00\x00\x03\x00\x1d\x00\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x1e>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x10>Y01!#\x113\x01U\xb9\xb9\x06\x00\x00\x00\x01\x00\x8b\x00\x00\x06x\x04N\x00\x1d\x00w\xb2\x04\x1e\x1f\x11\x129\x00\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x18>Y\xb0\x00EX\xb0\b/\x1b\xb1\b\x18>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x18>Y\xb0\x00EX\xb0\v/\x1b\xb1\v\x10>Y\xb0\x00EX\xb0\x14/\x1b\xb1\x14\x10>Y\xb0\x00EX\xb0\x1b/\x1b\xb1\x1b\x10>Y\xb2\x01\b\v\x11\x129\xb2\x05\b\v\x11\x129\xb0\b\x10\xb2\x10\x01\n+X!\xd8\x1b\xf4Y\xb0\x18\xd001\x01\x17632\x17663 \x13\x11#\x114&#\"\x06\a\x11#\x114#\"\a\x11#\x11\x01:\x05w\xca\xe3R6\xadv\x01d\x06\xb9j}g\x88\v\xba\xe7\xb6C\xb9\x04:x\x8c\xaeN`\xfe\x87\xfd+\x02\xcats{h\xfd2\x02\xc5\xec\x9b\xfc\xea\x04:\x00\x01\x00\x8c\x00\x00\x03\xdf\x04N\x00\x11\x00S\xb2\v\x12\x13\x11\x129\x00\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x18>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x18>Y\xb0\x00EX\xb0\x06/\x1b\xb1\x06\x10>Y\xb0\x00EX\xb0\x0f/\x1b\xb1\x0f\x10>Y\xb2\x01\x03\x06\x11\x129\xb0\x03\x10\xb2\v\x01\n+X!\xd8\x1b\xf4Y01\x01\x1763 \x13\x11#\x11&&#\"\x06\a\x11#\x11\x01;\x06|\xc8\x01W\x03\xb9\x01ioZ\x88&\xb9\x04:\x88\x9c\xfe}\xfd5\x02\xccup`N\xfc\xfd\x04:\x00\x00\x02\x00[\xff\xec\x044\x04N\x00\x0f\x00\x1b\x00C\xb2\f\x1c\x1d\x11\x129\xb0\f\x10\xb0\x13\xd0\x00\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x18>Y\xb0\x00EX\xb0\f/\x1b\xb1\f\x10>Y\xb2\x13\x01\n+X!\xd8\x1b\xf4Y\xb0\x04\x10\xb2\x19\x01\n+X!\xd8\x1b\xf4Y01\x1346632\x00\x15\x15\x14\x06\x06#\"\x005\x17\x14\x1632654&#\"\x06[}ߏ\xdd\x01\x11y\xe1\x92\xdc\xfeﺧ\x8c\x8d\xa6\xa9\x8c\x89\xa8\x02'\x9f\xfe\x8a\xfe\xce\xfe\r\x9e\xfb\x8c\x012\xfc\t\xb4\xda\xddDz\xdd\xda\x00\x02\x00\x8c\xfe`\x04\x1e\x04N\x00\x0f\x00\x1a\x00n\xb2\x13\x1b\x1c\x11\x129\xb0\x13\x10\xb0\f\xd0\x00\xb0\x00EX\xb0\f/\x1b\xb1\f\x18>Y\xb0\x00EX\xb0\t/\x1b\xb1\t\x18>Y\xb0\x00EX\xb0\x06/\x1b\xb1\x06\x12>Y\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x10>Y\xb2\x05\f\x03\x11\x129\xb2\n\f\x03\x11\x129\xb0\f\x10\xb2\x13\x01\n+X!\xd8\x1b\xf4Y\xb0\x03\x10\xb2\x18\x01\n+X!\xd8\x1b\xf4Y01\x01\x14\x02#\"'\x11#\x113\x17632\x12\x11'4&#\"\a\x11\x16326\x04\x1e\xe2\xc1\xc5q\xb9\xa9\tq\xc9\xc3㹜\x88\xa8TS\xab\x85\x9d\x02\x11\xf7\xfe\xd2}\xfd\xf7\x05\xdax\x8c\xfe\xda\xfe\xfa\x04\xb7ԕ\xfd\xfb\x94\xd3\x00\x00\x02\x00_\xfe`\x03\xef\x04N\x00\x0f\x00\x1a\x00k\xb2\x18\x1b\x1c\x11\x129\xb0\x18\x10\xb0\x03\xd0\x00\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x18>Y\xb0\x00EX\xb0\x06/\x1b\xb1\x06\x18>Y\xb0\x00EX\xb0\b/\x1b\xb1\b\x12>Y\xb0\x00EX\xb0\f/\x1b\xb1\f\x10>Y\xb2\x05\x03\f\x11\x129\xb2\n\x03\f\x11\x129\xb2\x13\x01\n+X!\xd8\x1b\xf4Y\xb0\x03\x10\xb2\x18\x01\n+X!\xd8\x1b\xf4Y01\x134\x1232\x1773\x11#\x11\x06#\"\x025\x17\x14\x16327\x11&#\"\x06_\xea\xc5\xc0o\b\xaa\xb9p\xba\xc4鹝\x85\xa5WX\xa2\x86\x9e\x02&\xff\x01)\x81m\xfa&\x02\x04x\x011\xfc\b\xbaԒ\x02\x12\x8f\xd5\x00\x01\x00\x8c\x00\x00\x02\x97\x04N\x00\r\x00F\xb2\x04\x0e\x0f\x11\x129\x00\xb0\x00EX\xb0\v/\x1b\xb1\v\x18>Y\xb0\x00EX\xb0\b/\x1b\xb1\b\x18>Y\xb0\x00EX\xb0\x05/\x1b\xb1\x05\x10>Y\xb0\v\x10\xb2\x02\x01\n+X!\xd8\x1b\xf4Y\xb2\t\v\x05\x11\x12901\x01&#\"\a\x11#\x113\x17632\x17\x02\x97*1\xb6A\xb9\xb4\x03[\xa76\x1c\x03\x94\a\x9b\xfd\x00\x04:}\x91\x0e\x00\x01\x00_\xff\xec\x03\xbb\x04N\x00&\x00a\xb2\t'(\x11\x129\x00\xb0\x00EX\xb0\t/\x1b\xb1\t\x18>Y\xb0\x00EX\xb0\x1c/\x1b\xb1\x1c\x10>Y\xb2\x03\x1c\t\x11\x129\xb0\t\x10\xb0\rа\t\x10\xb2\x10\x01\n+X!\xd8\x1b\xf4Y\xb0\x03\x10\xb2\x15\x01\n+X!\xd8\x1b\xf4Y\xb0\x1c\x10\xb0!а\x1c\x10\xb2$\x01\n+X!\xd8\x1b\xf4Y01\x014&$&&54632\x16\x15#4&#\"\x06\x15\x14\x16\x04\x16\x16\x15\x14\x06#\"&&53\x16\x16326\x03\x02q\xfe\xe7\xa5O\u1bf8庁berj\x01\x15\xacS蹂\xc8q\xb9\x05\x8bri\u007f\x01\x1fKSVyW\x91\xaf\\\xa5`]mU\x00\x01\x00\t\xff\xec\x02V\x05@\x00\x15\x00_\xb2\x0e\x16\x17\x11\x129\x00\xb0\x00EX\xb0\x01/\x1b\xb1\x01\x18>Y\xb0\x00EX\xb0\x13/\x1b\xb1\x13\x18>Y\xb0\x00EX\xb0\r/\x1b\xb1\r\x10>Y\xb0\x01\x10\xb0\x00а\x00/\xb0\x01\x10\xb2\x03\x01\n+X!\xd8\x1b\xf4Y\xb0\r\x10\xb2\b\x01\n+X!\xd8\x1b\xf4Y\xb0\x03\x10\xb0\x11а\x12\xd001\x01\x113\x15#\x11\x14\x16327\x15\x06#\"&5\x11#53\x11\x01\x87\xca\xca6A 8IE|~\xc5\xc5\x05@\xfe\xfa\x8f\xfdaAA\f\x96\x14\x96\x8a\x02\x9f\x8f\x01\x06\x00\x01\x00\x88\xff\xec\x03\xdc\x04:\x00\x10\x00S\xb2\n\x11\x12\x11\x129\x00\xb0\x00EX\xb0\x06/\x1b\xb1\x06\x18>Y\xb0\x00EX\xb0\r/\x1b\xb1\r\x18>Y\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x10>Y\xb0\x00EX\xb0\x10/\x1b\xb1\x10\x10>Y\xb2\x00\r\x02\x11\x129\xb0\x02\x10\xb2\n\x01\n+X!\xd8\x1b\xf4Y01%\x06#\"&'\x113\x11\x14327\x113\x11#\x03(lѭ\xb5\x01\xb9\xc8\xd4F\xb9\xb0k\u007f\xc9\xc5\x02\xc0\xfdE\xf6\x9e\x03\x13\xfb\xc6\x00\x00\x01\x00!\x00\x00\x03\xba\x04:\x00\x06\x008\xb2\x00\a\b\x11\x129\x00\xb0\x00EX\xb0\x01/\x1b\xb1\x01\x18>Y\xb0\x00EX\xb0\x05/\x1b\xb1\x05\x18>Y\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x10>Y\xb2\x00\x05\x03\x11\x12901%\x013\x01#\x013\x01\xf1\x01\f\xbd\xfe|\x8d\xfex\xbd\xfb\x03?\xfb\xc6\x04:\x00\x00\x01\x00+\x00\x00\x05\xd3\x04:\x00\f\x00`\xb2\x05\r\x0e\x11\x129\x00\xb0\x00EX\xb0\x01/\x1b\xb1\x01\x18>Y\xb0\x00EX\xb0\b/\x1b\xb1\b\x18>Y\xb0\x00EX\xb0\v/\x1b\xb1\v\x18>Y\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x10>Y\xb0\x00EX\xb0\x06/\x1b\xb1\x06\x10>Y\xb2\x00\v\x03\x11\x129\xb2\x05\v\x03\x11\x129\xb2\n\v\x03\x11\x12901%\x133\x01#\x01\x01#\x013\x13\x133\x04Jй\xfeŖ\xfe\xf9\xff\x00\x96\xfeƸ\xd5\xfc\x95\xff\x03;\xfb\xc6\x034\xfc\xcc\x04:\xfc\xd6\x03*\x00\x01\x00)\x00\x00\x03\xca\x04:\x00\v\x00S\x00\xb0\x00EX\xb0\x01/\x1b\xb1\x01\x18>Y\xb0\x00EX\xb0\n/\x1b\xb1\n\x18>Y\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x10>Y\xb0\x00EX\xb0\a/\x1b\xb1\a\x10>Y\xb2\x00\n\x04\x11\x129\xb2\x06\n\x04\x11\x129\xb2\x03\x00\x06\x11\x129\xb2\t\x06\x00\x11\x12901\x01\x133\x01\x01#\x03\x03#\x01\x013\x01\xf7\xf0\xd8\xfe\x9e\x01m\xd6\xfa\xfa\xd7\x01m\xfe\x9e\xd6\x02\xaf\x01\x8b\xfd\xe9\xfd\xdd\x01\x95\xfek\x02#\x02\x17\x00\x01\x00\x16\xfeK\x03\xb0\x04:\x00\x0f\x00I\xb2\x00\x10\x11\x11\x129\x00\xb0\x00EX\xb0\x01/\x1b\xb1\x01\x18>Y\xb0\x00EX\xb0\x0e/\x1b\xb1\x0e\x18>Y\xb0\x00EX\xb0\x05/\x1b\xb1\x05\x12>Y\xb2\x00\x0e\x05\x11\x129\xb2\t\x01\n+X!\xd8\x1b\xf4Y\xb0\x00\x10\xb0\r\xd001\x01\x133\x01\x02#''5\x172677\x013\x01\xee\xfc\xc6\xfeMe\xdc#E2^i\")\xfe~\xca\x01\x0f\x03+\xfb\x1f\xfe\xf2\x03\r\x96\x04Len\x04.\x00\x01\x00X\x00\x00\x03\xb3\x04:\x00\t\x00D\x00\xb0\x00EX\xb0\a/\x1b\xb1\a\x18>Y\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x10>Y\xb2\x00\x01\n+X!\xd8\x1b\xf4Y\xb2\x04\x00\x02\x11\x129\xb0\a\x10\xb2\x05\x01\n+X!\xd8\x1b\xf4Y\xb2\t\x05\a\x11\x12901%!\x15!5\x01!5!\x15\x01:\x02y\xfc\xa5\x02U\xfd\xb4\x034\x97\x97\x88\x03\x19\x99\x83\x00\x00\x01\x00@\xfe\x92\x02\x9e\x06=\x00\x18\x001\xb2\x13\x19\x1a\x11\x129\x00\xb0\r/\xb0\x00/\xb2\a\r\x00\x11\x129\xb0\a/\xb2\x1f\a\x01]\xb2\x06\x03\n+X!\xd8\x1b\xf4Y\xb2\x13\x06\a\x11\x12901\x01&&554#5255667\x17\x06\x11\x15\x14\a\x16\x15\x15\x12\x17\x02x\xb1\xb3\xd4\xd4\x02\xaf\xb3&ѧ\xa7\x03\xce\xfe\x922\xe5\xbc\xc7\xf3\x91\xf2з\xe13sC\xfe\xe6\xca\xe3YZ\xe5\xce\xfe\xedB\x00\x00\x01\x00\xaf\xfe\xf2\x01D\x05\xb0\x00\x03\x00\x13\x00\xb0\x00/\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x1c>Y01\x01#\x113\x01D\x95\x95\xfe\xf2\x06\xbe\x00\x00\x01\x00\x13\xfe\x92\x02r\x06=\x00\x18\x001\xb2\x05\x19\x1a\x11\x129\x00\xb0\v/\xb0\x18/\xb2\x11\v\x18\x11\x129\xb0\x11/\xb2\x1f\x11\x01]\xb2\x12\x03\n+X!\xd8\x1b\xf4Y\xb2\x05\x12\x11\x11\x12901\x176\x13547&55\x10'7\x16\x16\x17\x15\x143\x15\"\x15\x15\x14\x06\a\x13\xcb\a\xb5\xb5\xd1&\xb1\xb2\x01\xd4Ե\xaf\xfbA\x01\n\xdc\xe7TR\xe9\xcb\x01\x1aCs2\xe1\xb9\xd2\xef\x91\xf3ʼ\xe22\x00\x00\x01\x00\x83\x01\x92\x04\xef\x03\"\x00\x17\x00B\xb2\x11\x18\x19\x11\x129\x00\xb0\x00EX\xb0\x0f/\x1b\xb1\x0f\x16>Y\xb0\x00а\x0f\x10\xb0\x14а\x14/\xb2\x03\x01\n+X!\xd8\x1b\xf4Y\xb0\x0f\x10\xb2\b\x01\n+X!\xd8\x1b\xf4Y\xb0\x03\x10\xb0\v\xd001\x01\x14\x06#\".\x02#\"\x06\x15\a4632\x16\x16\x17\x17265\x04ﻉH\x80\xa9J*NT\xa1\xb8\x8bL\x8c\xb0@\x1dL_\x03\t\x9e\xd95\x94$k^\x02\xa0\xce@\xa1\n\x02t_\x00\x02\x00\x8b\xfe\x98\x01f\x04M\x00\x03\x00\f\x002\xb2\x06\r\x0e\x11\x129\xb0\x06\x10\xb0\x00\xd0\x00\xb0\x02/\xb0\x00EX\xb0\v/\x1b\xb1\v\x18>Y\xb2\x06\x05\n+X!\xd8\x1b\xf4Y\xb2\x01\x02\x06\x11\x12901\x133\x13#\x13\x14\x06\"&462\x16\xaa\xa8\r\xc2\xc97l88l7\x02\xac\xfb\xec\x05L->>Z<<\x00\x01\x00i\xff\v\x03\xf9\x05&\x00!\x00R\xb2\x00\"#\x11\x129\x00\xb0\x00EX\xb0\x14/\x1b\xb1\x14\x18>Y\xb0\x00EX\xb0\n/\x1b\xb1\n\x10>Y\xb0\aв\x00\x01\n+X!\xd8\x1b\xf4Y\xb0\n\x10\xb0\x03а\x14\x10\xb0\x11а\x14\x10\xb0\x18а\x14\x10\xb2\x1b\x01\n+X!\xd8\x1b\xf4Y01%2673\x06\x06\a\x15#5&\x02554\x12753\x15\x16\x16\x17#&&#\"\x06\x15\x15\x14\x16\x02Jd\x94\b\xaf\x06Ɛ\xb9\xb3\xc8ʱ\xb9\x96\xc0\x06\xaf\b\x8fi\x8d\x9b\x9b\x83yY~\xc9\x1a\xe9\xea\"\x01\x1c\xdc#\xd4\x01\x1d!\xe2\xdf\x17Ԗi\x87\xcb\xc0#\xbb\xca\x00\x01\x00[\x00\x00\x04h\x05\xc4\x00!\x00|\xb2\x1c\"#\x11\x129\x00\xb0\x00EX\xb0\x14/\x1b\xb1\x14\x1c>Y\xb0\x00EX\xb0\x05/\x1b\xb1\x05\x10>Y\xb2\x1f\x14\x05\x11\x129\xb0\x1f/\xb2_\x1f\x01r\xb2\x8f\x1f\x01q\xb2\xbf\x1f\x01]\xb2\x00\x01\n+X!\xd8\x1b\xf4Y\xb0\x05\x10\xb2\x03\x01\n+X!\xd8\x1b\xf4Y\xb0\aа\bа\x00\x10\xb0\rа\x1f\x10\xb0\x0fа\x14\x10\xb0\x18а\x14\x10\xb2\x1b\x01\n+X!\xd8\x1b\xf4Y01\x01\x17\x14\a!\a!536675'#53\x034632\x16\x15#4&#\"\x06\x15\x13!\x15\x01\xc1\b>\x02\xdd\x01\xfb\xf8M(2\x02\b\xa5\xa0\t\xf5Ⱦ\u07bf\u007foi\x82\t\x01?\x02nܚ[\x9d\x9d\t\x83`\bݝ\x01\x04\xc7\xeeԱk|\x9a}\xfe\xfc\x9d\x00\x00\x02\x00i\xff\xe5\x05[\x04\xf1\x00\x1b\x00*\x00?\xb2\x02+,\x11\x129\xb0\x02\x10\xb0'\xd0\x00\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x10>Y\xb0\x10а\x10/\xb0\x02\x10\xb2\x1f\x01\n+X!\xd8\x1b\xf4Y\xb0\x10\x10\xb2'\x01\n+X!\xd8\x1b\xf4Y01%\x06#\"'\a'7&547'7\x17632\x177\x17\a\x16\x15\x14\a\x17\a\x01\x14\x16\x1626654&&#\"\x06\x06\x04O\x9f\xd1ϟ\x86\x82\x8bhp\x93\x82\x93\x9e\xc3ğ\x95\x84\x97nf\x8f\x84\xfc`s\xc4\xe2\xc4qq\xc5pq\xc4sp\x84\x82\x88\x87\x8d\x9c\xcaΣ\x97\x88\x96xy\x98\x89\x9a\xa3\xcbğ\x90\x88\x02{{\xd4z{\xd3{z\xd3yx\xd4\x00\x00\x01\x00\x1f\x00\x00\x04\xad\x05\xb0\x00\x16\x00k\x00\xb0\x00EX\xb0\x16/\x1b\xb1\x16\x1c>Y\xb0\x00EX\xb0\x01/\x1b\xb1\x01\x1c>Y\xb0\x00EX\xb0\f/\x1b\xb1\f\x10>Y\xb2\x0f\x13\x03+\xb2\x00\f\x16\x11\x129\xb4\x0f\x13\x1f\x13\x02]\xb0\x13\x10\xb0\x03а\x13\x10\xb2\x12\x02\n+X!\xd8\x1b\xf4Y\xb0\x06а\x0f\x10\xb0\aа\x0f\x10\xb2\x0e\x02\n+X!\xd8\x1b\xf4Y\xb0\n\xd001\x01\x013\x01!\x15!\x15!\x15!\x11#\x11!5!5!5!\x013\x02f\x01l\xdb\xfe^\x018\xfe\x80\x01\x80\xfe\x80\xc1\xfe\x86\x01z\xfe\x86\x019\xfe^\xdc\x03\x0e\x02\xa2\xfd0}\xa5|\xfe\xbe\x01B|\xa5}\x02\xd0\x00\x00\x02\x00\x93\xfe\xf2\x01M\x05\xb0\x00\x03\x00\a\x00\x18\x00\xb0\x00/\xb0\x00EX\xb0\x06/\x1b\xb1\x06\x1c>Y\xb2\x05\x01\x03+01\x13\x113\x11\x11#\x113\x93\xba\xba\xba\xfe\xf2\x03\x17\xfc\xe9\x03\xc8\x02\xf6\x00\x02\x00Z\xfe\x11\x04y\x05\xc4\x004\x00D\x00\x80\xb2#EF\x11\x129\xb0#\x10\xb05\xd0\x00\xb0\b/\xb0\x00EX\xb0#/\x1b\xb1#\x1c>Y\xb2\x16\b#\x11\x129\xb0\x16\x10\xb2?\x01\n+X!\xd8\x1b\xf4Y\xb2\x02\x16?\x11\x129\xb0\b\x10\xb0\x0eа\b\x10\xb2\x11\x01\n+X!\xd8\x1b\xf4Y\xb20#\b\x11\x129\xb00\x10\xb27\x01\n+X!\xd8\x1b\xf4Y\xb2\x1d70\x11\x129\xb0#\x10\xb0'а#\x10\xb2*\x01\n+X!\xd8\x1b\xf4Y01\x01\x14\a\x16\x16\x15\x14\x04#\"&'&57\x14\x1632654&'.\x02547&&54$32\x04\x15#4&#\"\x06\x15\x14\x16\x16\x04\x1e\x02%&'\x06\x06\x15\x14\x16\x16\x04\x176654&\x04y\xbaEH\xfe\xfc\xe4p\xc9F\x8b\xba\xb4\x9c\x88\xa6\x8eѶ\xc0]\xb6BG\x01\v\xde\xe8\x01\x04\xb9\xa8\x8b\x8e\xa18\x87\x01\x1f\xa9q:\xfd\xe1ZKPK6\x85\x01\x1c,NT\x8b\x01\xaf\xbdU1\x88d\xa8\xc789q\xcd\x02\x82\x97u`Yi>0o\x9bo\xbaX1\x88d\xa6\xc8\xe2\xcd}\x9bsbEPAPHa\x81\xab\x18\x1b\x13eEFPBR\x11\x14eEXm\x00\x00\x02\x00f\x04\xf0\x02\xef\x05\xc5\x00\b\x00\x11\x00\x1d\x00\xb0\a/\xb2\x02\x05\n+X!\xd8\x1b\xf4Y\xb0\vа\a\x10\xb0\x10а\x10/01\x13462\x16\x14\x06\"&%462\x16\x14\x06\"&f7l88l7\x01\xae7l88l7\x05[-==Z<<+->>Z<<\x00\x00\x03\x00[\xff\xeb\x05\xe6\x05\xc4\x00\x1b\x00*\x009\x00\x95\xb2':;\x11\x129\xb0'\x10\xb0\x03а'\x10\xb06\xd0\x00\xb0\x00EX\xb0./\x1b\xb1.\x1c>Y\xb0\x00EX\xb06/\x1b\xb16\x10>Y\xb2\x036.\x11\x129\xb0\x03/\xb4\x0f\x03\x1f\x03\x02]\xb2\n.6\x11\x129\xb0\n/\xb4\x00\n\x10\n\x02]\xb2\x0e\n\x03\x11\x129\xb2\x11\x02\n+X!\xd8\x1b\xf4Y\xb0\x03\x10\xb2\x18\x02\n+X!\xd8\x1b\xf4Y\xb2\x1b\x03\n\x11\x129\xb06\x10\xb2 \x04\n+X!\xd8\x1b\xf4Y\xb0.\x10\xb2'\x04\n+X!\xd8\x1b\xf4Y01\x01\x14\x06#\"&554632\x16\x15#4&#\"\x06\x15\x15\x14\x163265%\x14\x12\x04 $\x1254\x02$#\"\x04\x02\a4\x12$ \x04\x12\x15\x14\x02\x04#\"$\x02\x04_\xad\x9e\x9d\xbd\xbf\x9b\xa0\xac\x92_[^ll^\\]\xfd\x01\xa0\x01\x13\x01@\x01\x12\xa0\x9e\xfe\xed\xa1\xa0\xfe\xec\x9fs\xbb\x01K\x01\x80\x01J\xbb\xb4\xfe\xb5\xc6\xc5\xfe\xb5\xb6\x02U\x99\xa1Ӷn\xb0Ӥ\x95cU\x8a{qx\x8aTe\x84\xac\xfeۦ\xa6\x01%\xac\xaa\x01\"\xa7\xa5\xfeܪ\xca\x01Z\xc7\xc7\xfe\xa6\xca\xc5\xfe\xa8\xd1\xcf\x01X\x00\x00\x02\x00\x93\x02\xb3\x03\x0f\x05\xc4\x00\x1b\x00%\x00l\xb2\x0e&'\x11\x129\xb0\x0e\x10\xb0\x1d\xd0\x00\xb0\x00EX\xb0\x15/\x1b\xb1\x15\x1c>Y\xb2\x04&\x15\x11\x129\xb0\x04/\xb0\x00в\x02\x04\x15\x11\x129\xb2\v\x04\x15\x11\x129\xb0\v/\xb0\x15\x10\xb2\x0e\x03\n+X!\xd8\x1b\xf4Y\xb2\x11\v\x15\x11\x129\xb0\x04\x10\xb2\x1c\x03\n+X!\xd8\x1b\xf4Y\xb0\v\x10\xb2 \x04\n+X!\xd8\x1b\xf4Y01\x01&'\x06#\"&5463354#\"\x06\x15'4632\x16\x15\x11\x14\x17%2675#\x06\x06\x15\x14\x02j\f\x06L\x80w\x82\xa7\xacl|EO\xa1\xac\x89\x85\x9a\x1a\xfe\xa4+X\x1cpSY\x02\xc1\"&V|gox4\x8763\fg\x82\x8f\x86\xfe\xc4aQ{(\x1b\x8e\x01?3^\xff\xff\x00f\x00\x97\x03d\x03\xb3\x00&\x00\x9a\xfa\xfe\x00\a\x00\x9a\x01D\xff\xfe\x00\x01\x00\u007f\x01w\x03\xbe\x03 \x00\x05\x00\x1a\x00\xb0\x04/\xb0\x01а\x01/\xb0\x04\x10\xb2\x02\x01\n+X!\xd8\x1b\xf4Y01\x01#\x11!5!\x03\xbe\xba\xfd{\x03?\x01w\x01\b\xa1\x00\x04\x00Z\xff\xeb\x05\xe5\x05\xc4\x00\x0e\x00\x1e\x004\x00=\x00\xa9\xb26>?\x11\x129\xb06\x10\xb0\vа6\x10\xb0\x13а6\x10\xb0#\xd0\x00\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x1c>Y\xb0\x00EX\xb0\v/\x1b\xb1\v\x10>Y\xb2\x13\x04\n+X!\xd8\x1b\xf4Y\xb0\x03\x10\xb2\x1b\x04\n+X!\xd8\x1b\xf4Y\xb2 \v\x03\x11\x129\xb0 /\xb2\"\x03\v\x11\x129\xb0\"/\xb4\x00\"\x10\"\x02]\xb25 \"\x11\x129\xb05/\xb2\xbf5\x01]\xb4\x005\x105\x02]\xb2\x1f\x02\n+X!\xd8\x1b\xf4Y\xb2(\x1f5\x11\x129\xb0 \x10\xb0/а//\xb0\"\x10\xb2=\x02\n+X!\xd8\x1b\xf4Y01\x134\x12$ \x04\x12\x15\x14\x02\x04#\"$\x027\x14\x12\x0432$\x1254\x02$#\"\x04\x02\x05\x11#\x11!2\x16\x15\x14\a\x16\x17\x15\x14\x17\x15#&4'&''36654&##Z\xbb\x01K\x01\x80\x01J\xbb\xb4\xfe\xb5\xc6\xc5\xfe\xb5\xb6s\xa0\x01\x13\xa0\xa1\x01\x14\x9d\x9d\xfe졠\xfe\xec\x9f\x01\xc0\x8d\x01\x14\x99\xa9\x80z\x01\x11\x91\x0e\x03\x10s\xb0\x9cHXNd\x8a\x02\xd9\xca\x01Z\xc7\xc7\xfe\xa6\xca\xc5\xfe\xa8\xd1\xcf\x01XǬ\xfeۦ\xa9\x01\"\xac\xab\x01!\xa7\xa5\xfe\xdc\xf5\xfe\xae\x03Q\x83}{A2\x9a=V&\x10$\xb9\x11`\x04\x80\x02B6I=\x00\x00\x01\x00x\x05!\x03B\x05\xb0\x00\x03\x00\x11\x00\xb0\x01/\xb2\x02\x03\n+X!\xd8\x1b\xf4Y01\x01!5!\x03B\xfd6\x02\xca\x05!\x8f\x00\x02\x00\x82\x03\xc0\x02|\x05\xc4\x00\v\x00\x16\x00/\x00\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x1c>Y\xb0\fа\f/\xb2\t\x02\n+X!\xd8\x1b\xf4Y\xb0\x03\x10\xb2\x12\x02\n+X!\xd8\x1b\xf4Y01\x134632\x16\x15\x14\x06#\"&\x172654&#\"\x06\x14\x16\x82\x95jh\x93\x93hi\x96\xff6JJ67KK\x04\xc0h\x9c\x9bij\x96\x96\x16G9:KOlJ\x00\x02\x00a\x00\x00\x03\xf5\x04\xf3\x00\v\x00\x0f\x00F\x00\xb0\t/\xb0\x00EX\xb0\r/\x1b\xb1\r\x10>Y\xb0\t\x10\xb0\x00а\t\x10\xb2\x06\x01\n+X!\xd8\x1b\xf4Y\xb0\x03а\r\x10\xb2\x0e\x01\n+X!\xd8\x1b\xf4Y\xb2\x05\x0e\x06\x11\x129\xb4\v\x05\x1b\x05\x02]01\x01!\x15!\x11#\x11!5!\x113\x01!5!\x02\x89\x01l\xfe\x94\xa7\xfe\u007f\x01\x81\xa7\x01A\xfc\xbd\x03C\x03V\x97\xfeb\x01\x9e\x97\x01\x9d\xfb\r\x98\x00\x00\x01\x00B\x02\x9b\x02\xab\x05\xbb\x00\x16\x00T\xb2\b\x17\x18\x11\x129\x00\xb0\x00EX\xb0\x0e/\x1b\xb1\x0e\x1c>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x14>Y\xb2\x16\x02\n+X!\xd8\x1b\xf4Y\xb0\x02в\x03\x0e\x16\x11\x129\xb0\x0e\x10\xb2\b\x02\n+X!\xd8\x1b\xf4Y\xb0\x0e\x10\xb0\vв\x14\x16\x0e\x11\x12901\x01!5\x01654&#\"\x06\x15#46 \x16\x15\x14\x0f\x02!\x02\xab\xfd\xa9\x01,m@\x02\x8f\x02\x9a\x05\xba\x00&\x00\x89\xb2 '(\x11\x129\x00\xb0\x00EX\xb0\x0e/\x1b\xb1\x0e\x1c>Y\xb0\x00EX\xb0\x19/\x1b\xb1\x19\x14>Y\xb2\x00\x19\x0e\x11\x129\xb0\x00/\xb6o\x00\u007f\x00\x8f\x00\x03]\xb2?\x00\x01q\xb6\x0f\x00\x1f\x00/\x00\x03]\xb2_\x00\x01r\xb0\x0e\x10\xb2\a\x02\n+X!\xd8\x1b\xf4Y\xb2\n\x0e\x19\x11\x129\xb0\x00\x10\xb2&\x04\n+X!\xd8\x1b\xf4Y\xb2\x14&\x00\x11\x129\xb2\x1d\x19\x0e\x11\x129\xb0\x19\x10\xb2 \x02\n+X!\xd8\x1b\xf4Y01\x0132654&#\"\x06\x15#4632\x16\x15\x14\x06\a\x16\x15\x14\x06#\"&53\x14\x1632654'#\x01\tTJH?F9K\x9d\xa3|\x89\x9cFB\x95\xaa\x88\x84\xa6\x9eOCFI\x9cX\x04e=0-:3)b{yh7[\x19)\x8fj}~k-<<3q\x02\x00\x00\x01\x00{\x04\xd8\x02\x1c\x05\xfe\x00\x03\x00#\x00\xb0\x02/\xb2\x0f\x02\x01]\xb0\x00а\x00/\xb4\x0f\x00\x1f\x00\x02]\xb0\x02\x10\xb0\x03\xd0\x19\xb0\x03/\x1801\x013\x01#\x01<\xe0\xfe\xf4\x95\x05\xfe\xfe\xda\x00\x00\x01\x00\x9a\xfe`\x03\xee\x04:\x00\x12\x00P\xb2\r\x13\x14\x11\x129\x00\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x18>Y\xb0\x00EX\xb0\a/\x1b\xb1\a\x18>Y\xb0\x00EX\xb0\x10/\x1b\xb1\x10\x12>Y\xb0\x00EX\xb0\r/\x1b\xb1\r\x10>Y\xb2\x04\x01\n+X!\xd8\x1b\xf4Y\xb2\v\a\r\x11\x12901\x01\x11\x16\x16327\x113\x11#'\x06#\"'\x11#\x11\x01S\x01gt\xc7>\xba\xa7\t]\xaa\x93Q\xb9\x04:\xfd\x87\xa3\x9c\x98\x03 \xfb\xc6s\x87I\xfe+\x05\xda\x00\x01\x00C\x00\x00\x03@\x05\xb0\x00\n\x00+\xb2\x02\v\f\x11\x129\x00\xb0\x00EX\xb0\b/\x1b\xb1\b\x1c>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x10>Y\xb2\x01\x00\b\x11\x12901!\x11#\"$54$3!\x11\x02\x86T\xe6\xfe\xf7\x01\n\xe6\x01\r\x02\b\xfe\xd6\xd5\xff\xfaP\x00\x00\x01\x00\x93\x02k\x01y\x03I\x00\t\x00\x16\xb2\x03\n\v\x11\x129\x00\xb0\x02/\xb1\b\n+X\xd8\x1b\xdcY01\x13462\x16\x15\x14\x06\"&\x939r;;r9\x02\xd90@@0/??\x00\x01\x00t\xfeM\x01\xaa\x00\x00\x00\x0e\x00A\xb2\x05\x0f\x10\x11\x129\x00\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x10>Y\xb0\x00EX\xb0\x06/\x1b\xb1\x06\x12>Y\xb4\x13\x06#\x06\x02]\xb2\x01\x06\x00\x11\x129\xb1\a\n+X\xd8\x1b\xdcY\xb0\x01\x10\xb0\r\xd001!\a\x16\x15\x14\x06#'2654&'7\x01\x1d\f\x99\xa0\x8f\aOW@b 4\x1b\x92aqk4/,*\t\x86\x00\x01\x00z\x02\xa2\x01\xef\x05\xb7\x00\x06\x00@\xb2\x01\a\b\x11\x129\x00\xb0\x00EX\xb0\x05/\x1b\xb1\x05\x1c>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x14>Y\xb2\x04\x00\x05\x11\x129\xb0\x04/\xb2\x03\x02\n+X!\xd8\x1b\xf4Y\xb2\x02\x03\x05\x11\x12901\x01#\x11\a5%3\x01\xef\x9d\xd8\x01c\x12\x02\xa2\x02Y9\x80u\x00\x00\x02\x00z\x02\xb2\x03'\x05\xc4\x00\f\x00\x1a\x00@\xb2\x03\x1b\x1c\x11\x129\xb0\x03\x10\xb0\x10\xd0\x00\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x1c>Y\xb2\n\x1b\x03\x11\x129\xb0\n/\xb2\x10\x03\n+X!\xd8\x1b\xf4Y\xb0\x03\x10\xb2\x17\x03\n+X!\xd8\x1b\xf4Y01\x134632\x16\x15\x15\x14\x06 &5\x17\x14\x16326554&#\"\x06\az\xbc\x9a\x9b\xbc\xbb\xfe̾\xa3aTS_aSQ`\x02\x04c\x9e\xc3\xc1\xa6J\x9f\xc2¥\x06drseNcrna\x00\xff\xff\x00f\x00\x98\x03x\x03\xb5\x00&\x00\x9b\r\x00\x00\a\x00\x9b\x01j\x00\x00\xff\xff\x00U\x00\x00\x05\x91\x05\xad\x00'\x00\xa2\xff\xdb\x02\x98\x00'\x00\x9c\x01\x18\x00\b\x01\a\x00\xa5\x02\xd6\x00\x00\x00\x10\x00\xb0\x00EX\xb0\x05/\x1b\xb1\x05\x1c>Y01\xff\xff\x00P\x00\x00\x05\xc9\x05\xad\x00'\x00\x9c\x00\xec\x00\b\x00'\x00\xa2\xff\xd6\x02\x98\x01\a\x00\xa3\x03\x1e\x00\x00\x00\x10\x00\xb0\x00EX\xb0\t/\x1b\xb1\t\x1c>Y01\xff\xff\x00o\x00\x00\x05\xed\x05\xbb\x00'\x00\x9c\x01\x97\x00\b\x00'\x00\xa5\x032\x00\x00\x01\a\x00\xa4\x001\x02\x9b\x00\x10\x00\xb0\x00EX\xb0!/\x1b\xb1!\x1c>Y01\x00\x02\x00D\xfe\u007f\x03x\x04M\x00\x18\x00\"\x00W\xb2\t#$\x11\x129\xb0\t\x10\xb0\x1c\xd0\x00\xb0\x10/\xb0\x00EX\xb0!/\x1b\xb1!\x18>Y\xb2\x00\x10!\x11\x129\xb2\x03\x10\x00\x11\x129\xb0\x10\x10\xb2\t\x01\n+X!\xd8\x1b\xf4Y\xb0\x10\x10\xb0\fв\x15\x00\x10\x11\x129\xb0!\x10\xb2\x1b\x05\n+X!\xd8\x1b\xf4Y01\x01\x0e\x03\a\a\x14\x1632653\x06\x06#\"&547765\x13\x14\x06\"&5462\x16\x02L\x01)`\xb8\v\x02tmd}\xb9\x02\xe1\xb7\xc4֠mB\xc17l88l7\x02\xa8j\u007fv\xc1c%msq[\xa1\xccɳ\xad\xafqN\x92\x01=->>-,<<\x00\x02\xff\xf2\x00\x00\aW\x05\xb0\x00\x0f\x00\x12\x00w\x00\xb0\x00EX\xb0\x06/\x1b\xb1\x06\x1c>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x10>Y\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x10>Y\xb2\x11\x06\x00\x11\x129\xb0\x11/\xb2\x02\x01\n+X!\xd8\x1b\xf4Y\xb0\x06\x10\xb2\b\x01\n+X!\xd8\x1b\xf4Y\xb2\v\x00\x06\x11\x129\xb0\v/\xb2\f\x01\n+X!\xd8\x1b\xf4Y\xb0\x00\x10\xb2\x0e\x01\n+X!\xd8\x1b\xf4Y\xb2\x12\x06\x00\x11\x12901!!\x03!\x03#\x01!\x15!\x13!\x15!\x13!\x01!\x03\aW\xfc\x8d\x0f\xfd\xcc\xcd\xe2\x03p\x03\xb7\xfdM\x14\x02N\xfd\xb8\x16\x02\xc1\xfa\xaf\x01\xc8\x1f\x01a\xfe\x9f\x05\xb0\x98\xfe)\x97\xfd\xed\x01x\x02\xdd\x00\x01\x00Y\x00\xce\x03\xdd\x04c\x00\v\x008\x00\xb0\x03/\xb2\t\f\x03\x11\x129\xb0\t/\xb2\n\t\x03\x11\x129\xb2\x04\x03\t\x11\x129\xb2\x01\n\x04\x11\x129\xb0\x03\x10\xb0\x05в\a\x04\n\x11\x129\xb0\t\x10\xb0\v\xd001\x13\x01\x017\x01\x01\x17\x01\x01\a\x01\x01Y\x01J\xfe\xb8w\x01I\x01Iw\xfe\xb8\x01Jw\xfe\xb5\xfe\xb5\x01I\x01P\x01O{\xfe\xb1\x01O{\xfe\xb1\xfe\xb0{\x01Q\xfe\xaf\x00\x00\x03\x00v\xff\xa3\x05\x1d\x05\xec\x00\x17\x00 \x00)\x00f\xb2\x04*+\x11\x129\xb0\x04\x10\xb0\x1dа\x04\x10\xb0&\xd0\x00\xb0\x00EX\xb0\x10/\x1b\xb1\x10\x1c>Y\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x10>Y\xb2\x1a\x10\x04\x11\x129\xb2#\x10\x04\x11\x129\xb0#\x10\xb0\x1bа\x10\x10\xb2\x1d\x01\n+X!\xd8\x1b\xf4Y\xb0\x1a\x10\xb0$а\x04\x10\xb2&\x01\n+X!\xd8\x1b\xf4Y01\x01\x14\x02\x04#\"'\a#7&\x1154\x12$32\x1773\a\x16\x13\x05\x14\x17\x01&#\"\x02\a\x054'\x01\x1632\x127\x05\t\x90\xfe\xf8\xb0\xab\x83a\x8e\x90\xbe\x92\x01\v\xac֔g\x8d\x9f\x89\x02\xfc,b\x024f\xa6\xb6\xd1\x03\x03\x158\xfd\xdb[y\xba\xcc\x03\x02\xa9\xd6\xfe\xc1\xa8R\x9b\xe7\xc0\x01hS\xd2\x01B\xab}\xa5\xff\xbb\xfe\xdac\xf4\x8d\x03\x88o\xfe\xeb\xf6\r\xb6\x83\xfc\x8f@\x01\x0f\xfd\x00\x02\x00\xa6\x00\x00\x04]\x05\xb0\x00\r\x00\x16\x00W\xb2\t\x17\x18\x11\x129\xb0\t\x10\xb0\x10\xd0\x00\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x1c>Y\xb0\x00EX\xb0\v/\x1b\xb1\v\x10>Y\xb2\x01\x00\v\x11\x129\xb0\x01/\xb2\x10\x00\v\x11\x129\xb0\x10/\xb2\t\x01\n+X!\xd8\x1b\xf4Y\xb0\x01\x10\xb2\x0e\x01\n+X!\xd8\x1b\xf4Y01\x01\x11!2\x16\x16\x15\x14\x04#!\x11#\x11\x13\x11!2654&'\x01`\x01\x17\x93\xdcw\xfe\xf8\xe3\xfe\ueeba\x01\x15\x8e\xa0\xa0\x88\x05\xb0\xfe\xdbi\xc2~\xc2\xe7\xfe\xc7\x05\xb0\xfeC\xfdޗx{\x97\x01\x00\x01\x00\x8b\xff\xec\x04j\x06\x12\x00*\x00i\xb2!+,\x11\x129\x00\xb0\x00EX\xb0\x05/\x1b\xb1\x05\x1e>Y\xb0\x00EX\xb0\x13/\x1b\xb1\x13\x10>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x10>Y\xb2\n\x13\x05\x11\x129\xb2\x0e\x05\x13\x11\x129\xb0\x13\x10\xb2\x1a\x01\n+X!\xd8\x1b\xf4Y\xb2 \x13\x05\x11\x129\xb2#\x05\x13\x11\x129\xb0\x05\x10\xb2(\x01\n+X!\xd8\x1b\xf4Y01!#\x114632\x16\x15\x14\x06\x15\x14\x1e\x02\x15\x14\x06#\"&'7\x16\x1632654.\x0254654&#\"\x11\x01D\xb9Ϻ\xb4ŀK\xbcV˶Q\xb5&+1\x875kqJ\xbdW\x8bhX\xda\x04W\xd0볟}\xcbE3_\x90\x88L\x9f\xb2,\x1c\x9b ,^R4`\x93\x8aQY\xcfT^k\xfe\xdb\x00\x03\x00N\xff\xec\x06|\x04N\x00*\x005\x00=\x00Ʋ\x02>?\x11\x129\xb0\x02\x10\xb0.а\x02\x10\xb09\xd0\x00\xb0\x00EX\xb0\x17/\x1b\xb1\x17\x18>Y\xb0\x00EX\xb0\x1d/\x1b\xb1\x1d\x18>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x10>Y\xb0\x00EX\xb0\x05/\x1b\xb1\x05\x10>Y\xb2\x02\x1d\x00\x11\x129\xb2\f\x05\x17\x11\x129\xb0\f/\xb4\xbf\f\xcf\f\x02]\xb0\x17\x10\xb2\x10\x01\n+X!\xd8\x1b\xf4Y\xb2\x13\f\x17\x11\x129\xb2\x1a\x1d\x00\x11\x129\xb2:\x1d\x00\x11\x129\xb0:/\xb4\xbf:\xcf:\x02]\xb2!\x01\n+X!\xd8\x1b\xf4Y\xb0\x00\x10\xb2%\x01\n+X!\xd8\x1b\xf4Y\xb2(\x1d\x00\x11\x129\xb0+а\f\x10\xb2/\x01\n+X!\xd8\x1b\xf4Y\xb0\x10\x10\xb06\xd001\x05 '\x06\x06#\"&5463354&#\"\x06\x15'4632\x16\x176632\x12\x15\x15!\x16\x163277\x17\x06%2675#\x06\x06\x15\x14\x16\x01\"\x06\a!54&\x04\xee\xfe\xfb\x88A⍧\xbc\xe3\xdd\xdfnhi\x8c\xb8\xf2\xbbs\xb02?\xaei\xd2\xe8\xfd(\a\xae\x95\x94y/@\x9e\xfc\tH\x9e2\xe4u\x8cj\x03Ps\x95\x11\x02\x1a\x86\x14\xb4V^\xad\x97\x9d\xaeUk{nQ\x13\x8f\xb5SSOW\xfe\xff\xe9s\xb0\xbfL\x1f\x88y\x96J6\xed\x02nSM]\x034\xab\x8b\x1f\x84\x93\x00\x00\x02\x00~\xff\xec\x04-\x06,\x00\x1d\x00+\x00T\xb2\a,-\x11\x129\xb0\a\x10\xb0(\xd0\x00\xb0\x00EX\xb0\x19/\x1b\xb1\x19\x1e>Y\xb0\x00EX\xb0\a/\x1b\xb1\a\x10>Y\xb2\x0f\x19\a\x11\x129\xb0\x0f/\xb2\x11\x19\a\x11\x129\xb2\"\x01\n+X!\xd8\x1b\xf4Y\xb0\a\x10\xb2(\x01\n+X!\xd8\x1b\xf4Y01\x01\x12\x11\x15\x14\x06\x06#\"&&546632\x17&'\a'7&'7\x16\x177\x17\x03'&&#\"\x06\x15\x14\x163265\x034\xf9u؆\x87\xdcypρ\xa3y0\x8d\xdaI\xc0\x84\xb79ﯽIh\x02!\x8b\\\x91\xa2\xa7\x80}\x99\x05\x15\xfe\xf8\xfeg]\x9e\xfd\x90\x81\xe0\x86\x93\xe9\x82rÍ\x94c\x83[1\x9f6\x8b\x81d\xfc\xf38=I\xbf\xa7\x8c\xc4\xe2\xb8\x00\x00\x03\x00G\x00\xac\x04-\x04\xba\x00\x03\x00\r\x00\x17\x00N\xb2\a\x18\x19\x11\x129\xb0\a\x10\xb0\x00а\a\x10\xb0\x11\xd0\x00\xb0\x02/\xb2\x01\x01\n+X!\xd8\x1b\xf4Y\xb0\x02\x10\xb1\f\n+X\xd8\x1b\xdcY\xb1\x06\n+X\xd8\x1b\xdcY\xb0\x01\x10\xb1\x10\n+X\xd8\x1b\xdcY\xb1\x16\n+X\xd8\x1b\xdcY01\x01!5!\x01462\x16\x15\x14\x06\"&\x11462\x16\x15\x14\x06\"&\x04-\xfc\x1a\x03\xe6\xfd\xa09r;;r99r;;r9\x02X\xb8\x01:0@@0/>>\xfc\xfe0@@0.??\x00\x00\x03\x00[\xffz\x044\x04\xb8\x00\x15\x00\x1d\x00&\x00c\xb2\x04'(\x11\x129\xb0\x04\x10\xb0\x1bа\x04\x10\xb0#\xd0\x00\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x18>Y\xb0\x00EX\xb0\x0f/\x1b\xb1\x0f\x10>Y\xb2#\x01\n+X!\xd8\x1b\xf4Y\xb2!#\x04\x11\x129\xb0!\x10\xb0\x18а\x04\x10\xb2\x1b\x01\n+X!\xd8\x1b\xf4Y\xb2\x19\x1b\x0f\x11\x129\xb0\x19\x10\xb0 \xd001\x1346632\x1773\a\x16\x11\x14\x06\x06#\"'\a#7&\x13\x14\x17\x01&#\"\x06\x054'\x01\x163265[{\xe1\x8fn^I|f\xc3|\xe0\x90hVJ|d\u0379a\x01W>H\x8a\xa8\x02fW\xfe\xac7B\x8b\xa7\x02'\x9f\xfd\x8b*\x94͚\xfe\xc0\x9e\xfe\x89#\x95˕\x017\xc2o\x02\xb6 ڵ\xb6o\xfdP\x19۹\x00\x02\x00\x95\xfe`\x04'\x06\x00\x00\x0f\x00\x1a\x00d\xb2\x18\x1b\x1c\x11\x129\xb0\x18\x10\xb0\f\xd0\x00\xb0\b/\xb0\x00EX\xb0\f/\x1b\xb1\f\x18>Y\xb0\x00EX\xb0\x06/\x1b\xb1\x06\x12>Y\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x10>Y\xb2\x05\f\x03\x11\x129\xb2\n\f\x03\x11\x129\xb0\f\x10\xb2\x13\x01\n+X!\xd8\x1b\xf4Y\xb0\x03\x10\xb2\x18\x01\n+X!\xd8\x1b\xf4Y01\x01\x14\x02#\"'\x11#\x113\x11632\x12\x11'4&#\"\a\x11\x16326\x04'\xe2\xc1\xc5q\xb9\xb9q\xc2\xc3㹜\x88\xa8TS\xab\x85\x9d\x02\x11\xf7\xfe\xd2}\xfd\xf7\a\xa0\xfdʄ\xfe\xda\xfe\xfa\x04\xb7ԕ\xfd\xfb\x94\xd3\x00\x00\x01\x00\x9b\x00\x00\x01U\x04:\x00\x03\x00\x1d\x00\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x18>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x10>Y01!#\x113\x01U\xba\xba\x04:\x00\x00\x02\x00h\xff\xeb\a\t\x05\xc4\x00\x17\x00#\x00\x91\xb2\x01$%\x11\x129\xb0\x01\x10\xb0\x1a\xd0\x00\xb0\x00EX\xb0\f/\x1b\xb1\f\x1c>Y\xb0\x00EX\xb0\x0e/\x1b\xb1\x0e\x1c>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x10>Y\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x10>Y\xb0\x0e\x10\xb2\x10\x01\n+X!\xd8\x1b\xf4Y\xb2\x13\x00\x0e\x11\x129\xb0\x13/\xb2\x14\x01\n+X!\xd8\x1b\xf4Y\xb0\x00\x10\xb2\x16\x01\n+X!\xd8\x1b\xf4Y\xb0\x03\x10\xb2\x18\x01\n+X!\xd8\x1b\xf4Y\xb0\f\x10\xb2\x1d\x01\n+X!\xd8\x1b\xf4Y01!!\x06#\"&\x02'\x114\x12632\x17!\x15!\x11!\x15!\x11!\x0527\x11&#\"\x06\a\x11\x14\x16\a\t\xfc\xb0\xb2r\xa2\xfe\x8c\x01\x8b\xfe\xa2|\xaa\x03F\xfd-\x02w\xfd\x89\x02\xdd\xfb\x8cqfml\xad\xc2\x02\xc3\x15\x96\x01\x0f\xab\x015\xac\x01\x11\x97\x14\x9e\xfe,\x9d\xfd\xfc\x1b\x0e\x04\x8e\x0f\xe5\xcf\xfe\xc7\xd3\xeb\x00\x00\x03\x00a\xff\xec\a\x00\x04N\x00 \x00,\x004\x00\x96\xb2\x0656\x11\x129\xb0\x06\x10\xb0&а\x06\x10\xb00\xd0\x00\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x18>Y\xb0\x00EX\xb0\n/\x1b\xb1\n\x18>Y\xb0\x00EX\xb0\x17/\x1b\xb1\x17\x10>Y\xb0\x00EX\xb0\x1d/\x1b\xb1\x1d\x10>Y\xb2\a\n\x17\x11\x129\xb21\n\x17\x11\x129\xb01/\xb2\x0e\x01\n+X!\xd8\x1b\xf4Y\xb0\x17\x10\xb2\x12\x01\n+X!\xd8\x1b\xf4Y\xb2\x14\n\x17\x11\x129\xb2\x1a\n\x17\x11\x129\xb0$а\x04\x10\xb2*\x01\n+X!\xd8\x1b\xf4Y\xb0-\xd001\x1346632\x16\x176632\x16\x15\x15!\x16\x16327\x17\x06#\"&'\x06\x06#\"\x005\x17\x14\x1632654&#\"\x06%\"\x06\a!54&ayێ\x89\xc9=A\xc4p\xcf\xea\xfd2\a\xa4\x86\xbcxJ\x89\xf5\x87\xcd?>dž\xdc\xfe\xf8\xb9\xa0\x8b\x89\xa0\xa1\x8a\x87\xa2\x04-c\x96\x16\x02\x0e\x89\x02'\xa0\xfe\x89udfs\xfe\xebt\xaa\xc5l~\x84pdcq\x010\xfe\t\xb7\xd8\xd7ζ\xd9\xd6֣\x8a\x1a}\x96\x00\x00\x01\x00\xa9\x04\xe4\x03\x06\x06\x00\x00\b\x004\x00\xb0\x04/\xb0\aа\a/\xb4\x0f\a\x1f\a\x02]\xb2\x05\x04\a\x11\x129\x19\xb0\x05/\x18\xb0\x01\xd0\x19\xb0\x01/\x18\xb0\x04\x10\xb0\x02в\x03\x04\a\x11\x12901\x01\x15#'\a#5\x133\x03\x06\x99\x96\x95\x99\xf6p\x04\xee\n\xaa\xaa\f\x01\x10\x00\x00\x02\x00y\x04\xb4\x02'\x06P\x00\t\x00\x14\x00*\xb2\x03\x15\x16\x11\x129\xb0\x03\x10\xb0\r\xd0\x00\xb0\x03/\xb0\aа\a/\xb2?\a\x01]\xb0\x03\x10\xb0\rа\a\x10\xb0\x12\xd001\x01\x14\x06#\"&462\x16\x05\x14\x163264&#\"\x06\x02'|[\\{{\xb8{\xfe\xb5C10DC12B\x05\x80Wuv\xaczzV/DBbEF\x00\x00\x01\x00{\x04\xd9\x03>\x05\xe8\x00\x17\x00>\x00\xb0\x03/\xb0\bа\b/\xb4\x0f\b\x1f\b\x02]\xb0\x03\x10\xb0\vа\v/\xb0\b\x10\xb2\x0f\x03\n+X!\xd8\x1b\xf4Y\xb0\x03\x10\xb2\x14\x03\n+X!\xd8\x1b\xf4Y\xb0\x0f\x10\xb0\x17\xd001\x01\x14\x06#\".\x02#\"\x06\x15'4632\x1e\x023265\x03>{\\)\r?1\ak\x8c\x14:\x12D-\xff\xff\x00\xa2\x02\x8b\x04\x8d\x03\"\x00F\x00\x9f\xd9\x00L\xcd@\x00\xff\xff\x00\x90\x02\x8b\x05\xc9\x03\"\x00F\x00\x9f\x84\x00ff@\x00\x00\x01\x00`\x041\x01x\x06\x13\x00\b\x00!\xb2\b\t\n\x11\x129\x00\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x1e>Y\xb2\x05\t\x00\x11\x129\xb0\x05/01\x01\x17\x06\a\x15#546\x01\x0ej]\x03\xb8a\x06\x13H\u007f\x93\x88tf\xc8\x00\x01\x000\x04\x16\x01G\x06\x00\x00\b\x00!\xb2\b\t\n\x11\x129\x00\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x1e>Y\xb2\x00\t\x04\x11\x129\xb0\x00/01\x13'6753\x15\x06\x06\x99i]\x03\xb7\x01a\x04\x16H\x82\x90\x90\x82d\xc7\x00\x01\x00$\xfe\xe5\x01;\x00\xb5\x00\b\x00\x1e\xb2\b\t\n\x11\x129\x00\xb0\t/\xb2\x04\x05\n+X!\xd8\x1b\xf4Y\xb0\x00а\x00/01\x13'6753\x15\x14\x06\x8di[\x03\xb9c\xfe\xe5I\u007f\x92vde\xca\xff\xff\x00h\x041\x02\xbb\x06\x13\x00&\x00\x93\b\x00\x00\a\x00\x93\x01C\x00\x00\xff\xff\x00<\x04\x16\x02\x86\x06\x00\x00&\x00\x94\f\x00\x00\a\x00\x94\x01?\x00\x00\x00\x02\x00$\xfe\xd3\x02d\x00\xf6\x00\b\x00\x11\x000\xb2\n\x12\x13\x11\x129\xb0\n\x10\xb0\x05\xd0\x00\xb0\x12/\xb2\x04\x05\n+X!\xd8\x1b\xf4Y\xb0\x00а\x00/\xb0\tа\t/\xb0\x04\x10\xb0\r\xd001\x13'6753\x15\x14\x06\x17'6753\x15\x14\x06\x8di[\x03\xb9c\xddi[\x03\xbaa\xfe\xd3H\x89\x99\xb9\xa4l\xd3@H\x89\x99\xb9\xa4k\xd1\x00\x00\x01\x00\x8a\x02\x17\x02\"\x03\xcb\x00\r\x00\x16\xb2\n\x0e\x0f\x11\x129\x00\xb0\x03/\xb1\n\n+X\xd8\x1b\xdcY01\x134632\x16\x15\x15\x14\x06#\"&5\x8ao\\[rn^]o\x03\x04Wpm]%WnoX\x00\x01\x00l\x00\x99\x02 \x03\xb5\x00\x06\x00\x10\x00\xb0\x05/\xb2\x02\a\x05\x11\x129\xb0\x02/01\x01\x01#\x015\x013\x01\x1e\x01\x02\x8d\xfe\xd9\x01'\x8d\x02&\xfes\x01\x84\x13\x01\x85\x00\x01\x00Y\x00\x98\x02\x0e\x03\xb5\x00\x06\x00\x10\x00\xb0\x00/\xb2\x03\a\x00\x11\x129\xb0\x03/01\x13\x01\x15\x01#\x01\x01\xe7\x01'\xfeَ\x01\x02\xfe\xfe\x03\xb5\xfe{\x13\xfe{\x01\x8e\x01\x8f\x00\x01\x00;\x00n\x03j\x05\"\x00\x03\x00\t\x00\xb0\x00/\xb0\x02/017'\x01\x17\xa3h\x02\xc7hnB\x04rB\x00\xff\xff\x006\x02\x90\x02\xbb\x05\xa5\x03\a\x00\xa5\x00\x00\x02\x90\x00\x13\x00\xb0\x00EX\xb0\t/\x1b\xb1\t\x1c>Y\xb0\r\xd001\x00\x00\x01\x00_\xff\xec\x04\x1c\x05\xc4\x00#\x00\x87\xb2\x15$%\x11\x129\x00\xb0\x00EX\xb0\x16/\x1b\xb1\x16\x1c>Y\xb0\x00EX\xb0\t/\x1b\xb1\t\x10>Y\xb2#\t\x16\x11\x129\xb0#/\xb2\x00\x02\n+X!\xd8\x1b\xf4Y\xb0\t\x10\xb2\x04\x01\n+X!\xd8\x1b\xf4Y\xb0\x00\x10\xb0\fа#\x10\xb0\x0fа#\x10\xb0\x1fа\x1f/\xb6\x0f\x1f\x1f\x1f/\x1f\x03]\xb2 \x02\n+X!\xd8\x1b\xf4Y\xb0\x10а\x1f\x10\xb0\x13а\x16\x10\xb2\x1b\x01\n+X!\xd8\x1b\xf4Y01\x01!\x16\x16327\x17\x06#\"\x00\x03#535#53\x12\x0032\x17\a&#\"\x06\a!\x15!\x15!\x03Q\xfe\x80\x04\xb4\xa5tf\x14xx\xf8\xfe\xe3\x06\xb2\xb2\xb2\xb2\n\x01\x1d\xf3j\x87\x14mn\xa4\xb1\x06\x01\u007f\xfe\x80\x01\x80\x02\x1d\xc3\xd2\"\xa0\x1e\x01%\x01\f|\x89}\x01\x06\x01\x1f\x1f\xa2#˼}\x89\x00\x01\x00\xa8\x02\x8b\x03\xeb\x03\"\x00\x03\x00\x1b\x00\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x16>Y\xb2\x01\x01\n+X!\xd8\x1b\xf4Y01\x01!5!\x03\xeb\xfc\xbd\x03C\x02\x8b\x97\x00\x02\x00\x1f\x00\x00\x03\xcd\x06\x15\x00\x15\x00\x19\x00\x83\xb2\b\x1a\x1b\x11\x129\xb0\b\x10\xb0\x17\xd0\x00\xb0\x00EX\xb0\b/\x1b\xb1\b\x1e>Y\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x18>Y\xb0\x00EX\xb0\x11/\x1b\xb1\x11\x18>Y\xb0\x00EX\xb0\x18/\x1b\xb1\x18\x18>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x10>Y\xb0\x00EX\xb0\x16/\x1b\xb1\x16\x10>Y\xb0\x03\x10\xb2\x01\x01\n+X!\xd8\x1b\xf4Y\xb0\b\x10\xb2\r\x01\n+X!\xd8\x1b\xf4Y\xb0\x01\x10\xb0\x13а\x14\xd0013\x11#5354632\x17\a&#\"\x06\x15\x153\x15#\x11!#\x113ʫ\xabϽp\xab\x1f}qwi\xdd\xdd\x02I\xba\xba\x03\xab\x8f\\\xb5\xca=\x9c2kk^\x8f\xfcU\x04:\x00\x01\x00<\x00\x00\x03\xe9\x06\x15\x00\x16\x00\\\x00\xb0\x00EX\xb0\x12/\x1b\xb1\x12\x1e>Y\xb0\x00EX\xb0\x06/\x1b\xb1\x06\x18>Y\xb0\x00EX\xb0\t/\x1b\xb1\t\x10>Y\xb0\x00EX\xb0\x16/\x1b\xb1\x16\x10>Y\xb0\x12\x10\xb2\x02\x01\n+X!\xd8\x1b\xf4Y\xb0\x06\x10\xb2\a\x01\n+X!\xd8\x1b\xf4Y\xb0\vа\x06\x10\xb0\x0e\xd001\x01&#\"\x15\x153\x15#\x11#\x11#5356632\x05\x11#\x030|L\xc8\xe7繫\xab\x01\xc0\xb1e\x01+\xb9\x05c\x14\xd2k\x8f\xfcU\x03\xab\x8fv\xad\xb8=\xfa(\x00\x00\x01\x00z\x00\x00\x01\xef\x03\x15\x00\x06\x005\x00\xb0\x00EX\xb0\x05/\x1b\xb1\x05\x16>Y\xb0\x00EX\xb0\x01/\x1b\xb1\x01\x10>Y\xb2\x04\x05\x01\x11\x129\xb0\x04/\xb2\x03\x02\n+X!\xd8\x1b\xf4Y\xb0\x02\xd001!#\x11\a5%3\x01\xef\x9d\xd8\x01c\x12\x02Y9\x80u\x00\x01\x00B\x00\x00\x02\xab\x03 \x00\x16\x00T\xb2\b\x17\x18\x11\x129\x00\xb0\x00EX\xb0\x0e/\x1b\xb1\x0e\x16>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x10>Y\xb2\x15\x02\n+X!\xd8\x1b\xf4Y\xb0\x02в\x14\x15\x0e\x11\x129\xb2\x03\x0e\x14\x11\x129\xb0\x0e\x10\xb2\b\x02\n+X!\xd8\x1b\xf4Y\xb0\x0e\x10\xb0\v\xd001!!5\x01654&#\"\x06\x15#46 \x16\x15\x14\x0f\x02!\x02\xab\xfd\xa9\x01,m@\xff\xf5\x02\x9a\x03 \x00&\x00q\x00\xb0\x00EX\xb0\x0e/\x1b\xb1\x0e\x16>Y\xb0\x00EX\xb0\x19/\x1b\xb1\x19\x10>Y\xb2\x00\x19\x0e\x11\x129|\xb0\x00/\x18\xb6\x80\x00\x90\x00\xa0\x00\x03]\xb0\x0e\x10\xb2\a\x02\n+X!\xd8\x1b\xf4Y\xb2\n\x00\a\x11\x129\xb0\x00\x10\xb2&\x02\n+X!\xd8\x1b\xf4Y\xb2\x14&\x00\x11\x129\xb0\x19\x10\xb2 \x02\n+X!\xd8\x1b\xf4Y\xb2\x1d& \x11\x12901\x0132654&#\"\x06\x15#4632\x16\x15\x14\x06\a\x16\x15\x14\x06#\"&53\x14\x1632654'#\x01\tTJH?F9K\x9d\xa3|\x89\x9cFB\x95\xaa\x88\x84\xa6\x9eOCFI\x9cX\x01\xcb=0-:3)b{yh7[\x19)\x8fj}~k-<<3q\x02\x00\x00\x02\x006\x00\x00\x02\xbb\x03\x15\x00\n\x00\x0e\x00I\x00\xb0\x00EX\xb0\t/\x1b\xb1\t\x16>Y\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x10>Y\xb2\x01\t\x04\x11\x129\xb0\x01/\xb2\x02\x02\n+X!\xd8\x1b\xf4Y\xb0\x06а\x01\x10\xb0\vв\b\v\x06\x11\x129\xb2\r\t\x04\x11\x12901\x013\x15#\x15#5!'\x013\x013\x11\a\x02Pkk\x9d\xfe\x89\x06\x01y\xa1\xfe\x84\xdf\x11\x01+\x82\xa9\xa9f\x02\x06\xfe\x16\x01!\x1c\xff\xff\x00%\x02\x1f\x02\r\x02\xb6\x02\x06\x00\x11\x00\x00\x00\x02\x00%\x00\x00\x04\xe4\x05\xb0\x00\x0f\x00\x1d\x00f\x00\xb0\x00EX\xb0\x05/\x1b\xb1\x05\x1c>Y\xb0\x00EX\xb0\x00/\x1b\xb1\x00\x10>Y\xb2\x04\x00\x05\x11\x129\xb0\x04/\xb2\xcf\x04\x01]\xb2/\x04\x01]\xb2\x9f\x04\x01q\xb2\x01\x01\n+X!\xd8\x1b\xf4Y\xb0\x11а\x00\x10\xb2\x12\x01\n+X!\xd8\x1b\xf4Y\xb0\x05\x10\xb2\x1b\x01\n+X!\xd8\x1b\xf4Y\xb0\x04\x10\xb0\x1c\xd0013\x11#53\x11!2\x04\x12\x17\x15\x14\x02\x04\a\x13!\x1132\x12754\x02'#\x11!Ǣ\xa2\x01\x9b\xbe\x01$\x9f\x01\x9f\xfe\xd9\xc4G\xfe\xe6\xc9\xde\xf7\x01\xe9\xd6\xe0\x01\x1a\x02\x9a\x97\x02\u007f\xa8\xfe\xca\xc9]\xce\xfeʦ\x02\x02\x9a\xfe\x03\x01\x12\xf9]\xf8\x01\x13\x02\xfe\x1f\x00\xff\xff\x00\x1c\x00\x00\x05\x1d\a4\x02&\x00%\x00\x00\x01\a\x00D\x010\x016\x00\x14\x00\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x1c>Y\xb1\f\b\xf401\xff\xff\x00\x1c\x00\x00\x05\x1d\a4\x02&\x00%\x00\x00\x01\a\x00u\x01\xbf\x016\x00\x14\x00\xb0\x00EX\xb0\x05/\x1b\xb1\x05\x1c>Y\xb1\r\b\xf401\xff\xff\x00\x1c\x00\x00\x05\x1d\a6\x02&\x00%\x00\x00\x01\a\x00\x8e\x00\xc9\x016\x00\x14\x00\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x1c>Y\xb1\x0f\x06\xf401\xff\xff\x00\x1c\x00\x00\x05\x1d\a\"\x02&\x00%\x00\x00\x01\a\x00\x90\x00\xc5\x01:\x00\x14\x00\xb0\x00EX\xb0\x05/\x1b\xb1\x05\x1c>Y\xb1\x0e\x04\xf401\xff\xff\x00\x1c\x00\x00\x05\x1d\x06\xfb\x02&\x00%\x00\x00\x01\a\x00j\x00\xf9\x016\x00\x17\x00\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x1c>Y\xb1\x11\x04\xf4\xb0\x1b\xd001\x00\xff\xff\x00\x1c\x00\x00\x05\x1d\a\x91\x02&\x00%\x00\x00\x01\a\x00\x8f\x01P\x01A\x00\x17\x00\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x1c>Y\xb1\x0e\x06\xf4\xb0\x18\xd001\x00\xff\xff\x00w\xfeD\x04\xd8\x05\xc4\x02&\x00'\x00\x00\x00\a\x00y\x01\xd2\xff\xf7\xff\xff\x00\xa9\x00\x00\x04F\a@\x02&\x00)\x00\x00\x01\a\x00D\x00\xfb\x01B\x00\x14\x00\xb0\x00EX\xb0\x06/\x1b\xb1\x06\x1c>Y\xb1\r\b\xf401\xff\xff\x00\xa9\x00\x00\x04F\a@\x02&\x00)\x00\x00\x01\a\x00u\x01\x8a\x01B\x00\x14\x00\xb0\x00EX\xb0\x06/\x1b\xb1\x06\x1c>Y\xb1\x0e\b\xf401\xff\xff\x00\xa9\x00\x00\x04F\aB\x02&\x00)\x00\x00\x01\a\x00\x8e\x00\x94\x01B\x00\x14\x00\xb0\x00EX\xb0\x06/\x1b\xb1\x06\x1c>Y\xb1\x10\x06\xf401\xff\xff\x00\xa9\x00\x00\x04F\a\a\x02&\x00)\x00\x00\x01\a\x00j\x00\xc4\x01B\x00\x17\x00\xb0\x00EX\xb0\x06/\x1b\xb1\x06\x1c>Y\xb1\x12\x04\xf4\xb0\x1b\xd001\x00\xff\xff\xff\xe0\x00\x00\x01\x81\a@\x02&\x00-\x00\x00\x01\a\x00D\xff\xa7\x01B\x00\x14\x00\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x1c>Y\xb1\x05\b\xf401\xff\xff\x00\xb0\x00\x00\x02Q\a@\x02&\x00-\x00\x00\x01\a\x00u\x005\x01B\x00\x14\x00\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x1c>Y\xb1\x06\b\xf401\xff\xff\xff\xe9\x00\x00\x02F\aB\x02&\x00-\x00\x00\x01\a\x00\x8e\xff@\x01B\x00\x14\x00\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x1c>Y\xb1\b\x06\xf401\xff\xff\xff\xd6\x00\x00\x02_\a\a\x02&\x00-\x00\x00\x01\a\x00j\xffp\x01B\x00\x17\x00\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x1c>Y\xb1\n\x04\xf4\xb0\x14\xd001\x00\xff\xff\x00\xa9\x00\x00\x05\b\a\"\x02&\x002\x00\x00\x01\a\x00\x90\x00\xfb\x01:\x00\x14\x00\xb0\x00EX\xb0\x06/\x1b\xb1\x06\x1c>Y\xb1\r\x04\xf401\xff\xff\x00v\xff\xec\x05\t\a6\x02&\x003\x00\x00\x01\a\x00D\x01R\x018\x00\x14\x00\xb0\x00EX\xb0\r/\x1b\xb1\r\x1c>Y\xb1!\b\xf401\xff\xff\x00v\xff\xec\x05\t\a6\x02&\x003\x00\x00\x01\a\x00u\x01\xe1\x018\x00\x14\x00\xb0\x00EX\xb0\r/\x1b\xb1\r\x1c>Y\xb1\"\b\xf401\xff\xff\x00v\xff\xec\x05\t\a8\x02&\x003\x00\x00\x01\a\x00\x8e\x00\xeb\x018\x00\x14\x00\xb0\x00EX\xb0\r/\x1b\xb1\r\x1c>Y\xb1\"\x06\xf401\xff\xff\x00v\xff\xec\x05\t\a$\x02&\x003\x00\x00\x01\a\x00\x90\x00\xe7\x01<\x00\x14\x00\xb0\x00EX\xb0\r/\x1b\xb1\r\x1c>Y\xb1#\x04\xf401\xff\xff\x00v\xff\xec\x05\t\x06\xfd\x02&\x003\x00\x00\x01\a\x00j\x01\x1b\x018\x00\x17\x00\xb0\x00EX\xb0\r/\x1b\xb1\r\x1c>Y\xb1'\x04\xf4\xb00\xd001\x00\xff\xff\x00\x8c\xff\xec\x04\xaa\a4\x02&\x009\x00\x00\x01\a\x00D\x01+\x016\x00\x14\x00\xb0\x00EX\xb0\n/\x1b\xb1\n\x1c>Y\xb1\x14\b\xf401\xff\xff\x00\x8c\xff\xec\x04\xaa\a4\x02&\x009\x00\x00\x01\a\x00u\x01\xba\x016\x00\x14\x00\xb0\x00EX\xb0\x12/\x1b\xb1\x12\x1c>Y\xb1\x15\b\xf401\xff\xff\x00\x8c\xff\xec\x04\xaa\a6\x02&\x009\x00\x00\x01\a\x00\x8e\x00\xc4\x016\x00\x14\x00\xb0\x00EX\xb0\n/\x1b\xb1\n\x1c>Y\xb1\x17\x06\xf401\xff\xff\x00\x8c\xff\xec\x04\xaa\x06\xfb\x02&\x009\x00\x00\x01\a\x00j\x00\xf4\x016\x00\x17\x00\xb0\x00EX\xb0\n/\x1b\xb1\n\x1c>Y\xb1\x19\x04\xf4\xb0#\xd001\x00\xff\xff\x00\x0f\x00\x00\x04\xbb\a4\x02&\x00=\x00\x00\x01\a\x00u\x01\x88\x016\x00\x14\x00\xb0\x00EX\xb0\x01/\x1b\xb1\x01\x1c>Y\xb1\v\b\xf401\xff\xff\x00m\xff\xec\x03\xea\x05\xfe\x02&\x00E\x00\x00\x01\a\x00D\x00\xd5\x00\x00\x00\x14\x00\xb0\x00EX\xb0\x17/\x1b\xb1\x17\x18>Y\xb1*\t\xf401\xff\xff\x00m\xff\xec\x03\xea\x05\xfe\x02&\x00E\x00\x00\x01\a\x00u\x01d\x00\x00\x00\x14\x00\xb0\x00EX\xb0\x17/\x1b\xb1\x17\x18>Y\xb1+\t\xf401\xff\xff\x00m\xff\xec\x03\xea\x06\x00\x02&\x00E\x00\x00\x01\x06\x00\x8en\x00\x00\x14\x00\xb0\x00EX\xb0\x17/\x1b\xb1\x17\x18>Y\xb1+\x01\xf401\xff\xff\x00m\xff\xec\x03\xea\x05\xec\x02&\x00E\x00\x00\x01\x06\x00\x90j\x04\x00\x14\x00\xb0\x00EX\xb0\x17/\x1b\xb1\x17\x18>Y\xb1,\x01\xf401\xff\xff\x00m\xff\xec\x03\xea\x05\xc5\x02&\x00E\x00\x00\x01\a\x00j\x00\x9e\x00\x00\x00\x17\x00\xb0\x00EX\xb0\x17/\x1b\xb1\x17\x18>Y\xb10\x01\xf4\xb09\xd001\x00\xff\xff\x00m\xff\xec\x03\xea\x06[\x02&\x00E\x00\x00\x01\a\x00\x8f\x00\xf5\x00\v\x00\x17\x00\xb0\x00EX\xb0\x17/\x1b\xb1\x17\x18>Y\xb1,\x04\xf4\xb06\xd001\x00\xff\xff\x00\\\xfeD\x03\xec\x04N\x02&\x00G\x00\x00\x00\a\x00y\x01?\xff\xf7\xff\xff\x00]\xff\xec\x03\xf3\x05\xfe\x02&\x00I\x00\x00\x01\a\x00D\x00\xc5\x00\x00\x00\x14\x00\xb0\x00EX\xb0\b/\x1b\xb1\b\x18>Y\xb1\x1f\t\xf401\xff\xff\x00]\xff\xec\x03\xf3\x05\xfe\x02&\x00I\x00\x00\x01\a\x00u\x01T\x00\x00\x00\x14\x00\xb0\x00EX\xb0\b/\x1b\xb1\b\x18>Y\xb1 \t\xf401\xff\xff\x00]\xff\xec\x03\xf3\x06\x00\x02&\x00I\x00\x00\x01\x06\x00\x8e^\x00\x00\x14\x00\xb0\x00EX\xb0\b/\x1b\xb1\b\x18>Y\xb1 \x01\xf401\xff\xff\x00]\xff\xec\x03\xf3\x05\xc5\x02&\x00I\x00\x00\x01\a\x00j\x00\x8e\x00\x00\x00\x17\x00\xb0\x00EX\xb0\b/\x1b\xb1\b\x18>Y\xb1%\x01\xf4\xb0.\xd001\x00\xff\xff\xff\xc6\x00\x00\x01g\x05\xfd\x02&\x00\x8b\x00\x00\x01\x06\x00D\x8d\xff\x00\x14\x00\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x18>Y\xb1\x05\t\xf401\xff\xff\x00\x96\x00\x00\x027\x05\xfd\x02&\x00\x8b\x00\x00\x01\x06\x00u\x1b\xff\x00\x14\x00\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x18>Y\xb1\x06\t\xf401\xff\xff\xff\xcf\x00\x00\x02,\x05\xff\x02&\x00\x8b\x00\x00\x01\a\x00\x8e\xff&\xff\xff\x00\x14\x00\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x18>Y\xb1\b\x01\xf401\xff\xff\xff\xbc\x00\x00\x02E\x05\xc4\x02&\x00\x8b\x00\x00\x01\a\x00j\xffV\xff\xff\x00\x17\x00\xb0\x00EX\xb0\x02/\x1b\xb1\x02\x18>Y\xb1\v\x01\xf4\xb0\x14\xd001\x00\xff\xff\x00\x8c\x00\x00\x03\xdf\x05\xec\x02&\x00R\x00\x00\x01\x06\x00\x90a\x04\x00\x14\x00\xb0\x00EX\xb0\x03/\x1b\xb1\x03\x18>Y\xb1\x15\x01\xf401\xff\xff\x00[\xff\xec\x044\x05\xfe\x02&\x00S\x00\x00\x01\a\x00D\x00\xcf\x00\x00\x00\x14\x00\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x18>Y\xb1\x1d\t\xf401\xff\xff\x00[\xff\xec\x044\x05\xfe\x02&\x00S\x00\x00\x01\a\x00u\x01^\x00\x00\x00\x14\x00\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x18>Y\xb1\x1e\t\xf401\xff\xff\x00[\xff\xec\x044\x06\x00\x02&\x00S\x00\x00\x01\x06\x00\x8eh\x00\x00\x14\x00\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x18>Y\xb1\x1e\x01\xf401\xff\xff\x00[\xff\xec\x044\x05\xec\x02&\x00S\x00\x00\x01\x06\x00\x90d\x04\x00\x14\x00\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x18>Y\xb1\x1f\x01\xf401\xff\xff\x00[\xff\xec\x044\x05\xc5\x02&\x00S\x00\x00\x01\a\x00j\x00\x98\x00\x00\x00\x17\x00\xb0\x00EX\xb0\x04/\x1b\xb1\x04\x18>Y\xb1#\x01\xf4\xb0,\xd001\x00\xff\xff\x00\x88\xff\xec\x03\xdc\x05\xfe\x02&\x00Y\x00\x00\x01\a\x00D\x00\xc7\x00\x00\x00\x14\x00\xb0\x00EX\xb0\a/\x1b\xb1\a\x18>Y\xb1\x12\t\xf401\xff\xff\x00\x88\xff\xec\x03\xdc\x05\xfe\x02&\x00Y\x00\x00\x01\a\x00u\x01V\x00\x00\x00\x14\x00\xb0\x00EX\xb0\r/\x1b\xb1\r\x18>Y\xb1\x13\t\xf401\xff\xff\x00\x88\xff\xec\x03\xdc\x06\x00\x02&\x00Y\x00\x00\x01\x06\x00\x8e`\x00\x00\x14\x00\xb0\x00EX\xb0\a/\x1b\xb1\a\x18>Y\xb1\x15\x01\xf401\xff\xff\x00\x88\xff\xec\x03\xdc\x05\xc5\x02&\x00Y\x00\x00\x01\a\x00j\x00\x90\x00\x00\x00\x17\x00\xb0\x00EX\xb0\a/\x1b\xb1\a\x18>Y\xb1\x18\x01\xf4\xb0!\xd001\x00\xff\xff\x00\x16\xfeK\x03\xb0\x05\xfe\x02&\x00]\x00\x00\x01\a\x00u\x01\x1b\x00\x00\x00\x14\x00\xb0\x00EX\xb0\x01/\x1b\xb1\x01\x18>Y\xb1\x12\t\xf401\xff\xff\x00\x16\xfeK\x03\xb0\x05\xc5\x02&\x00]\x00\x00\x01\x06\x00jU\x00\x00\x17\x00\xb0\x00EX\xb0\x0f/\x1b\xb1\x0f\x18>Y\xb1\x17\x01\xf4\xb0 \xd001\x00\x00\x00\x00\x01\x00\x00\x00\xde\x00\x8f\x00\x16\x00T\x00\x05\x00\x01\x00\x00\x00\x00\x00\x0e\x00\x00\x02\x00\x02\x14\x00\x06\x00\x01\x00\x00\x00a\x00a\x00a\x00a\x00a\x00\x93\x00\xb8\x018\x01\xaa\x02:\x02\xcd\x02\xe4\x03\x0e\x038\x03k\x03\x90\x03\xaf\x03\xc5\x03\xe6\x03\xfd\x04J\x04x\x04\xc7\x05<\x05\u007f\x05\xdf\x06>\x06k\x06\xdf\aF\a[\ap\a\x8f\a\xb6\a\xd5\b3\b\xd6\t\x15\tt\t\xc8\n\r\nM\n\x83\n\xeb\v-\vH\v{\v\xd0\v\xf4\fB\f~\f\xd3\r\x1e\r\x83\r\xdf\x0eJ\x0et\x0e\xb6\x0e\xe6\x0f;\x0f\x90\x0f\xc0\x0f\xf8\x10\x1c\x103\x10X\x10\u007f\x10\x9a\x10\xba\x112\x11\x90\x11\xe3\x12A\x12\xa8\x12\xfa\x13t\x13\xb9\x13\xf1\x14=\x14\x94\x14\xaf\x15\x1a\x15e\x15\xb3\x16\x17\x16x\x16\xb5\x17\x1f\x17q\x17\xb8\x17\xe8\x186\x18}\x18\xc2\x18\xfa\x19;\x19R\x19\x92\x19\xd9\x1a\f\x1ah\x1a\xda\x1b=\x1b\x9c\x1b\xbb\x1c`\x1c\x8f\x1d5\x1d\xa3\x1d\xaf\x1d\xcc\x1e\x84\x1e\x9a\x1e\xd6\x1f\x19\x1fi\x1f\xe4 \x04 M y \x98 \xd3!\x05!O![!u!\x8f!\xa9\"\n\"m\"\xab#&#z#\xea$\xa8%\x17%h%\xd9&8&S&\xd6'p'\x9e'\xd7(\x1b(%(/(S(w(\x99(\xa5(\xb1(\xe9)\f)()E)X)l)\xe8*\x03*k*\xbd*\xe8+7+\xa6+\xe8+\xe8+\xf0,V,m,\x84,\x9b,\xb2,\xcb,\xe4,\xf0-\a-\x1e-5-N-e-|-\x93-\xac-\xc3-\xda-\xf1.\b.\x1f.8.O.f.}.\x96.\xad.\xc4.\xdb.\xf1/\a/ /9/E/\\/s/\x89/\xa2/\xb8/\xce/\xe5/\xfe0\x140+0B0X0n0\x870\x9e0\xb50\xcb0\xe40\xfb1\x13\x00\x00\x00\x01\x00\x00\x00\x02\x00\x000\x1bQ\xae_\x0f<\xf5\x00\x1b\b\x00\x00\x00\x00\x00\xc4\xf0\x11.\x00\x00\x00\x00\xd0\xdbN\x9a\xfa\x1b\xfd\xd5\t0\bs\x00\x00\x00\t\x00\x02\x00\x00\x00\x00\x00\x00\x03\x8c\x00d\x00\x00\x00\x00\x00\x00\x00\x00\x01\xfb\x00\x00\x01\xfb\x00\x00\x02\x0f\x00\xa0\x02\x8f\x00\x88\x04\xed\x00w\x04~\x00n\x05\xdc\x00i\x04\xf9\x00e\x01e\x00g\x02\xbc\x00\x85\x02\xc8\x00&\x03r\x00\x1c\x04\x89\x00N\x01\x92\x00\x1d\x025\x00%\x02\x1b\x00\x90\x03L\x00\x12\x04~\x00s\x04~\x00\xaa\x04~\x00]\x04~\x00^\x04~\x005\x04~\x00\x9a\x04~\x00\x84\x04~\x00M\x04~\x00p\x04~\x00d\x01\xf0\x00\x86\x01\xb1\x00)\x04\x11\x00H\x04d\x00\x98\x04.\x00\x86\x03\xc7\x00K\a/\x00j\x058\x00\x1c\x04\xfb\x00\xa9\x055\x00w\x05?\x00\xa9\x04\x8c\x00\xa9\x04l\x00\xa9\x05s\x00z\x05\xb4\x00\xa9\x02-\x00\xb7\x04j\x005\x05\x04\x00\xa9\x04N\x00\xa9\x06\xfc\x00\xa9\x05\xb4\x00\xa9\x05\x80\x00v\x05\f\x00\xa9\x05\x80\x00m\x04\xed\x00\xa8\x04\xbf\x00P\x04\xc6\x001\x050\x00\x8c\x05\x17\x00\x1c\a\x19\x00=\x05\x04\x009\x04\xce\x00\x0f\x04\xca\x00V\x02\x1f\x00\x92\x03H\x00(\x02\x1f\x00\t\x03X\x00@\x03\x9c\x00\x04\x02y\x009\x04Z\x00m\x04}\x00\x8c\x040\x00\\\x04\x83\x00_\x04=\x00]\x02\xc7\x00<\x04}\x00`\x04h\x00\x8c\x01\xf1\x00\x8d\x01\xe9\xff\xbf\x04\x0e\x00\x8d\x01\xf1\x00\x9c\a\x03\x00\x8b\x04j\x00\x8c\x04\x90\x00[\x04}\x00\x8c\x04\x8c\x00_\x02\xb5\x00\x8c\x04 \x00_\x02\x9d\x00\t\x04i\x00\x88\x03\xe0\x00!\x06\x03\x00+\x03\xf7\x00)\x03\xc9\x00\x16\x03\xf7\x00X\x02\xb5\x00@\x01\xf3\x00\xaf\x02\xb5\x00\x13\x05q\x00\x83\x01\xf3\x00\x8b\x04`\x00i\x04\xa6\x00[\x05\xb4\x00i\x04\xd8\x00\x1f\x01\xeb\x00\x93\x04\xe8\x00Z\x03X\x00f\x06I\x00[\x03\x93\x00\x93\x03\xc1\x00f\x04n\x00\u007f\x06J\x00Z\x03\xaa\x00x\x02\xfd\x00\x82\x04F\x00a\x02\xef\x00B\x02\xef\x00>\x02\x82\x00{\x04\x88\x00\x9a\x03\xe9\x00C\x02\x16\x00\x93\x01\xfb\x00t\x02\xef\x00z\x03\xa3\x00z\x03\xc0\x00f\x05\xdc\x00U\x065\x00P\x069\x00o\x03\xc9\x00D\az\xff\xf2\x04D\x00Y\x05\x80\x00v\x04\xba\x00\xa6\x04\xc2\x00\x8b\x06\xc1\x00N\x04\xb0\x00~\x04\x91\x00G\x04\x88\x00[\x04\x9c\x00\x95\x01\xfa\x00\x9b\a\xa1\x00h\aD\x00a\x03\xc4\x00\xa9\x02\xad\x00y\x03\xc6\x00{\x05@\x00\xa2\x06?\x00\x90\x01\x99\x00`\x01\x99\x000\x01\x97\x00$\x02\xd4\x00h\x02\xdb\x00<\x02\xc1\x00$\x02\xb2\x00\x8a\x02f\x00l\x02f\x00Y\x03\xa3\x00;\x02\xef\x006\x04~\x00_\x04\x92\x00\xa8\x04n\x00\x1f\x04\x8b\x00<\x02\xef\x00z\x02\xef\x00B\x02\xef\x00>\x02\xef\x006\x01\xfb\x00\x00\x025\x00%\x05]\x00%\x058\x00\x1c\x058\x00\x1c\x058\x00\x1c\x058\x00\x1c\x058\x00\x1c\x058\x00\x1c\x055\x00w\x04\x8c\x00\xa9\x04\x8c\x00\xa9\x04\x8c\x00\xa9\x04\x8c\x00\xa9\x02-\xff\xe0\x02-\x00\xb0\x02-\xff\xe9\x02-\xff\xd6\x05\xb4\x00\xa9\x05\x80\x00v\x05\x80\x00v\x05\x80\x00v\x05\x80\x00v\x05\x80\x00v\x050\x00\x8c\x050\x00\x8c\x050\x00\x8c\x050\x00\x8c\x04\xce\x00\x0f\x04Z\x00m\x04Z\x00m\x04Z\x00m\x04Z\x00m\x04Z\x00m\x04Z\x00m\x040\x00\\\x04=\x00]\x04=\x00]\x04=\x00]\x04=\x00]\x01\xfa\xff\xc6\x01\xfa\x00\x96\x01\xfa\xff\xcf\x01\xfa\xff\xbc\x04j\x00\x8c\x04\x90\x00[\x04\x90\x00[\x04\x90\x00[\x04\x90\x00[\x04\x90\x00[\x04i\x00\x88\x04i\x00\x88\x04i\x00\x88\x04i\x00\x88\x03\xc9\x00\x16\x00\x16\x00\x00\x00\x01\x00\x00\al\xfe\f\x00\x00\tI\xfa\x1b\xfeJ\t0\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdd\x00\x03\x04\x85\x01\x90\x00\x05\x00\x00\x05\x9a\x053\x00\x00\x01\x1f\x05\x9a\x053\x00\x00\x03\xd1\x00f\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\n\xffP\x00!\u007f\x00\x00\x00!\x00\x00\x00\x00GOOG\x00@\x00\x00\xff\xfd\x06\x00\xfe\x00\x00f\a\x9a\x02\x00 \x00\x01\x9f\x00\x00\x00\x00\x04:\x05\xb0\x00 \x00 \x00\x02\x00\x00\x00\x01\x00\x00\x00\xe0\t\t\x04\x00\x00\x02\x02\x02\x03\x06\x05\a\x06\x02\x03\x03\x04\x05\x02\x02\x02\x04\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x02\x02\x05\x05\x05\x04\b\x06\x06\x06\x06\x05\x05\x06\x06\x02\x05\x06\x05\b\x06\x06\x06\x06\x06\x05\x05\x06\x06\b\x06\x05\x05\x02\x04\x02\x04\x04\x03\x05\x05\x05\x05\x05\x03\x05\x05\x02\x02\x05\x02\b\x05\x05\x05\x05\x03\x05\x03\x05\x04\a\x04\x04\x04\x03\x02\x03\x06\x02\x05\x05\x06\x05\x02\x06\x04\a\x04\x04\x05\a\x04\x03\x05\x03\x03\x03\x05\x04\x02\x02\x03\x04\x04\a\a\a\x04\b\x05\x06\x05\x05\b\x05\x05\x05\x05\x02\t\b\x04\x03\x04\x06\a\x02\x02\x02\x03\x03\x03\x03\x03\x03\x04\x03\x05\x05\x05\x05\x03\x03\x03\x03\x02\x02\x06\x06\x06\x06\x06\x06\x06\x06\x05\x05\x05\x05\x02\x02\x02\x02\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x02\x02\x02\x02\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x04\x04\x00\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00\x1c\x00\x03\x00\x01\x00\x00\x00\x1c\x00\x03\x00\n\x00\x00\x01`\x00\x04\x01D\x00\x00\x006\x00 \x00\x04\x00\x16\x00\x00\x00\r\x00~\x00\xa0\x00\xac\x00\xad\x00\xbf\x00\xc6\x00\xcf\x00\xe6\x00\xef\x00\xff\x011\x01S\x02\xc6\x02\xda\x02\xdc \x14 \x1a \x1e \" : D t \xac\"\x12\xff\xff\x00\x00\x00\x00\x00\r\x00 \x00\xa0\x00\xa1\x00\xad\x00\xae\x00\xc0\x00\xc7\x00\xd0\x00\xe7\x00\xf0\x011\x01R\x02\xc6\x02\xda\x02\xdc \x13 \x18 \x1c \" 9 D t \xac\"\x12\xff\xff\x00\x01\xff\xf6\xff\xe4\x00\x06\xff\xc2\xff\xfa\xff\xc1\x00\x00\xff\xe8\x00\x00\xff\xe2\x00\x00\xffZ\xff:\xfd\xc8\xfd\xb5\xfd\xb4\xe0~\xe0{\xe0z\xe0w\xe0a\xe0X\xe0)\xdf\xf2ލ\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(\x00\x00\x002\x00\x00\x00\\\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa9\x00\xaa\x00\xab\x00\xac\x00\xad\x00\xae\x00\x81\x00\xa8\x00\xb8\x00\xb9\x00\xba\x00\xbb\x00\xbc\x00\xbd\x00\x82\x00\x83\x00\xbe\x00\xbf\x00\xc0\x00\xc1\x00\xc2\x00\x84\x00\x85\x00\xc3\x00\xc4\x00\xc5\x00\xc6\x00\xc7\x00\xc8\x00\x86\x00\x87\x00\xd2\x00\xd3\x00\xd4\x00\xd5\x00\xd6\x00\xd7\x00\x88\x00\x89\x00\xd8\x00\xd9\x00\xda\x00\xdb\x00\xdc\x00\x8a\x00\xdd\x00\f\x00\x00\x00\x00\x01\xd8\x00\x00\x00\x00\x00\x00\x00&\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\r\x00\x00\x00\r\x00\x00\x00\x03\x00\x00\x00 \x00\x00\x00~\x00\x00\x00\x04\x00\x00\x00\xa0\x00\x00\x00\xa0\x00\x00\x00\xa6\x00\x00\x00\xa1\x00\x00\x00\xac\x00\x00\x00c\x00\x00\x00\xad\x00\x00\x00\xad\x00\x00\x00\xa7\x00\x00\x00\xae\x00\x00\x00\xbf\x00\x00\x00o\x00\x00\x00\xc0\x00\x00\x00\xc5\x00\x00\x00\xa9\x00\x00\x00\xc6\x00\x00\x00\xc6\x00\x00\x00\x81\x00\x00\x00\xc7\x00\x00\x00\xcf\x00\x00\x00\xaf\x00\x00\x00\xd0\x00\x00\x00\xd0\x00\x00\x00\xa8\x00\x00\x00\xd1\x00\x00\x00\xd6\x00\x00\x00\xb8\x00\x00\x00\xd7\x00\x00\x00\xd8\x00\x00\x00\x82\x00\x00\x00\xd9\x00\x00\x00\xdd\x00\x00\x00\xbe\x00\x00\x00\xde\x00\x00\x00\xdf\x00\x00\x00\x84\x00\x00\x00\xe0\x00\x00\x00\xe5\x00\x00\x00\xc3\x00\x00\x00\xe6\x00\x00\x00\xe6\x00\x00\x00\x86\x00\x00\x00\xe7\x00\x00\x00\xef\x00\x00\x00\xc9\x00\x00\x00\xf0\x00\x00\x00\xf0\x00\x00\x00\x87\x00\x00\x00\xf1\x00\x00\x00\xf6\x00\x00\x00\xd2\x00\x00\x00\xf7\x00\x00\x00\xf8\x00\x00\x00\x88\x00\x00\x00\xf9\x00\x00\x00\xfd\x00\x00\x00\xd8\x00\x00\x00\xfe\x00\x00\x00\xfe\x00\x00\x00\x8a\x00\x00\x00\xff\x00\x00\x00\xff\x00\x00\x00\xdd\x00\x00\x011\x00\x00\x011\x00\x00\x00\x8b\x00\x00\x01R\x00\x00\x01S\x00\x00\x00\x8c\x00\x00\x02\xc6\x00\x00\x02\xc6\x00\x00\x00\x8e\x00\x00\x02\xda\x00\x00\x02\xda\x00\x00\x00\x8f\x00\x00\x02\xdc\x00\x00\x02\xdc\x00\x00\x00\x90\x00\x00 \x13\x00\x00 \x14\x00\x00\x00\x91\x00\x00 \x18\x00\x00 \x1a\x00\x00\x00\x93\x00\x00 \x1c\x00\x00 \x1e\x00\x00\x00\x96\x00\x00 \"\x00\x00 \"\x00\x00\x00\x99\x00\x00 9\x00\x00 :\x00\x00\x00\x9a\x00\x00 D\x00\x00 D\x00\x00\x00\x9c\x00\x00 t\x00\x00 t\x00\x00\x00\x9d\x00\x00 \xac\x00\x00 \xac\x00\x00\x00\x9e\x00\x00\"\x12\x00\x00\"\x12\x00\x00\x00\x9f\xb0\x00,K\xb0\tPX\xb1\x01\x01\x8eY\xb8\x01\xff\x85\xb0\x84\x1d\xb1\t\x03_^-\xb0\x01, EiD\xb0\x01`-\xb0\x02,\xb0\x01*!-\xb0\x03, F\xb0\x03%FRX#Y \x8a \x8aId\x8a F had\xb0\x04%F hadRX#e\x8aY/ \xb0\x00SXi \xb0\x00TX!\xb0@Y\x1bi \xb0\x00TX!\xb0@eYY:-\xb0\x04, F\xb0\x04%FRX#\x8aY F jad\xb0\x04%F jadRX#\x8aY/\xfd-\xb0\x05,K \xb0\x03&PXQX\xb0\x80D\x1b\xb0@DY\x1b!! E\xb0\xc0PX\xb0\xc0D\x1b!YY-\xb0\x06, EiD\xb0\x01` E}i\x18D\xb0\x01`-\xb0\a,\xb0\x06*-\xb0\b,K \xb0\x03&SX\xb0@\x1b\xb0\x00Y\x8a\x8a \xb0\x03&SX#!\xb0\x80\x8a\x8a\x1b\x8a#Y \xb0\x03&SX#!\xb0\xc0\x8a\x8a\x1b\x8a#Y \xb0\x03&SX#!\xb8\x01\x00\x8a\x8a\x1b\x8a#Y \xb0\x03&SX#!\xb8\x01@\x8a\x8a\x1b\x8a#Y \xb0\x03&SX\xb0\x03%E\xb8\x01\x80PX#!\xb8\x01\x80#!\x1b\xb0\x03%E#!#!Y\x1b!YD-\xb0\t,KSXED\x1b!!Y-\xb0\n,\xb0$E-\xb0\v,\xb0%E-\xb0\f,\xb1'\x01\x88 \x8aSX\xb9@\x00\x04\x00c\xb8\b\x00\x88TX\xb9\x00$\x03\xe8pY\x1b\xb0#SX\xb0 \x88\xb8\x10\x00TX\xb9\x00$\x03\xe8pYYY-\xb0\r,\xb0@\x88\xb8 \x00ZX\xb1%\x00D\x1b\xb9\x00%\x03\xe8DY-\xb0\f+\xb0\x00+\x00\xb2\x01\x0e\x02+\x01\xb2\x0f\x01\x02+\x01\xb7\x0f:0%\x1b\x10\x00\b+\x00\xb7\x01H;.!\x14\x00\b+\xb7\x02XH8(\x14\x00\b+\xb7\x03RC4%\x16\x00\b+\xb7\x04^M<+\x19\x00\b+\xb7\x056,\"\x19\x0f\x00\b+\xb7\x06q]F2\x1b\x00\b+\xb7\a\x91w\\:#\x00\b+\xb7\b~gP9\x1a\x00\b+\xb7\tTE6&\x17\x00\b+\xb7\nv`K6\x1d\x00\b+\xb7\v\x83dN:#\x00\b+\xb7\fٲ\x8ac<\x00\b+\xb7\r\x14\x11\r\t\x06\x00\b+\xb7\x0e<2'\x1c\x11\x00\b+\x00\xb2\x10\n\a+\xb0\x00 E}i\x18D\xb20\x12\x01s\xb2\xb0\x14\x01s\xb2P\x14\x01t\xb2\x80\x14\x01t\xb2p\x14\x01u\xb2\x0f\x1c\x01s\xb2o\x1c\x01u\x00\x00*\x00\x9d\x00\x80\x00\x8a\x00x\x00\xd4\x00d\x00N\x00Z\x00\x87\x00`\x00V\x004\x02<\x00\xbc\x00\xc4\x00\x00\x00\x14\xfe`\x00\x14\x02\x9b\x00 \x03!\x00\v\x04:\x00\x14\x04\x8d\x00\x10\x05\xb0\x00\x14\x06\x18\x00\x15\x01\xa6\x00\x11\x06\xc0\x00\x0e\x00\x00\x00\x00\x00\x00\x00\a\x00Z\x00\x03\x00\x01\x04\t\x00\x01\x00\f\x00\x00\x00\x03\x00\x01\x04\t\x00\x02\x00\x0e\x00\f\x00\x03\x00\x01\x04\t\x00\x03\x00\f\x00\x00\x00\x03\x00\x01\x04\t\x00\x04\x00\f\x00\x00\x00\x03\x00\x01\x04\t\x00\x05\x00,\x00\x1a\x00\x03\x00\x01\x04\t\x00\x06\x00\x1c\x00F\x00\x03\x00\x01\x04\t\x00\x0e\x00T\x00b\x00R\x00o\x00b\x00o\x00t\x00o\x00R\x00e\x00g\x00u\x00l\x00a\x00r\x00V\x00e\x00r\x00s\x00i\x00o\x00n\x00 \x002\x00.\x000\x000\x001\x001\x000\x001\x00;\x00 \x002\x000\x001\x004\x00R\x00o\x00b\x00o\x00t\x00o\x00-\x00R\x00e\x00g\x00u\x00l\x00a\x00r\x00h\x00t\x00t\x00p\x00:\x00/\x00/\x00w\x00w\x00w\x00.\x00a\x00p\x00a\x00c\x00h\x00e\x00.\x00o\x00r\x00g\x00/\x00l\x00i\x00c\x00e\x00n\x00s\x00e\x00s\x00/\x00L\x00I\x00C\x00E\x00N\x00S\x00E\x00-\x002\x00.\x000\x00\x03\x00\x00\x00\x00\x00\x00\xffj\x00d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\x00\b\x00\x02\xff\xff\x00\x0f\x00\x01\x00\x00\x00\f\x00\x00\x00\x00\x00\x00\x00\x02\x00\n\x00%\x00>\x00\x01\x00E\x00^\x00\x01\x00y\x00y\x00\x03\x00\x81\x00\x81\x00\x01\x00\x83\x00\x83\x00\x01\x00\x86\x00\x86\x00\x01\x00\x89\x00\x89\x00\x01\x00\x8b\x00\x8d\x00\x01\x00\xa0\x00\xa1\x00\x02\x00\xa8\x00\xdd\x00\x01\x00\x01\x00\x00\x00\n\x00T\x00t\x00\x04DFLT\x00\x1acyrl\x00&grek\x002latn\x00>\x00\x04\x00\x00\x00\x00\xff\xff\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\xff\xff\x00\x01\x00\x01\x00\x04\x00\x00\x00\x00\xff\xff\x00\x01\x00\x02\x00\x04\x00\x00\x00\x00\xff\xff\x00\x01\x00\x03\x00\x04kern\x00\x1akern\x00\x1akern\x00\x1akern\x00\x1a\x00\x00\x00\x01\x00\x00\x00\x01\x00\x04\x00\x02\x00\x00\x00\x04\x00\x0e\x02\x0e\x03\x92\x04R\x00\x01\x00\x82\x00\x04\x00\x00\x00<\x01\x88\x01\x88\x00\xfe\x01\x8e\x01\x9c\x01\xb4\x01\xaa\x01\x04\x01\n\x01\x10\x01\xb4\x01\x16\x01 \x01B\x01T\x01\xba\x01f\x01\xf4\x01l\x01\xf4\x01\xf4\x01\xf4\x01\xf4\x01z\x01\xfa\x01\xfa\x01\x88\x01\x88\x01\x88\x01\x88\x01\xb4\x01\x8e\x01\x8e\x01\x8e\x01\x8e\x01\x8e\x01\x8e\x01\x9c\x01\xaa\x01\xaa\x01\xaa\x01\xaa\x01\xb4\x01\xb4\x01\xb4\x01\xb4\x01\xb4\x01\xba\x01\xf4\x01\xf4\x01\xf4\x01\xf4\x01\xf4\x01\xf4\x01\xf4\x01\xf4\x01\xf4\x01\xf4\x01\xfa\x01\xfa\x00\x01\x00<\x00\x06\x00\v\x00\x13\x00%\x00'\x00(\x00)\x00*\x00/\x000\x003\x004\x008\x00:\x00;\x00=\x00>\x00I\x00J\x00L\x00Q\x00R\x00S\x00V\x00Z\x00]\x00\x93\x00\x94\x00\x96\x00\x97\x00\xa8\x00\xa9\x00\xaa\x00\xab\x00\xac\x00\xad\x00\xae\x00\xaf\x00\xb0\x00\xb1\x00\xb2\x00\xb3\x00\xb9\x00\xba\x00\xbb\x00\xbc\x00\xbd\x00\xc2\x00\xca\x00\xcb\x00\xcc\x00\xcd\x00\xd2\x00\xd3\x00\xd4\x00\xd5\x00\xd6\x00\xd7\x00\xdc\x00\xdd\x00\x01\x00\x13\xff \x00\x01\x00V\xff\xe6\x00\x01\x00[\xff\xc1\x00\x01\x00[\xff\xa4\x00\x02\x00X\x00\x0e\x00\x81\xff\x9f\x00\b\x00\x04\xff\xd8\x00V\xff\xb5\x00[\xff\xc7\x00m\xfe\xb8\x00|\xff(\x00\x81\xffM\x00\x86\xff\x8e\x00\x89\xff\xa1\x00\x04\x00\r\x00\x14\x00A\x00\x11\x00V\xff\xe2\x00a\x00\x13\x00\x04\x00\r\x00\x0f\x00A\x00\f\x00V\xff\xeb\x00a\x00\x0e\x00\x01\x00[\xff\xe5\x00\x03\x00\r\x00\x14\x00A\x00\x12\x00a\x00\x13\x00\x03\x00J\x00\x0f\x00X\x002\x00[\x00\x11\x00\x01\x00[\x00\v\x00\x03\x00#\xff\xc3\x00X\xff\xef\x00[\xff\xdf\x00\x03\x00\r\xff\xe6\x00A\xff\xf4\x00a\xff\xef\x00\x02\x00J\xff\xee\x00[\xff\xea\x00\x01\x00\x81\xff\xdf\x00\x0e\x00\n\xff\xe2\x00\r\x00\x14\x00\x0e\xff\xcf\x00A\x00\x12\x00J\xff\xea\x00V\xff\xd8\x00X\xff\xea\x00a\x00\x13\x00m\xff\xae\x00|\xff\xcd\x00\x81\xff\xa0\x00\x86\xff\xc1\x00\x89\xff\xc0\x00\x99\xff\xd3\x00\x01\x00\x94\xff\xb0\x00\x01\x00J\x00\r\x00\x01\x00\x18\x00\x04\x00\x00\x00\a\x00*\x000\x00B\x00\xfc\x01\x12\x01$\x01>\x00\x01\x00\a\x00\x04\x00\f\x00*\x005\x006\x00?\x00J\x00\x01\x008\xff\xd8\x00\x04\x00:\x00\x14\x00;\x00\x12\x00=\x00\x16\x00\xc2\x00\x16\x00.\x00\x10\xff\x16\x00\x12\xff\x16\x00%\xffV\x00.\xfe\xf8\x008\x00\x14\x00E\xff\xde\x00G\xff\xeb\x00H\xff\xeb\x00I\xff\xeb\x00K\xff\xeb\x00S\xff\xeb\x00U\xff\xeb\x00Y\xff\xea\x00Z\xff\xe8\x00]\xff\xe8\x00\x8d\xff\xeb\x00\x95\xff\x16\x00\x98\xff\x16\x00\xa9\xffV\x00\xaa\xffV\x00\xab\xffV\x00\xac\xffV\x00\xad\xffV\x00\xae\xffV\x00\xc3\xff\xde\x00\xc4\xff\xde\x00\xc5\xff\xde\x00\xc6\xff\xde\x00\xc7\xff\xde\x00\xc8\xff\xde\x00\xc9\xff\xeb\x00\xca\xff\xeb\x00\xcb\xff\xeb\x00\xcc\xff\xeb\x00\xcd\xff\xeb\x00\xd3\xff\xeb\x00\xd4\xff\xeb\x00\xd5\xff\xeb\x00\xd6\xff\xeb\x00\xd7\xff\xeb\x00\xd8\xff\xea\x00\xd9\xff\xea\x00\xda\xff\xea\x00\xdb\xff\xea\x00\xdc\xff\xe8\x00\xdd\xff\xe8\x00\x05\x008\xff\xd5\x00:\xff\xe4\x00;\xff\xec\x00=\xff\xdd\x00\xc2\xff\xdd\x00\x04\x008\xff\xb0\x00:\xff\xed\x00=\xff\xd0\x00\xc2\xff\xd0\x00\x06\x00.\xff\xee\x009\xff\xee\x00\xbe\xff\xee\x00\xbf\xff\xee\x00\xc0\xff\xee\x00\xc1\xff\xee\x00\x11\x00\x06\x00\x10\x00\v\x00\x10\x00G\xff\xe8\x00H\xff\xe8\x00I\xff\xe8\x00K\xff\xe8\x00U\xff\xe8\x00\x8d\xff\xe8\x00\x93\x00\x10\x00\x94\x00\x10\x00\x96\x00\x10\x00\x97\x00\x10\x00\xc9\xff\xe8\x00\xca\xff\xe8\x00\xcb\xff\xe8\x00\xcc\xff\xe8\x00\xcd\xff\xe8\x00\x01\x00\x14\x00\x04\x00\x00\x00\x05\x00\"\x00P\x00j\x00|\x00\x96\x00\x01\x00\x05\x00O\x00X\x00[\x00_\x00\x94\x00\v\x00G\xff\xec\x00H\xff\xec\x00I\xff\xec\x00K\xff\xec\x00U\xff\xec\x00\x8d\xff\xec\x00\xc9\xff\xec\x00\xca\xff\xec\x00\xcb\xff\xec\x00\xcc\xff\xec\x00\xcd\xff\xec\x00\x06\x00S\xff\xec\x00\xd3\xff\xec\x00\xd4\xff\xec\x00\xd5\xff\xec\x00\xd6\xff\xec\x00\xd7\xff\xec\x00\x04\x00\x10\xff\x84\x00\x12\xff\x84\x00\x95\xff\x84\x00\x98\xff\x84\x00\x06\x00.\xff\xec\x009\xff\xec\x00\xbe\xff\xec\x00\xbf\xff\xec\x00\xc0\xff\xec\x00\xc1\xff\xec\x00\n\x00L\x00 \x00O\x00 \x00P\x00 \x00S\xff\x80\x00W\xff\x90\x00\xd3\xff\x80\x00\xd4\xff\x80\x00\xd5\xff\x80\x00\xd6\xff\x80\x00\xd7\xff\x80\x00\x02\x05P\x00\x04\x00\x00\x05\xc6\a\b\x00\x1c\x00\x18\x00\x00\xff\xce\xff\xf5\xff\xef\xff\x88\xff\xf4\xff\xbb\xff\u007f\xff\xf5\x00\f\xff\xa9\xff\xa2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xe5\x00\x00\x00\x00\xff\xe8\xff\xc9\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xe3\x00\x00\x00\x00\x00\x00\xff\xe4\x00\x12\x00\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xe5\x00\x00\x00\x00\xff\xea\xff\xd5\xff\xeb\xff\xea\xff\x9a\xff\xe9\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xe3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xe6\x00\x00\x00\x00\x00\x00\xff\xed\x00\x00\x00\x14\xff\xef\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xed\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xb8\xff\xe4\x00\x00\x00\x00\xff\x9d\x00\x0f\x00\x10\xff\xa1\xff\xc4\x00\x10\x00\x10\xff\xb1\x00\x00\xff&\x00\x00\xff\x9d\xff\xb3\xff\x18\xff\x93\xff\xf0\xff\x8f\xff\x8c\xff\x10\x00\x00\xff\xd8\xff\xe1\x00\x00\x00\x00\xff\xe5\x00\x00\x00\x00\xff\xe9\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xe6\x00\x00\xff\xc0\xff\xe9\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff{\xff\xbf\xff\xca\xfe\xb0\x00\x00\xffq\xfe\xed\xff\xd4\x00\x00\xffQ\xff\x11\x00\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\x00\x00\x00\xff\xf3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xffv\xff\xe1\xfe\xbc\xff\xe6\xff\xf3\x00\x00\x00\x00\x00\x00\x00\x00\xff\xf5\x00\x00\xff8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xea\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xf5\xff\xf3\x00\x00\x00\x00\xff\xd2\x00\x00\x00\x00\xff\xe4\x00\x00\x00\x00\x00\x00\xff\xb5\x00\x00\xff\x1f\x00\x00\xff\xd4\x00\x00\xff\xdb\x00\x00\x00\x00\xff\xd2\x00\x00\x00\x00\x00\x00\xff\xe1\xff\xe7\x00\x00\x00\x00\xff\xeb\x00\x00\x00\x00\xff\xeb\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xe6\x00\x00\xff\xd2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xec\xff\xe3\xff\xa0\x00\x00\xff\xbf\x00\x11\x00\x11\xff\xd9\xff\xe2\x00\x12\x00\x12\xff\xa2\x00\r\xff-\x00\x00\xff\xbf\xff\xe9\xff\xcc\xff\xd8\xff\xf0\xff\xb7\xff\xc6\xff\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xe1\x00\x00\x00\x0e\xff\xed\x00\x00\x00\x00\x00\x00\xff\xd5\x00\x00\xff\x85\x00\x00\xff\xe1\x00\x00\xff\xc4\x00\x00\x00\x00\xff\xdf\x00\x00\x00\x00\x00\x00\xff\xe5\xff\xe6\x00\x00\x00\x00\xff\xeb\x00\x00\x00\x00\xff\xed\x00\x00\x00\x00\x00\x00\x00\r\x00\x00\x00\x00\x00\x00\xff\xeb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xf1\x00\x00\x00\x00\xff\xbd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xf5\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xf5\x00\x00\x00\x00\xff\xe3\x00\x00\x00\x00\x00\x00\x00\x00\xff\xf1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xf1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xf3\x00\x00\x00\x00\xff\xf2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x98\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xf1\x00\x00\x00\x00\xffx\x00\x00\x00\x00\x00\x00\x00\x00\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xeb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\xff\xf1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x95\x00\x00\xff\xf3\x00\x00\x00\x00\x00\x00\x00\x00\xff\xf1\x00\x00\x00\x00\x00\x00\x00\x12\x00\x00\x00\x00\x00\x10\xff\xec\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x85\x00\x00\xff\xed\x00\x00\x00\x00\x00\x00\x00\x00\xff\xd8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xec\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xec\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x95\xff\xc3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x88\x00\x00\x00\x00\x00\x00\xff\xc5\x00\x00\x00\x00\xff\xec\x00\x00\xff\xce\xff\xb0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xffV\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x13\x00\x06\x00\x06\x00\x00\x00\v\x00\v\x00\x01\x00\x10\x00\x10\x00\x02\x00\x12\x00\x12\x00\x03\x00%\x00)\x00\x04\x00,\x004\x00\t\x008\x00>\x00\x12\x00E\x00G\x00\x19\x00I\x00I\x00\x1c\x00L\x00L\x00\x1d\x00Q\x00T\x00\x1e\x00V\x00V\x00\"\x00Z\x00Z\x00#\x00\\\x00^\x00$\x00\x8a\x00\x8a\x00'\x00\x93\x00\x98\x00(\x00\xa8\x00\xcd\x00.\x00\xd2\x00\xd7\x00T\x00\xdc\x00\xdd\x00Z\x00\x02\x005\x00\x06\x00\x06\x00\x1a\x00\v\x00\v\x00\x1a\x00\x10\x00\x10\x00\x1b\x00\x12\x00\x12\x00\x1b\x00&\x00&\x00\x01\x00'\x00'\x00\x04\x00(\x00(\x00\x03\x00)\x00)\x00\x05\x00,\x00-\x00\x02\x00.\x00.\x00\n\x00/\x00/\x00\a\x000\x000\x00\b\x001\x002\x00\x02\x003\x003\x00\x03\x004\x004\x00\t\x008\x008\x00\x06\x009\x009\x00\n\x00:\x00:\x00\v\x00;\x00;\x00\x0e\x00<\x00<\x00\f\x00=\x00=\x00\r\x00>\x00>\x00\x0f\x00E\x00E\x00\x10\x00F\x00F\x00\x12\x00G\x00G\x00\x11\x00I\x00I\x00\x13\x00L\x00L\x00\x14\x00Q\x00R\x00\x14\x00S\x00S\x00\x15\x00T\x00T\x00\x12\x00V\x00V\x00\x17\x00Z\x00Z\x00\x16\x00\\\x00\\\x00\x18\x00]\x00]\x00\x16\x00^\x00^\x00\x19\x00\x8a\x00\x8a\x00\x12\x00\x93\x00\x94\x00\x1a\x00\x95\x00\x95\x00\x1b\x00\x96\x00\x97\x00\x1a\x00\x98\x00\x98\x00\x1b\x00\xa8\x00\xa8\x00\x03\x00\xaf\x00\xaf\x00\x04\x00\xb0\x00\xb3\x00\x05\x00\xb4\x00\xb8\x00\x02\x00\xb9\x00\xbd\x00\x03\x00\xbe\x00\xc1\x00\n\x00\xc2\x00\xc2\x00\r\x00\xc3\x00\xc8\x00\x10\x00\xc9\x00\xc9\x00\x11\x00\xca\x00\xcd\x00\x13\x00\xd2\x00\xd2\x00\x14\x00\xd3\x00\xd7\x00\x15\x00\xdc\x00\xdd\x00\x16\x00\x02\x004\x00\x06\x00\x06\x00\x04\x00\v\x00\v\x00\x04\x00\x10\x00\x10\x00\x0e\x00\x11\x00\x11\x00\x12\x00\x12\x00\x12\x00\x0e\x00%\x00%\x00\f\x00'\x00'\x00\x02\x00+\x00+\x00\x02\x00.\x00.\x00\x17\x003\x003\x00\x02\x005\x005\x00\x02\x007\x007\x00\x14\x008\x008\x00\a\x009\x009\x00\x03\x00:\x00:\x00\n\x00;\x00;\x00\x06\x00<\x00<\x00\r\x00=\x00=\x00\v\x00>\x00>\x00\x0f\x00E\x00E\x00\x15\x00G\x00I\x00\x10\x00K\x00K\x00\x10\x00Q\x00R\x00\x13\x00S\x00S\x00\x05\x00T\x00T\x00\x13\x00U\x00U\x00\x10\x00W\x00W\x00\x16\x00Y\x00Y\x00\b\x00Z\x00Z\x00\x01\x00\\\x00\\\x00\x11\x00]\x00]\x00\x01\x00^\x00^\x00\t\x00\x83\x00\x83\x00\x02\x00\x8c\x00\x8c\x00\x02\x00\x8d\x00\x8d\x00\x10\x00\x91\x00\x92\x00\x12\x00\x93\x00\x94\x00\x04\x00\x95\x00\x95\x00\x0e\x00\x96\x00\x97\x00\x04\x00\x98\x00\x98\x00\x0e\x00\xa7\x00\xa7\x00\x12\x00\xa9\x00\xae\x00\f\x00\xaf\x00\xaf\x00\x02\x00\xb9\x00\xbd\x00\x02\x00\xbe\x00\xc1\x00\x03\x00\xc2\x00\xc2\x00\v\x00\xc3\x00\xc8\x00\x15\x00\xc9\x00\xcd\x00\x10\x00\xd2\x00\xd2\x00\x13\x00\xd3\x00\xd7\x00\x05\x00\xd8\x00\xdb\x00\b\x00\xdc\x00\xdd\x00\x01\x00\x00\x00\x01\x00\x00\x00\n\x00,\x00H\x00\x01latn\x00\b\x00\n\x00\x01TUR \x00\x12\x00\x00\xff\xff\x00\x01\x00\x00\x00\x00\xff\xff\x00\x01\x00\x01\x00\x02liga\x00\x0eliga\x00\x16\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\x00\x01\x00\x02\x00\x06\x00 \x00\x04\x00\x00\x00\x01\x00\b\x00\x01\x00,\x00\x01\x00\b\x00\x01\x00\x04\x00\xa0\x00\x02\x00M\x00\x04\x00\x00\x00\x01\x00\b\x00\x01\x00\x12\x00\x01\x00\b\x00\x01\x00\x04\x00\xa1\x00\x02\x00P\x00\x01\x00\x01\x00J"), + } + file4 := &embedded.EmbeddedFile{ + Filename: "3d3a53586bd78d1069ae4b89a3b9aa98.svg", + FileModTime: time.Unix(1576651902, 0), + + Content: string("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"), + } + file5 := &embedded.EmbeddedFile{ + Filename: "674f50d287a8c48dc19ba404d20fe713.eot", + FileModTime: time.Unix(1576651902, 0), + + Content: string("n\x87\x02\x00\xac\x86\x02\x00\x01\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x90\x01\x00\x00\x00\x00LP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00Yxϐ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16\x00F\x00o\x00n\x00t\x00A\x00w\x00e\x00s\x00o\x00m\x00e\x00\x00\x00\x0e\x00R\x00e\x00g\x00u\x00l\x00a\x00r\x00\x00\x00$\x00V\x00e\x00r\x00s\x00i\x00o\x00n\x00 \x004\x00.\x007\x00.\x000\x00 \x002\x000\x001\x006\x00\x00\x00\x16\x00F\x00o\x00n\x00t\x00A\x00w\x00e\x00s\x00o\x00m\x00e\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\r\x00\x80\x00\x03\x00PFFTMk\xbeG\xb9\x00\x02\x86\x90\x00\x00\x00\x1cGDEF\x02\xf0\x00\x04\x00\x02\x86p\x00\x00\x00 OS/2\x882z@\x00\x00\x01X\x00\x00\x00`cmap\n\xbf:\u007f\x00\x00\f\xa8\x00\x00\x02\xf2gasp\xff\xff\x00\x03\x00\x02\x86h\x00\x00\x00\bglyf\x8f\xf7\xaeM\x00\x00\x1a\xac\x00\x02L\xbchead\x10\x89\xe5-\x00\x00\x00\xdc\x00\x00\x006hhea\x0f\x03\n\xb5\x00\x00\x01\x14\x00\x00\x00$hmtxEy\x18\x85\x00\x00\x01\xb8\x00\x00\n\xf0loca\x02\xf5\xa2\\\x00\x00\x0f\x9c\x00\x00\v\x10maxp\x03,\x02\x1c\x00\x00\x018\x00\x00\x00 name㗋\xac\x00\x02gh\x00\x00\x04\x86post\xaf\x8f\x9b\xa1\x00\x02k\xf0\x00\x00\x1au\x00\x01\x00\x00\x00\x04\x01ː\xcfxY_\x0f<\xf5\x00\v\a\x00\x00\x00\x00\x00\xd43\xcd2\x00\x00\x00\x00\xd43\xcd2\xff\xff\xff\x00\t\x01\x06\x00\x00\x00\x00\b\x00\x02\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x06\x00\xff\x00\x00\x00\t\x00\xff\xff\xff\xff\t\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xb5\x00\x01\x00\x00\x02\xc3\x02\x19\x00'\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x01\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x00\x03\x06i\x01\x90\x00\x05\x00\x00\x04\x8c\x043\x00\x00\x00\x86\x04\x8c\x043\x00\x00\x02s\x00\x00\x01\x8a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pyrs\x00@\x00 \xf5\x00\x06\x00\xff\x00\x00\x00\x06\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x01\x03\x80\x00p\x00\x00\x00\x00\x02U\x00\x00\x01\xc0\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00]\x06\x00\x00\x00\x06\x80\x00\x00\a\x00\x00\x00\a\x00\x00\x00\x06\x80\x00\x00\x06\x80\x00\x00\x05\x00\x00\x00\a\x80\x00\x00\x06\x80\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00y\x05\x80\x00n\x06\x80\x00\x00\x06\x80\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x05\x80\x00\x00\x06\x80\x00\x1a\x06\x00\x00\x00\x06\x00\x00\x00\a\x80\x002\x06\x80\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\x04\x80\x00\x00\a\x00\x00@\x06\x80\x00\x00\x03\x00\x00\x00\x04\x80\x00\x00\x06\x80\x00\x00\x05\x80\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\a\x80\x00\x00\x06\x80\x00\n\x05\x00\x00\x00\x06\x80\x00\x00\a\x80\x00\x00\x06\x80\x00\x00\x05\x80\x00\x00\x04\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x80\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\a\x00\x00\x00\x06\x80\x00\x00\x06\x80\x00\x00\a\x00\x00\x00\x04\x00\x00\x00\a\x00\x00\x00\x06\x80\x00z\x05\x80\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x80\x00\x00\a\x00\x00\x00\x04\x00\x00\x00\x06\x02\x00\x01\x05\x00\x00\x9a\x05\x00\x00Z\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00@\x06\x00\x00\x00\x06\x80\x005\x06\x80\x005\a\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\r\x05\x80\x00\x00\x05\x80\x00\x00\x06\x80\x00z\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\x05\x80\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x10\x05\x80\x00\x00\x06\x80\x00\x00\a\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\a\x00\x00Z\a\x00\x00Z\a\x80\x00\x00\x06\x80\x00\x00\x06\x80\x00\x00\a\x80\x00\x00\x03\x00\x00@\a\x00\x00\x00\b\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x80\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x03\x80\x00\x00\a\x00\x00\x00\x06\x80\x00\x00\x06\x00\x00\x00\x04\x80\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x06\x80\x00\x00\x06\x00\x00\x00\x06\x80\x00\x00\x06\x00\x00\x00\x05\x80\x00\x00\x05\x80\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\x06\x80\x00,\x04\x00\x00_\x06\x00\x00\x00\x06\x80\x00\x00\a\x80\x00\x00\x05\x80\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\a\x00\x00@\x06\x00\x00\x02\a\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x80\x00\x15\a\x00\x00\x00\x05\x80\x00\x05\a\x00\x00\x00\x06\x00\x00\x00\a\x80\x00\x00\x06\x80\x00\x10\a\x80\x00\x00\x06\x80\x00s\a\x00\x00\x01\a\x00\x00\x00\x05\x80\x00\x04\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x0f\a\x00\x00\x00\x06\x00\x00\x00\x06\x80\x00\x00\x06\x80\x00\x1b\a\x00\x00@\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\t\x00\x00\x00\a\x80\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x02\x80\x00@\x02\x80\x00\x00\x06\x80\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00(\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\x03\x80\x00\x01\a\x00\x00\x00\x06\x80\x00\x00\a\x00\x00\x00\x04\x00\x00\x00\a\x00\x00\x00\a\x80\x00\x00\a\x80\x00\x00\x05\x80\x00\x00\x05\x80\x00\x00\a\x00\x00\x00\a\x00\x00@\a\x80\x00\x00\x05\x80\x00\x00\x06\x00\x00\x00\x05\x80\x00\x00\x05\x80\x00\x00\a\x80\x00@\a\x00\x00\x00\a\x80\x00\x00\x06\x80\x00@\x06\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00-\x04\x00\x00\r\x04\x80\x00M\x04\x80\x00M\x02\x80\x00-\x02\x80\x00\r\x04\x80\x00M\x04\x80\x00M\a\x80\x00\x00\a\x80\x00\x00\x04\x80\x00\x00\x03\x00\x00\x00\x06\x00\x00\x00\x06\x80\x00\x00\x06\x80\x00\x00\a\x00\x00@\x06\x00\x00\x00\a\x00\x00\x00\x06\x80\x00\x00\x06\x80\x00\x00\a\x80\x00\x00\a\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x80\x00\x00\a\x80\x00\x00\a\x00\x00@\a\x00\x00@\x06\x80\x00\r\a\x80\x00-\a\x00\x00\x00\x06\x80\x00\x02\x05\x80\x00\x02\x06\x80\x00\x00\x04\x00\x00\x00\x06\x80\x00\x00\x04\x00\x00`\x02\x80\x00\x00\x02\x80\x00b\x06\x00\x00\x05\x06\x00\x00\x05\a\x80\x00\x01\x06\x80\x00\x00\x04\x80\x00\x00\x05\x80\x00\r\x05\x00\x00\x00\x06\x80\x00\x00\x05\x80\x00\x03\x06\x80\x00$\a\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x05\x80\x00\x00\a\x00\x00\f\a\x00\x00\x00\x04\x80\x00\x00\x06\x00\x00\x00\x05\x80\x00\x00\x01\x80\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x006\x06\x00\x00\x00\x05\x80\x00\x00\x04\x00\x00\x03\x04\x00\x00\x03\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x04\x00\x004\x03\x82\x00\x00\x04\x03\x00\x04\x05\x00\x00\x00\a\x00\x00\x00\x05\x00\x008\x06\x00\x00\x00\x06\x00\x00\x00\x06\x80\x00\"\x06\x80\x00\"\a\x00\x00\"\a\x00\x00\"\x06\x00\x00\"\x06\x00\x00\"\x06\x80\x00\x00\x06\x80\x00\x00\x06\x00\x00\x00\x06\x00\x00\x1b\x05\x80\x00\x05\x06\x00\x00\x00\a\x00\x00\x00\a\x00\x00@\x06\x00\x00\v\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x05\x80\x00\x00\x06\x00\x00\x00\x04\x00\x00D\x06\x00\x00\x00\x03\x00\x00\x03\x03\x00\x00\x03\a\x00\x00@\a\x00\x00\x00\x05\x80\x00\x00\x06\x80\x00\x00\x05\x80\x00\x00\x06\x00\x00\v\x06\x00\x00\x00\x06\x00\x00\x00\x05\x00\x00,\x06\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\x06\x00\x00\x00\a\x00\x00,\x06\x00\x00\x00\a\x00\x00@\x06\x80\x00 \a\x80\xff\xff\a\x00\x00\x00\x06\x00\x00\x00\x05\x80\x00\x00\x05\x00\x00\x15\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x80\x00\x00\x06\x00\x00\x00\x04\x80\x00\x00\x05\x80\x00\x00\b\x80\x00\x00\x06\x80\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\b\x00\x00\x00\t\x00\x00\x00\x06\x00\x00m\x06\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x80\x00\x00\x06\x00\x00\x00\b\x00\x00\x00\x06\x00\x00\x00\a\xf6\x00)\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x05\x00\x00@\x06\x80\x00\x00\x03\x00\x00@\a\x00\x00\x00\t\x00\x00\x00\b\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x10\b\x00\x00\x00\b\x00\x00\x00\x06\x00\x00 \x06\x00\x00\x00\x04\x00\x00\x00\t\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00'\a\x00\x00\x00\b\x00\x00\x00\a\x00\x00\x00\a\x00\x00 \a\x00\x00\x13\a\x00\x00\x00\x06\x00\x00\x00\a\x00\x00D\x06\x00\x00\x00\x05\x00\x009\a\x00\x00\x12\b\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00>\x05\x00\x00\x18\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x19\a\x00\x00d\x06\x00\x00Y\b\x00\x00\x00\b\x00\x00*\a\x00\x00\x00\x06\x00\x00\t\a\x00\x00'\t\x00\x00\x00\t\x00\x00\x00\t\x00\x00\x00\t\x00\x00\x00\t\x00\x00\x00\t\x00\x00\x00\b\x00\x00\x0e\b\x00\x00\x0e\x05\x80\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\b\x00\x00\x00\a\x00\x00\x00\b\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\b\x00\x00\x00\b\x00\x00\x00\t\x00\x00\x00\x06\x00\x00\x00\b\x00\x00\x00\x05\x00\x00\v\b\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\b\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\b\x00\x00\x00\b\x00\x00\x00\x06\x00\x00\x00\b\x00\x00\x00\b\x00\x00\x00\x06\x80\x00\x00\x06\x80\x00\x00\b\x00\x00\x00\b\x00\x00\x13\x06\x00\x00\x00\t\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\x05\x00\x00\x02\x06\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x02\a\x00\x00\x00\a\x00\x00\x02\a\x80\x00\x01\b\x00\x00\x06\x06\x00\x00\x00\x05\x00\x00\x02\b\x00\x00\x04\x05\x00\x00\x00\x05\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\b\x00\x00\x00\b\x00\x00\x00\b\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\b\xf8\x00T\t\x00\x00\x00\a\x00\x00\x00\t\x00\x00\x00\t\x00\x00\x00\t\x00\x00\x00\t\x00\x00\x00\t\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\b\x00\x00\x00\t\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\t\x00\x00\x00\t\x00\x00\x00\a\x00\x00\x00\t\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\b\x00\x00\x00\b\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\a\xb5\x00\x00\a\x00\x00\x00\a\x00\x00\x00\b\x00\x00@\a\x00\x00\x00\t\x00\x00\x00\x05\x00\x00f\x06\x00\x00\x00\x06\xb8\x00\x00\t\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x02\a\x00\x00\x00\a\x00\x00\x00\b\x00\x00\x00\a\x00\x00\x16\x06\x00\x00\x0e\a\x00\x00\x1d\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\x04\x00\x00\x00\a\x00\x00%\b\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\x04\x00\x00\x00\a\x00\x00R\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\a\x00\x00E\t\x00\x00\x00\a\x00\x00\x00\a\x00\x00 \a\x00\x00\x00\t\x00\x00\x00\a\x00\x00\x00\t\x00\x00\x00\x06\x00\x00$\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\b\x00\x00\x00\a\x00\x00!\x06\x00\x00k\x04\x00\x00(\x06\x00\x00\x00\a\x00\x00\x03\a\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\x06\x00\x00D\x06\x00\x00\x00\x05\x80\x00'\t\x00\x00\x03\x05\x80\x00\x00\b\x80\x00\x00\a\x00\x00\x00\t\x00\x00\x03\a\x00\x00\x00\x06\x00\x00\x00\x05\xff\x00%\x06\x80\x00\x01\a\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x80\x00\x0f\x06\x00\x00\x00\t\x00\x00\x00\x06\x00\x00\x00\x06\x80\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00%\t\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x15\x06\x80\x00\x00\x06\x80\x00\x00\b\x00\x00\x00\b\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x05\x00\x00\x00\b\x00\x00\x00\b\x00\x00\x00\a\x00\x00\x1d\t\x00\x00\x00\a\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\a\x80\x00\x00\a\x00\x00\x00\x06\x00\x00\x01\a\x00\x00\x00\a\x00\x00\x00\b\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x02\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\b\x80\x000\a\x00\x00%\x06\x00\x00\x00\x06\x80\x00/\a\x00\x00\x00\a\x00\x00\x00\a\x80\x00&\a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00\x1c\x00\x01\x00\x00\x00\x00\x01\xec\x00\x03\x00\x01\x00\x00\x00\x1c\x00\x04\x01\xd0\x00\x00\x00p\x00@\x00\x05\x000\x00 \x00\xa9\x00\xae\x00\xb4\x00\xc6\x00\xd8!\"\"\x1e\"`\xf0\x0e\xf0\x1e\xf0>\xf0N\xf0^\xf0n\xf0~\xf0\x8e\xf0\x9e\xf0\xae\xf0\xb2\xf0\xce\xf0\xde\xf0\xee\xf0\xfe\xf1\x0e\xf1\x1e\xf1.\xf1>\xf1N\xf1^\xf1n\xf1~\xf1\x8e\xf1\x9e\xf1\xae\xf1\xbe\xf1\xce\xf1\xde\xf1\xee\xf1\xfe\xf2\x0e\xf2\x1e\xf2>\xf2N\xf2^\xf2n\xf2~\xf2\x8e\xf2\x9e\xf2\xae\xf2\xbe\xf2\xce\xf2\xde\xf2\xee\xf5\x00\xff\xff\x00\x00\x00 \x00\xa8\x00\xae\x00\xb4\x00\xc6\x00\xd8!\"\"\x1e\"`\xf0\x00\xf0\x10\xf0!\xf0@\xf0P\xf0`\xf0p\xf0\x80\xf0\x90\xf0\xa0\xf0\xb0\xf0\xc0\xf0\xd0\xf0\xe0\xf0\xf0\xf1\x00\xf1\x10\xf1 \xf10\xf1@\xf1P\xf1`\xf1p\xf1\x80\xf1\x90\xf1\xa0\xf1\xb0\xf1\xc0\xf1\xd0\xf1\xe0\xf1\xf0\xf2\x00\xf2\x10\xf2!\xf2@\xf2P\xf2`\xf2p\xf2\x80\xf2\x90\xf2\xa0\xf2\xb0\xf2\xc0\xf2\xd0\xf2\xe0\xf5\x00\xff\xff\xff\xe3\xff\\\xffX\xffS\xffB\xff1\xde\xe8\xdd\xedݬ\x10\r\x10\f\x10\n\x10\t\x10\b\x10\a\x10\x06\x10\x05\x10\x04\x10\x03\x10\x02\x0f\xf5\x0f\xf4\x0f\xf3\x0f\xf2\x0f\xf1\x0f\xf0\x0f\xef\x0f\xee\x0f\xed\x0f\xec\x0f\xeb\x0f\xea\x0f\xe9\x0f\xe8\x0f\xe7\x0f\xe6\x0f\xe5\x0f\xe4\x0f\xe3\x0f\xe2\x0f\xe1\x0f\xe0\x0f\xde\x0f\xdd\x0f\xdc\x0f\xdb\x0f\xda\x0f\xd9\x0f\xd8\x0f\xd7\x0f\xd6\x0f\xd5\x0f\xd4\x0f\xd3\r\xc2\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x06\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x05\n\a\x04\f\b\t\v\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,\x00\x00\x00,\x00\x00\x00,\x00\x00\x00,\x00\x00\x00,\x00\x00\x00,\x00\x00\x00,\x00\x00\x00,\x00\x00\x00,\x00\x00\x00,\x00\x00\x00,\x00\x00\x00,\x00\x00\x00,\x00\x00\x00\x90\x00\x00\x01\x14\x00\x00\x01\x98\x00\x00\x02t\x00\x00\x02\xd0\x00\x00\x03L\x00\x00\x03\xf0\x00\x00\x04T\x00\x00\x06$\x00\x00\x06\xe0\x00\x00\bl\x00\x00\tx\x00\x00\t\xd0\x00\x00\nT\x00\x00\v(\x00\x00\v\xd4\x00\x00\f\x84\x00\x00\rd\x00\x00\x0e\xa8\x00\x00\x0f\xd4\x00\x00\x10\x84\x00\x00\x11\x00\x00\x00\x11\x9c\x00\x00\x12l\x00\x00\x13,\x00\x00\x13\xd8\x00\x00\x14\x80\x00\x00\x14\xfc\x00\x00\x15\x90\x00\x00\x164\x00\x00\x17\x10\x00\x00\x18d\x00\x00\x18\xcc\x00\x00\x19p\x00\x00\x1aH\x00\x00\x1a\x94\x00\x00\x1b$\x00\x00\x1cd\x00\x00\x1d,\x00\x00\x1e\b\x00\x00\x1et\x00\x00\x1f(\x00\x00 \x8c\x00\x00 \xf0\x00\x00!\xa0\x00\x00\"0\x00\x00# \x00\x00$,\x00\x00$\xe0\x00\x00&D\x00\x00'\xe4\x00\x00(\x9c\x00\x00)T\x00\x00*\b\x00\x00*\xbc\x00\x00,\x10\x00\x00,\xf4\x00\x00-\xd8\x00\x00.@\x00\x00.\xd8\x00\x00/`\x00\x00/\xbc\x00\x000\x14\x00\x000\xa4\x00\x001\x94\x00\x002\x90\x00\x003d\x00\x0044\x00\x004\x94\x00\x005 \x00\x005\x80\x00\x005\xb8\x00\x006 \x00\x006\\\x00\x006\xbc\x00\x007H\x00\x007\xa8\x00\x008\f\x00\x008`\x00\x008\xb4\x00\x009L\x00\x009\xb4\x00\x00:h\x00\x00:\xec\x00\x00;\xc0\x00\x00<\x00\x00>\xe4\x00\x00?h\x00\x00?\xd8\x00\x00@H\x00\x00@\xbc\x00\x00A0\x00\x00A\xb8\x00\x00BX\x00\x00B\xf8\x00\x00Cd\x00\x00C\x9c\x00\x00DL\x00\x00D\xe4\x00\x00E\xb8\x00\x00F\x9c\x00\x00G0\x00\x00G\xdc\x00\x00H\xec\x00\x00I\x8c\x00\x00J8\x00\x00K\xac\x00\x00L\xe4\x00\x00Md\x00\x00N,\x00\x00N\x80\x00\x00N\xd4\x00\x00O\xb0\x00\x00P`\x00\x00P\xa8\x00\x00Q4\x00\x00Q\xa0\x00\x00R\f\x00\x00Rl\x00\x00S,\x00\x00S\x98\x00\x00T`\x00\x00U0\x00\x00W\xf0\x00\x00X\xdc\x00\x00Z\b\x00\x00[@\x00\x00[\x8c\x00\x00\\<\x00\x00\\\xf8\x00\x00]\x98\x00\x00^(\x00\x00^\xe4\x00\x00_\xa0\x00\x00`p\x00\x00b,\x00\x00b\xf4\x00\x00d\x04\x00\x00d\xec\x00\x00eP\x00\x00e\xd0\x00\x00f\xc4\x00\x00g`\x00\x00g\xa8\x00\x00iL\x00\x00i\xc0\x00\x00jD\x00\x00k\f\x00\x00k\xd4\x00\x00l\x80\x00\x00m@\x00\x00n,\x00\x00oL\x00\x00p\x84\x00\x00q\xa4\x00\x00r\xdc\x00\x00sx\x00\x00t\x10\x00\x00t\xa8\x00\x00uD\x00\x00{`\x00\x00|\x00\x00\x00|\xbc\x00\x00}\x10\x00\x00}\xa4\x00\x00~\x88\x00\x00\u007f\x94\x00\x00\x80\xbc\x00\x00\x81\x18\x00\x00\x81\x8c\x00\x00\x83H\x00\x00\x84\x14\x00\x00\x84\xd4\x00\x00\x85\xa8\x00\x00\x85\xe4\x00\x00\x86l\x00\x00\x87@\x00\x00\x88\x98\x00\x00\x89\xc0\x00\x00\x8b\x10\x00\x00\x8c\xc8\x00\x00\x8d\x8c\x00\x00\x8el\x00\x00\x8fH\x00\x00\x90 \x00\x00\x90\xc0\x00\x00\x91T\x00\x00\x92\f\x00\x00\x92H\x00\x00\x92\x84\x00\x00\x92\xc0\x00\x00\x92\xfc\x00\x00\x93`\x00\x00\x93\xc8\x00\x00\x94\x04\x00\x00\x94@\x00\x00\x94\xf0\x00\x00\x95\x80\x00\x00\x96$\x00\x00\x97\\\x00\x00\x98X\x00\x00\x99\x1c\x00\x00\x9aD\x00\x00\x9a\xb8\x00\x00\x9b\x98\x00\x00\x9c\xa0\x00\x00\x9dT\x00\x00\x9eX\x00\x00\x9e\xf8\x00\x00\x9f\x9c\x00\x00\xa0D\x00\x00\xa1P\x00\x00\xa2,\x00\x00\xa2\xa4\x00\x00\xa38\x00\x00\xa3\xa8\x00\x00\xa4d\x00\x00\xa5\\\x00\x00\xa8\x90\x00\x00\xab\b\x00\x00\xac\x1c\x00\x00\xac\xec\x00\x00\xad\x90\x00\x00\xad\xe8\x00\x00\xae\x80\x00\x00\xaf\x18\x00\x00\xaf\xb0\x00\x00\xb0H\x00\x00\xb0\xe0\x00\x00\xb1x\x00\x00\xb1\xcc\x00\x00\xb2 \x00\x00\xb2t\x00\x00\xb2\xc8\x00\x00\xb3X\x00\x00\xb3\xf4\x00\x00\xb4p\x00\x00\xb5\x00\x00\x00\xb5d\x00\x00\xb6\x1c\x00\x00\xb6\xd4\x00\x00\xb7\xb4\x00\x00\xb7\xf0\x00\x00\xb8x\x00\x00\xb9t\x00\x00\xb9\xf8\x00\x00\xba\xcc\x00\x00\xba\xcc\x00\x00\xba\xcc\x00\x00\xbb\xa8\x00\x00\xbc\x84\x00\x00\xbd@\x00\x00\xbe\x04\x00\x00\xbf\xc8\x00\x00\xc0\xc4\x00\x00\xc2\f\x00\x00\u008c\x00\x00\xc3\\\x00\x00\xc4 \x00\x00ļ\x00\x00\xc5\x10\x00\x00Ÿ\x00\x00Ɣ\x00\x00\xc80\x00\x00\xc8\xe0\x00\x00\xc9d\x00\x00\xc9\xcc\x00\x00ʨ\x00\x00ˀ\x00\x00\xcb\xe0\x00\x00\xcc\xf4\x00\x00͔\x00\x00\xcex\x00\x00\xce\xe8\x00\x00ϰ\x00\x00Ќ\x00\x00\xd1,\x00\x00ш\x00\x00\xd2\b\x00\x00҈\x00\x00\xd3\f\x00\x00ӌ\x00\x00\xd3\xec\x00\x00\xd48\x00\x00\xd5,\x00\x00՜\x00\x00\xd6`\x00\x00\xd6\xe8\x00\x00\xd7l\x00\x00\xd8H\x00\x00ش\x00\x00\xd9`\x00\x00\xd9\xc4\x00\x00\xdaT\x00\x00ڸ\x00\x00\xdb\x18\x00\x00۔\x00\x00\xdc@\x00\x00\xdc\xc8\x00\x00\xddl\x00\x00\xdd\xf0\x00\x00ބ\x00\x00\xdf\x18\x00\x00߬\x00\x00\xe0\xbc\x00\x00\xe1l\x00\x00\xe2p\x00\x00\xe3 \x00\x00\xe3\xe4\x00\x00\xe4\x80\x00\x00\xe5\xc8\x00\x00\xe6\xc0\x00\x00\xe7\x18\x00\x00\xe7\xec\x00\x00\xe8\xe4\x00\x00\xe9\xd8\x00\x00\xea\xd8\x00\x00\xeb\xd8\x00\x00\xec\xd4\x00\x00\xed\xd0\x00\x00\xee\xdc\x00\x00\xef\xe4\x00\x00\xf2\x04\x00\x00\xf3\xf4\x00\x00\xf4\x80\x00\x00\xf54\x00\x00\xf6\x10\x00\x00\xf6\x9c\x00\x00\xf7\x18\x00\x00\xf8X\x00\x00\xf8\xc0\x00\x00\xf9$\x00\x00\xfal\x00\x00\xfb\xbc\x00\x00\xfc(\x00\x00\xfc\xb8\x00\x00\xfd\f\x00\x00\xfd`\x00\x00\xfd\xb4\x00\x00\xfe\b\x00\x00\xfe\xb8\x00\x00\xff\b\x00\x01\x00\x14\x00\x01\x05\xb4\x00\x01\x06\xf4\x00\x01\a\xf8\x00\x01\b\xd0\x00\x01\td\x00\x01\n\x10\x00\x01\n\x98\x00\x01\v\x18\x00\x01\f\x04\x00\x01\f\xa4\x00\x01\r,\x00\x01\x0e\x00\x00\x01\x0f\x88\x00\x01\x11,\x00\x01\x11\xa0\x00\x01\x12\xcc\x00\x01\x138\x00\x01\x13\xe4\x00\x01\x14\x90\x00\x01\x15(\x00\x01\x15\xa4\x00\x01\x16X\x00\x01\x16\xfc\x00\x01\x17\xc0\x00\x01\x18\x84\x00\x01\x19x\x00\x01\x1a|\x00\x01\x1bT\x00\x01\x1c\xd4\x00\x01\x1d@\x00\x01\x1d\xd4\x00\x01\x1e\x90\x00\x01\x1f\x04\x00\x01\x1f|\x00\x01 \xa4\x00\x01!\xc0\x00\x01\"x\x00\x01#\b\x00\x01#l\x00\x01$\x04\x00\x01$\xcc\x00\x01'h\x00\x01(\xe8\x00\x01*L\x00\x01,T\x00\x01.L\x00\x011t\x00\x011\xf4\x00\x012\xe0\x00\x0130\x00\x013\xb0\x00\x014\xa8\x00\x015t\x00\x016T\x00\x017$\x00\x018\f\x00\x019H\x00\x01:\x10\x00\x01:\xf0\x00\x01;\x90\x00\x01<\x84\x00\x01<\xd8\x00\x01?X\x00\x01@\x1c\x00\x01A\xc0\x00\x01B\xc8\x00\x01C\xc8\x00\x01D\x9c\x00\x01EH\x00\x01FH\x00\x01Gp\x00\x01HH\x00\x01Ix\x00\x01J \x00\x01J\xe4\x00\x01K\xd4\x00\x01L\xa0\x00\x01M\x18\x00\x01N@\x00\x01P@\x00\x01Q\xa0\x00\x01R\xe0\x00\x01SD\x00\x01T \x00\x01UL\x00\x01V`\x00\x01V\xd4\x00\x01WX\x00\x01X4\x00\x01X\xa0\x00\x01Z\x04\x00\x01Z\x88\x00\x01[d\x00\x01[\xe0\x00\x01\\|\x00\x01]\xd8\x00\x01^\xa0\x00\x01`\x94\x00\x01aH\x00\x01a\xbc\x00\x01b\xf0\x00\x01cX\x00\x01d\xac\x00\x01et\x00\x01fh\x00\x01g\xdc\x00\x01h\xb4\x00\x01i\\\x00\x01jx\x00\x01n\x84\x00\x01p@\x00\x01s\xe0\x00\x01v\x10\x00\x01w\xc8\x00\x01x\x90\x00\x01y\x88\x00\x01z\x8c\x00\x01{h\x00\x01|\x8c\x00\x01}\x1c\x00\x01}\xa4\x00\x01\u007f\\\x00\x01\u007f\x98\x00\x01\u007f\xf8\x00\x01\x80l\x00\x01\x81t\x00\x01\x82\x90\x00\x01\x834\x00\x01\x83\xa4\x00\x01\x84\xc8\x00\x01\x85\xb0\x00\x01\x86\xa4\x00\x01\x88t\x00\x01\x89\x8c\x00\x01\x8a8\x00\x01\x8b8\x00\x01\x8b\xa0\x00\x01\x8eL\x00\x01\x8e\xa8\x00\x01\x8fT\x00\x01\x90\x10\x00\x01\x91\x14\x00\x01\x93\x90\x00\x01\x94\x14\x00\x01\x95\x04\x00\x01\x95\xfc\x00\x01\x96\xf8\x00\x01\x97\xa0\x00\x01\x99|\x00\x01\x9a\xc8\x00\x01\x9c\x10\x00\x01\x9d\b\x00\x01\x9d\xd8\x00\x01\x9e|\x00\x01\x9f\x18\x00\x01\x9f\xe8\x00\x01\xa0\xc4\x00\x01\xa2\f\x00\x01\xa34\x00\x01\xa4x\x00\x01\xa5\xb0\x00\x01\xa6\x80\x00\x01\xa7L\x00\x01\xa8\x1c\x00\x01\xa8\x90\x00\x01\xa8\xec\x00\x01\xa8\xec\x00\x01\xa8\xec\x00\x01\xa9X\x00\x01\xaa(\x00\x01\xab \x00\x01\xab\xcc\x00\x01\xac\xac\x00\x01\xad\xa8\x00\x01\xae \x00\x01\xae\x88\x00\x01\xaf\x04\x00\x01\xaf\xa8\x00\x01\xb0@\x00\x01\xb0\x88\x00\x01\xb6\xbc\x00\x01\xb7l\x00\x01\xb8\xe0\x00\x01\xb9t\x00\x01\xba\x04\x00\x01\xba\x94\x00\x01\xbb$\x00\x01\xbb\xa4\x00\x01\xbc\b\x00\x01\xbcx\x00\x01\xbdL\x00\x01\xbeL\x00\x01\xbe\xa4\x00\x01\xbf \x00\x01\xc0H\x00\x01\xc1\x18\x00\x01\xc1\xc4\x00\x01\xc3\x04\x00\x01\xc3\xe4\x00\x01Ġ\x00\x01\xc5T\x00\x01\xc6(\x00\x01\xc6\xec\x00\x01\xc8\f\x00\x01\xc9\f\x00\x01ʈ\x00\x01ˠ\x00\x01\xcc\xf8\x00\x01\xce\x1c\x00\x01ϔ\x00\x01\xd0l\x00\x01\xd1d\x00\x01\xd2\xdc\x00\x01\xd3P\x00\x01\xd3\xf8\x00\x01Մ\x00\x01\xd6x\x00\x01\xd7p\x00\x01\xd7\xfc\x00\x01\xd8\xf4\x00\x01ڬ\x00\x01\xdbT\x00\x01\xdcT\x00\x01\xdd\f\x00\x01\xdd\xf0\x00\x01ވ\x00\x01\xdfL\x00\x01\xe1\x80\x00\x01\xe2\xf8\x00\x01\xe4\x18\x00\x01\xe5\f\x00\x01\xe6<\x00\x01\xe7H\x00\x01\xe7\xa8\x00\x01\xe8$\x00\x01\xe8\xd4\x00\x01\xe9l\x00\x01\xea\x1c\x00\x01\xea\xd4\x00\x01\xeb\xe4\x00\x01\xec4\x00\x01\xec\xb8\x00\x01\xec\xf4\x00\x01\xed\xf0\x00\x01\xef\b\x00\x01\xef\xa4\x00\x01\xf0\x04\x00\x01\xf0\xcc\x00\x01\xf1 \x00\x01\xf2P\x00\x01\xf3l\x00\x01\xf3\xe8\x00\x01\xf5\f\x00\x01\xf6,\x00\x01\xf6\xc0\x00\x01\xf7x\x00\x01\xf7\xe0\x00\x01\xf8p\x00\x01\xf9,\x00\x01\xfax\x00\x01\xfbt\x00\x01\xfc\f\x00\x01\xfcd\x00\x01\xfd\f\x00\x01\xfd\x8c\x00\x01\xfe4\x00\x01\xff\b\x00\x01\xff\xd0\x00\x02\x014\x00\x02\x02\x1c\x00\x02\x03,\x00\x02\x04h\x00\x02\x05\xd4\x00\x02\aP\x00\x02\t4\x00\x02\n\xd4\x00\x02\f\xe0\x00\x02\r\xf0\x00\x02\x0f\x18\x00\x02\x104\x00\x02\x11\xe4\x00\x02\x13<\x00\x02\x14,\x00\x02\x15,\x00\x02\x164\x00\x02\x170\x00\x02\x188\x00\x02\x19$\x00\x02\x1a\x88\x00\x02\x1b8\x00\x02\x1d\xb4\x00\x02\x1eT\x00\x02\x1e\xcc\x00\x02 |\x00\x02!h\x00\x02\"\xac\x00\x02$L\x00\x02%0\x00\x02&H\x00\x02'\x88\x00\x02(\xf4\x00\x02)\x8c\x00\x02*0\x00\x02*\xdc\x00\x02+\x94\x00\x02,\xdc\x00\x02.$\x00\x02.\xec\x00\x020\xec\x00\x021\x84\x00\x022@\x00\x022\xfc\x00\x023\xb8\x00\x024t\x00\x025$\x00\x026\xf4\x00\x029 \x00\x02:\x8c\x00\x02:\xd4\x00\x02;\f\x00\x02;\x88\x00\x02<(\x00\x02<\xd8\x00\x02=4\x00\x02?\xb8\x00\x02@\x98\x00\x02A\xe0\x00\x02C\xa0\x00\x02D\xfc\x00\x02F\x98\x00\x02H`\x00\x02H\xf4\x00\x02I\xcc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02\x00p\x00\x00\x03\x10\x06\x00\x00\x03\x00\a\x00\x007!\x11!\x03\x11!\x11\xe0\x01\xc0\xfe@p\x02\xa0p\x05 \xfap\x06\x00\xfa\x00\x00\x00\x00\x00\x01\x00]\xff\x00\x06\xa3\x05\x80\x00\x1d\x00\x00\x01\x14\a\x01\x11!2\x16\x14\x06#!\"&463!\x11\x01&54>\x013!2\x1e\x01\x06\xa3+\xfd\x88\x01@\x1a&&\x1a\xfc\x80\x1a&&\x1a\x01@\xfd\x88+$(\x17\x05\x80\x17($\x05F#+\xfd\x88\xfd\x00&4&&4&\x03\x00\x02x+#\x17\x1b\b\b\x1b\x00\x00\x01\x00\x00\xff\x00\x06\x00\x05\x80\x00+\x00\x00\x01\x11\x14\x0e\x02\".\x024>\x0232\x17\x11\x05\x11\x14\x0e\x02\".\x024>\x0232\x17\x11467\x01632\x16\x06\x00DhgZghDDhg-iW\xfd\x00DhgZghDDhg-iW&\x1e\x03@\f\x10(8\x05 \xfb\xa02N+\x15\x15+NdN+\x15'\x02\x19\xed\xfd;2N+\x15\x15+NdN+\x15'\x03\xc7\x1f3\n\x01\x00\x048\x00\x02\x00\x00\xff\x00\x06\x80\x05\x80\x00\a\x00!\x00\x00\x00\x10\x00 \x00\x10\x00 \x01\x14\x06#\"'\x01\x06#\"$&\x02\x10\x126$ \x04\x16\x12\x15\x14\a\x01\x16\x04\x80\xfe\xf9\xfe\x8e\xfe\xf9\x01\a\x01r\x03\aL46$\xfe\xa9\xb3\u070f\xfe\xfb\xbdoo\xbd\x01\x05\x01\x1e\x01\x05\xbdo|\x01W%\x02\a\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\xfe\x804L&\x01V|o\xbd\x01\x05\x01\x1e\x01\x05\xbdoo\xbd\xfe\xfb\x8fܳ\xfe\xa9%\x00\x00\x03\x00\x00\xff\x80\a\x00\x05\x00\x00\x1a\x00=\x00M\x00\x00%\x11\x06\a\x04\a\x0e\x02+\x02\".\x01'&%&'\x11\x14\x163!26\x11<\x02.\x03#!\"\x06\x15\x14\x17\x16\x17\x1e\x04;\x022>\x03767>\x017\x11\x14\x06#!\"&5\x11463!2\x16\x06\x80 %\xfe\xf4\x9e3@m0\x01\x010m@3\x9e\xfe\xf4% \x13\r\x05\xc0\r\x13\x01\x05\x06\f\b\xfa@\r\x13\x93\xc1\xd0\x06:\"7.\x14\x01\x01\x14.7\":\x06\xd0\xc16]\x80^B\xfa@B^^B\x05\xc0B^ \x03\x00$\x1e΄+0110+\x84\xce\x1e$\xfd\x00\r\x13\x13\x04(\x02\x12\t\x11\b\n\x05\x13\r\xa8t\x98\xa5\x051\x1a%\x12\x12%\x1a1\x05\xa5\x98+\x91`\xfb\xc0B^^B\x04@B^^\x00\x00\x01\x00\x00\xff\x80\a\x00\x05\x80\x00\x1c\x00\x00\x04\"'\x01.\x0454632\x1e\x02\x17>\x0332\x16\x15\x14\a\x01\x03\x9a4\x12\xfd\x90\n#L\x81oP$$Po\x81>\xe0\xfe\xe5\xfd\x91\x80\x12\x02Z\b$_d\x8eC\xdc\xf8+I@$$@I+\xf8\xdc\xdd\xe5\xfd\xa8\x00\x00\x01\x00\x00\xff\xad\x06\x80\x05\xe0\x00\"\x00\x00\x01\x14\a\x01\x13\x16\x15\x14\x06#\"'%\x05\x06#\"&547\x13\x01&547%\x1362\x17\x13\x05\x16\x06\x80\x1a\xfe\x95V\x01\x15\x14\x13\x15\xfe?\xfe?\x16\x12\x15\x15\x02V\xfe\x94\x198\x01\xf6\xe1\x13<\x13\xe1\x01\xf68\x03y\x16\x1a\xfe\x9e\xfe\f\a\r\x15\x1d\f\xec\xec\f\x1d\x15\x06\x0e\x01\xf4\x01b\x1b\x15%\tI\x01\xc7))\xfe9I\t\x00\x00\x00\x00\x02\x00\x00\xff\xad\x06\x80\x05\xe0\x00\t\x00+\x00\x00\t\x01%\v\x01\x05\x01\x03%\x05\x01\x14\a\x01\x13\x16\x15\x14#\"'%\x05\x06#\"&547\x13\x01&547%\x1362\x17\x13\x05\x16\x04q\x012\xfeZ\xbd\xbd\xfeZ\x012I\x01z\x01y\x01\xc7\x1a\xfe\x95V\x01)\x13\x15\xfe?\xfe?\x16\x12\x15\x15\x02V\xfe\x94\x198\x01\xf6\xe1\x13<\x13\xe1\x01\xf68\x02\x14\x01)>\x01~\xfe\x82>\xfe\xd7\xfe[\xc7\xc7\x03\n\x16\x1a\xfe\x9e\xfe\f\a\r2\f\xec\xec\f\x1d\x15\x06\x0e\x01\xf4\x01b\x1b\x15%\tI\x01\xc7))\xfe9I\t\x00\x00\x02\x00\x00\xff\x80\x05\x00\x05\x80\x00\x15\x00\x1d\x00\x00%\x14\x06#!\"&54>\x033\x16 72\x1e\x03\x00\x10\x06 &\x106 \x05\x00}X\xfc\xaaX}\x11.GuL\x83\x01l\x83LuG.\x11\xff\x00\xe1\xfe\xc2\xe1\xe1\x01>\x89m\x9c\x9cmU\x97\x99mE\x80\x80Em\x99\x97\x03\xc1\xfe\xc2\xe1\xe1\x01>\xe1\x00\x00\x00\v\x00\x00\xff\x00\a\x80\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00o\x00\u007f\x00\x8f\x00\x9f\x00\xaf\x00\x00\x0554&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x01\x114&#!\"\x06\x15\x11\x14\x163!26\x0154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x0154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x01\x114&#!\"\x06\x15\x11\x14\x163!26\x0154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x01267\x11\x14\x06#!\"&5\x11463!2\x16\x01\x80&\x1a\x80\x1a&&\x1a\x80\x1a&&\x1a\x80\x1a&&\x1a\x80\x1a&&\x1a\x80\x1a&&\x1a\x80\x1a&\x04\x00&\x1a\xfd\x00\x1a&&\x1a\x03\x00\x1a&\xfc\x00&\x1a\x80\x1a&&\x1a\x80\x1a&\x05\x80&\x1a\x80\x1a&&\x1a\x80\x1a&\xfe\x80&\x1a\xfd\x00\x1a&&\x1a\x03\x00\x1a&\x01\x80&\x1a\x80\x1a&&\x1a\x80\x1a&&\x1a\x80\x1a&&\x1a\x80\x1a&&\x1a\x80\x1a&&\x1a\x80\x1a&\x80^B\xf9\xc0B^^B\x06@B^@\x80\x1a&&\x1a\x80\x1a&&\x01\x9a\x80\x1a&&\x1a\x80\x1a&&\x01\x9a\x80\x1a&&\x1a\x80\x1a&&\xfd\x1a\x02\x00\x1a&&\x1a\xfe\x00\x1a&&\x04\x9a\x80\x1a&&\x1a\x80\x1a&&\xfb\x9a\x80\x1a&&\x1a\x80\x1a&&\x03\x1a\x02\x00\x1a&&\x1a\xfe\x00\x1a&&\xfe\x9a\x80\x1a&&\x1a\x80\x1a&&\x01\x9a\x80\x1a&&\x1a\x80\x1a&&\x01\x9a\x80\x1a&&\x1a\x80\x1a&&\xba\xfa\xc0B^^B\x05@B^^\x00\x04\x00\x00\x00\x00\x06\x80\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00\x00\x01\x11\x14\x06#!\"&5\x11463!2\x16\x19\x01\x14\x06#!\"&5\x11463!2\x16\x01\x11\x14\x06#!\"&5\x11463!2\x16\x19\x01\x14\x06#!\"&5\x11463!2\x16\x03\x00L4\xfe\x004LL4\x02\x004LL4\xfe\x004LL4\x02\x004L\x03\x80L4\xfe\x004LL4\x02\x004LL4\xfe\x004LL4\x02\x004L\x02\x00\xfe\x804LL4\x01\x804LL\x02\xcc\xfe\x804LL4\x01\x804LL\xfc\xcc\xfe\x804LL4\x01\x804LL\x02\xcc\xfe\x804LL4\x01\x804LL\x00\t\x00\x00\x00\x00\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00o\x00\u007f\x00\x8f\x00\x00\x01\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x02\x008(\xfe\xc0(88(\x01@(88(\xfe\xc0(88(\x01@(8\x02\x808(\xfe\xc0(88(\x01@(8\xfd\x808(\xfe\xc0(88(\x01@(8\x02\x808(\xfe\xc0(88(\x01@(8\x02\x808(\xfe\xc0(88(\x01@(8\xfd\x808(\xfe\xc0(88(\x01@(8\x02\x808(\xfe\xc0(88(\x01@(88(\xfe\xc0(88(\x01@(8\x01 \xc0(88(\xc0(88\x01\xd8\xc0(88(\xc0(88\xfd\xd8\xc0(88(\xc0(88\x03\xd8\xc0(88(\xc0(88\xfd\xd8\xc0(88(\xc0(88\xfd\xd8\xc0(88(\xc0(88\x03\xd8\xc0(88(\xc0(88\xfd\xd8\xc0(88(\xc0(88\x01\xd8\xc0(88(\xc0(88\x00\x00\x06\x00\x00\x00\x00\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00\x00\x01\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x02\x008(\xfe\xc0(88(\x01@(88(\xfe\xc0(88(\x01@(8\x05\x008(\xfc@(88(\x03\xc0(8\xfb\x008(\xfe\xc0(88(\x01@(8\x05\x008(\xfc@(88(\x03\xc0(88(\xfc@(88(\x03\xc0(8\x01 \xc0(88(\xc0(88\x01\xd8\xc0(88(\xc0(88\xfd\xd8\xc0(88(\xc0(88\x03\xd8\xc0(88(\xc0(88\xfd\xd8\xc0(88(\xc0(88\x01\xd8\xc0(88(\xc0(88\x00\x00\x00\x01\x00y\x00\x0e\x06\x87\x04\xb2\x00\x16\x00\x00\x00\x14\a\x01\a\x06\"/\x01\x01&4?\x0162\x17\t\x0162\x1f\x01\x06\x87\x1c\xfd,\x88\x1cP\x1c\x88\xfe\x96\x1c\x1c\x88\x1cP\x1c\x01&\x02\x90\x1cP\x1c\x88\x03\xf2P\x1c\xfd,\x88\x1c\x1c\x88\x01j\x1cP\x1c\x88\x1c\x1c\xfe\xd9\x02\x91\x1c\x1c\x88\x00\x01\x00n\xff\xee\x05\x12\x04\x92\x00#\x00\x00$\x14\x0f\x01\x06\"'\t\x01\x06\"/\x01&47\t\x01&4?\x0162\x17\t\x0162\x1f\x01\x16\x14\a\t\x01\x05\x12\x1c\x88\x1cP\x1c\xfe\xda\xfe\xda\x1cP\x1c\x88\x1c\x1c\x01&\xfe\xda\x1c\x1c\x88\x1cP\x1c\x01&\x01&\x1cP\x1c\x88\x1c\x1c\xfe\xda\x01&\xfeP\x1c\x88\x1c\x1c\x01&\xfe\xda\x1c\x1c\x88\x1cP\x1c\x01&\x01&\x1cP\x1c\x88\x1c\x1c\xfe\xda\x01&\x1c\x1c\x88\x1cP\x1c\xfe\xda\xfe\xda\x00\x00\x03\x00\x00\xff\x00\x06\x80\x05\x80\x00#\x00+\x00D\x00\x00\x01\x15\x14\x06+\x01\x15\x14\x06+\x01\"&=\x01#\"&=\x0146;\x01546;\x012\x16\x1d\x0132\x1e\x01\x10\x00 \x00\x10\x00 \x00\x14\x06#\"'\x01\x06#\"$&\x02\x10\x126$ \x04\x16\x12\x15\x14\a\x01\x04\x00\x13\r\xe0\x13\r@\r\x13\xe0\r\x13\x13\r\xe0\x13\r@\r\x13\xe0\r\x13\x80\xfe\xf9\xfe\x8e\xfe\xf9\x01\a\x01r\x03\aK56$\xfe\xa9\xb3\u070f\xfe\xfb\xbdoo\xbd\x01\x05\x01\x1e\x01\x05\xbdo|\x01W\x02\xe0@\r\x13\xe0\r\x13\x13\r\xe0\x13\r@\r\x13\xe0\r\x13\x13\r\xe0\x13\xe6\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\xfe\xb5jK&\x01V|o\xbd\x01\x05\x01\x1e\x01\x05\xbdoo\xbd\xfe\xfb\x8fܳ\xfe\xa9\x00\x00\x03\x00\x00\xff\x00\x06\x80\x05\x80\x00\x0f\x00\x17\x000\x00\x00\x01\x15\x14\x06#!\"&=\x01463!2\x1e\x01\x10\x00 \x00\x10\x00 \x00\x14\x06#\"'\x01\x06#\"$&\x02\x10\x126$ \x04\x16\x12\x15\x14\a\x01\x04\x00\x13\r\xfd\xc0\r\x13\x13\r\x02@\r\x13\x80\xfe\xf9\xfe\x8e\xfe\xf9\x01\a\x01r\x03\aK56$\xfe\xa9\xb3\u070f\xfe\xfb\xbdoo\xbd\x01\x05\x01\x1e\x01\x05\xbdo|\x01W\x02\xe0@\r\x13\x13\r@\r\x13\x13\xe6\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\xfe\xb5jK&\x01V|o\xbd\x01\x05\x01\x1e\x01\x05\xbdoo\xbd\xfe\xfb\x8fܳ\xfe\xa9\x00\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x06\x00\x00)\x005\x00\x00\x01\x14\x02\x06\x04 $&\x0254\x1276\x16\x17\x16\x06\a\x0e\x01\x15\x14\x1e\x022>\x0254&'.\x017>\x01\x17\x16\x12\x01\x11\x14\x06\"&5\x11462\x16\x06\x00z\xce\xfe\xe4\xfe\xc8\xfe\xe4\xcez\xa1\x92+i\x1f \x0f*bkQ\x8a\xbdн\x8aQkb*\x0f \x1fj*\x92\xa1\xfd\x80LhLLhL\x02\x80\x9c\xfe\xe4\xcezz\xce\x01\x1c\x9c\xb6\x01Bm \x0e+*i J\xd6yh\xbd\x8aQQ\x8a\xbdhy\xd6J i*+\x0e m\xfe\xbe\x02J\xfd\x804LL4\x02\x804LL\x00\x00\x00\x00\x05\x00\x00\xff\x80\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00O\x00\x00%\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x11\x14\x06+\x01\"&5\x1146;\x012\x16%\x11\x14\x06+\x01\"&5\x1146;\x012\x16\x01\x11\x14\x06+\x01\"&5\x1146;\x012\x16\x01\x11\x14\x06+\x01\"&5\x1146;\x012\x16\x01\x00\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x01\x80\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x01\x80\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x01\x80\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x01\x80\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12`\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12r\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\x12\xf2\xfd\xc0\x0e\x12\x12\x0e\x02@\x0e\x12\x12\x01r\xfc@\x0e\x12\x12\x0e\x03\xc0\x0e\x12\x12\x01\xf2\xfa@\x0e\x12\x12\x0e\x05\xc0\x0e\x12\x12\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\a\x00n\x00\x00\x004&\"\x06\x14\x162\x01\x15\x14\x06\x0f\x01\x06\a\x16\x17\x16\x14\a\x0e\x01#\"/\x01\x06\a\x06\a\x06+\x01\"&/\x01&'\a\x06#\"'&'&547>\x017&/\x01.\x01=\x0146?\x0167&'&547>\x0132\x1f\x0167676;\x012\x16\x1f\x01\x16\x177632\x17\x16\x17\x16\x15\x14\a\x0e\x01\a\x16\x1f\x01\x1e\x01\x04\x00\x96Ԗ\x96\xd4\x02\x96\x10\f\xb9\x13\x14#H\n\t\x1b\x90\x16\f\x0e\x8a,/\x10\r\a\x1d\xde\x0e\x15\x01\x1c1)\x8d\n\x0f\x0e\v~'\a\b\x0fH\x12\x1b\x0e\xb7\r\x10\x10\v\xba\x0e\x19(C\n\t\x1a\x91\x16\r\r\x8a,/\x10\r\a\x1d\xde\x0e\x15\x01\x1c1)\x8e\t\x0f\r\f\x81$\a\b\x0fH\x12\x1a\x0f\xb7\r\x10\x02\x16Ԗ\x96Ԗ\x01m\xde\f\x16\x02\x1c6%2X\f\x1a\n%\x8e\tl\x17\x0f\x882\x1c\x11\r\xb8\x10\x15k\t\vr6\n\r\f\v\x15[\x1921\x1b\x02\x15\r\xde\f\x16\x02\x1c..9Q\f\f\n\r$\x8f\nk\x17\x0f\x882\x1c\x11\r\xb8\x10\x15k\t\nw3\b\x0e\f\v\x15[\x1920\x1c\x02\x15\x00\x00\x06\x00\x00\xff\x80\x05\x80\x05\x80\x00\x0f\x00\x1f\x00/\x00;\x00C\x00g\x00\x00\x01\x11\x14\x06+\x01\"&5\x1146;\x012\x16\x05\x11\x14\x06+\x01\"&5\x1146;\x012\x16\x05\x11\x14\x06+\x01\"&5\x1146;\x012\x16\x13\x11!\x11\x14\x1e\x013!2>\x01\x01!'&'!\x06\a\x05\x15\x14\x06+\x01\x11\x14\x06#!\"&5\x11#\"&=\x01463!7>\x013!2\x16\x1f\x01!2\x16\x02\x00\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x01\x00\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x01\x00\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x80\xfc\x80\x0e\x0f\x03\x03@\x03\x0f\x0e\xfd`\x01\xc00\a\n\xfe\xc3\n\a\x03o\x12\x0e`^B\xfc\xc0B^`\x0e\x12\x12\x0e\x015F\x0fN(\x01@(N\x0fF\x015\x0e\x12\x03 \xfd\xc0\x0e\x12\x12\x0e\x02@\x0e\x12\x12\x0e\xfd\xc0\x0e\x12\x12\x0e\x02@\x0e\x12\x12\x0e\xfd\xc0\x0e\x12\x12\x0e\x02@\x0e\x12\x12\xfd\x1e\x03\xb4\xfcL\x16%\x11\x11%\x04Ju\t\x02\x02\t\x95@\x0e\x12\xfcLSyuS\x03\xb8\x12\x0e@\x0e\x12\xa7%44%\xa7\x12\x00\x00\x00\x00\x02\x00\x1a\x00\x00\x06f\x05\x03\x00\x13\x005\x00\x00\x01\x11\x14\x06#!\x11!\x11!\"&5\x11465\t\x01\x167\a\x06\a#\"'\t\x01\x06'&/\x01&67\x0162\x1f\x01546;\x012\x16\x15\x11\x17\x1e\x01\x05\x80&\x1a\xfe\x80\xff\x00\xfe\x80\x1a&\x01\x02?\x02?\x01\xdf>\b\r\x03\r\b\xfdL\xfdL\f\f\r\b>\b\x02\n\x02\xcf X \xf4\x12\x0e\xc0\x0e\x12\xdb\n\x02\x02 \xfe \x1a&\x01\x80\xfe\x80&\x1a\x01\xe0\x01\x04\x01\x01\xda\xfe&\x02AJ\t\x02\a\x02A\xfd\xbf\b\x01\x02\tJ\n\x1b\b\x02W\x1a\x1a\xcc\xc3\x0e\x12\x12\x0e\xfeh\xb6\b\x1b\x00\x00\x03\x00\x00\xff\x00\x06\x00\x06\x00\x00\x13\x00\x1a\x00#\x00\x00\x01\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x17\a\x11!&'\x01&\x01\x11!\"&5\x11!\x11\x05\xbc\x1c(8(\xfa\xc0(88(\x03\x80(`\x1c\x84\x01x\n\f\xfe\xc7\f\x01c\xfe`(8\xfd\x00\x04\x84\x1c`(\xfb\x80(88(\x06@(8(\x1cD\xfe\x88\x1d\f\x019\f\xfa\x12\x04\x008(\x01\xa0\xfa\x00\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x14\x00 \x00,\x00\x00\x01\x11\x14\x06#!\"&=\x0146;\x01\x1146;\x012\x16\x00\x10.\x01 \x0e\x01\x10\x1e\x01 6\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x03\x80\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\xe0\x12\x0e@\x0e\x12\x01\xa0\x92\xfa\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\x01r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x03\xe0\xfe@\x0e\x12\x12\x0e@\x0e\x12\x01`\x0e\x12\x12\xfd\xfe\x01(\xfa\x92\x92\xfa\xfe\xd8\xfa\x92\x92\x02_\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x02\x002\x00\x00\aN\x05\x00\x00\x11\x00C\x00\x00\x015\x03.\x01+\x01\"\x06\a\x03\x15\x06\x16;\x0126\x01\x14#!26'\x03.\x01#!\"\x06\a\x03\x06\x163!\"547\x01>\x013!\"\x06\x0f\x01\x06\x16;\x0126/\x01.\x01#!2\x16\x17\x01\x16\x04W\x18\x01\x14\r\xba\r\x14\x01\x18\x01\x12\f\xf4\f\x12\x02\xf6.\xfd@\r\x12\x01\x14\x01\x14\r\xfe\xf0\r\x14\x01\x14\x01\x12\r\xfd@.\x1a\x01\xa1\b$\x14\x01S\r\x14\x01\x0f\x01\x12\r\xa6\r\x12\x01\x0f\x01\x14\r\x01S\x14$\b\x01\xa1\x1a\x02\x1c\x04\x01@\r\x13\x13\r\xfe\xc0\x04\f\x10\x10\xfe9I\x13\r\x01\x00\r\x13\x13\r\xff\x00\r\x13I6>\x04\x14\x13\x1c\x13\r\xc0\x0e\x12\x12\x0e\xc0\r\x13\x1c\x13\xfb\xec>\x00\x04\x00\x00\x00\x00\x06\x80\x06\x00\x00\a\x00\x0f\x00%\x00=\x00\x00$4&\"\x06\x14\x162$4&\"\x06\x14\x162\x13\x11\x14\x06#!\"&5\x11463!\x17\x162?\x01!2\x16\x01\x16\a\x01\x06\"'\x01&763!\x11463!2\x16\x15\x11!2\x05\x00&4&&4\x01&&4&&4\xa68(\xfa@(88(\x01ч:\x9c:\x88\x01\xd0(8\xfe\xbb\x11\x1f\xfe@\x126\x12\xfe@\x1f\x11\x11*\x01\x00&\x1a\x01\x00\x1a&\x01\x00*\xa64&&4&&4&&4&\x01 \xfe\xc0(88(\x01@(8\x8888\x888\x02\x11)\x1d\xfe@\x13\x13\x01\xc0\x1d)'\x01\xc0\x1a&&\x1a\xfe@\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x18\x00$\x000\x00\x00\x01\x14\a\x01\x06\"'\x01&76;\x01\x1146;\x012\x16\x15\x1132\x16\x02 \x0e\x01\x10\x1e\x01 >\x01\x10&\x04\x10\x02\x04 $\x02\x10\x12$ \x04\x04`\n\xfe\xc1\v\x18\v\xfe\xc0\x0f\b\b\x16\xc0\x12\x0e\xc0\x0e\x12\xc0\x0e\x12\xcc\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\x92\x92\x01r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02`\f\f\xfe\xc1\t\t\x01@\x10\x13\x14\x01`\x0e\x12\x12\x0e\xfe\xa0\x12\x022\x92\xfa\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\xbd\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x18\x00$\x000\x00\x00\x01\x06+\x01\x11\x14\x06+\x01\"&5\x11#\"&547\x0162\x17\x01\x16\x02 \x0e\x01\x10\x1e\x01 >\x01\x10&\x04\x10\x02\x04 $\x02\x10\x12$ \x04\x04^\b\x16\xc0\x12\x0e\xc0\x0e\x12\xc0\x0e\x12\n\x01?\v\x18\v\x01@\x0f\xd2\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\x92\x92\x01r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02\x94\x14\xfe\xa0\x0e\x12\x12\x0e\x01`\x12\x0e\f\f\x01?\t\t\xfe\xc0\x10\x01\xf9\x92\xfa\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\xbd\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x02\x00\x00\x00\x00\x06\x00\x05\x00\x00\r\x00#\x00\x00\x01!.\x01'\x03!\x03\x0e\x01\a!\x17!%\x11\x14\x06#!\"&5\x1147\x13>\x013!2\x16\x17\x13\x16\x03\xff\x01<\x01\x03\x01\xd4\xfd<\xd4\x01\x03\x01\x01<_\x01@\x02`&\x1a\xfa\x80\x1a&\x19\xee\n5\x1a\x03@\x1a5\n\xee\x19\x02@\x03\v\x02\x01\xf0\xfe\x10\x03\v\x02\xc0\xa2\xfe\x1e\x1a&&\x1a\x01\xe2>=\x02(\x19\"\"\x19\xfd\xd8=\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x1b\x00'\x00\x00\x00\x14\a\x01\x06#\"'&5\x11476\x17\x01\x16\x10.\x01 \x0e\x01\x10\x1e\x01 6\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04\xa0 \xfd\xe0\x0f\x11\x10\x10 !\x1f\x02 \xa0\x92\xfa\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\x01r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02\xa5J\x12\xfe\xc0\t\b\x13%\x02\x80%\x13\x12\x13\xfe\xc0\xcb\x01(\xfa\x92\x92\xfa\xfe\xd8\xfa\x92\x92\x02_\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x01\x00\x00\xff\x80\x06\x00\x05\x80\x003\x00\x00\x01\x11\x14\x06#!\"'&?\x01&#\"\x0e\x02\x14\x1e\x023267672\x1f\x01\x1e\x01\a\x06\x04#\"$&\x02\x10\x126$32\x04\x1776\x17\x16\x06\x00&\x1a\xfe@*\x11\x11\x1f\x8a\x94\xc9h\xbd\x8aQQ\x8a\xbdhw\xd4I\a\x10\x0f\n\x89\t\x01\bm\xfeʬ\x9c\xfe\xe4\xcezz\xce\x01\x1c\x9c\x93\x01\x13k\x82\x1d)'\x05\x00\xfe@\x1a&('\x1e\x8a\x89Q\x8a\xbdн\x8aQh_\n\x02\t\x8a\b\x19\n\x84\x91z\xce\x01\x1c\x018\x01\x1c\xcezoe\x81\x1f\x11\x11\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00$\x00G\x00\x00\x01\x14\a\x02\x00!\"$'\a\x06\"&5\x11463!2\x16\x14\x0f\x01\x1e\x013267676;\x012\x16\x13\x11\x14\x06#!\"&4?\x01&#\"\x06\a\x06\a\x06+\x01\"&=\x01\x12\x00!2\x04\x17762\x16\x05\xe7\x01@\xfeh\xfe\xee\x92\xfe\xefk\x81\x134&&\x1a\x01\xc0\x1a&\x13\x89G\xb4a\x86\xe8F\v*\b\x16\xc0\r\x13\x19&\x1a\xfe@\x1a&\x13\x8a\x94Ɇ\xe8F\v*\b\x16\xc7\r\x13A\x01\x9a\x01\x13\x92\x01\x14k\x82\x134&\x01\xe0\x05\x02\xfe\xf4\xfe\xb3nf\x81\x13&\x1a\x01\xc0\x1a&&4\x13\x89BH\x82r\x11d\x17\x13\x03\x13\xfe@\x1a&&4\x13\x8a\x89\x82r\x11d\x17\x13\r\a\x01\f\x01Moe\x81\x13&\x00\x00\x00\x00\b\x00\x00\x00\x00\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00o\x00\u007f\x00\x00\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x165\x15\x14\x06+\x01\"&=\x0146;\x012\x165\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15\x14\x06#!\"&=\x01463!2\x165\x15\x14\x06#!\"&=\x01463!2\x165\x15\x14\x06#!\"&=\x01463!2\x16\x13\x114&#!\"\x06\x15\x11\x14\x163!26\x13\x11\x14\x06#!\"&5\x11463!2\x16\x01\x80\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x04\x80\x13\r\xfc@\r\x13\x13\r\x03\xc0\r\x13\x13\r\xfc@\r\x13\x13\r\x03\xc0\r\x13\x13\r\xfc@\r\x13\x13\r\x03\xc0\r\x13\x80\x13\r\xfa@\r\x13\x13\r\x05\xc0\r\x13\x80^B\xfa@B^^B\x05\xc0B^\x01`@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xfd\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xfd3\x03@\r\x13\x13\r\xfc\xc0\r\x13\x13\x04M\xfb\xc0B^^B\x04@B^^\x00\x02\x00\x00\x00\x00\x04\x80\x05\x80\x00\a\x00\x1f\x00\x00\x01!54&\"\x06\x15\x01\x11\x14\x06#!\"&5\x1146;\x0154\x00 \x00\x1d\x0132\x16\x01@\x02\x00\x96Ԗ\x03@8(\xfc@(88( \x01\b\x01p\x01\b (8\x03\x00\xc0j\x96\x96j\xfe\xe0\xfd\xc0(88(\x02@(8\xc0\xb8\x01\b\xfe\xf8\xb8\xc08\x00\x00\x02\x00@\xff\x80\a\x00\x05\x80\x00\x11\x007\x00\x00\x01\x14\a\x11\x14\x06+\x01\"&5\x11&5462\x16\x05\x11\x14\x06\a\x06#\".\x02#\"\x05\x06#\"&5\x114767632\x16\x17\x1632>\x0232\x16\x01@@\x13\r@\r\x13@KjK\x05\xc0\x19\x1bך=}\\\x8bI\xc0\xfe\xf0\x11\x10\x1a&\x1f\x15:\xec\xb9k\xba~&26\u007f]S\r\x1a&\x05\x00H&\xfb\x0e\r\x13\x13\r\x04\xf2&H5KKu\xfd\x05\x19\x1b\x0et,4,\x92\t&\x1a\x02\xe6 \x17\x0e\x1dx:;\x13*4*&\x00\x00\x00\x01\x00\x00\x00\x00\x06\x80\x05\x80\x00K\x00\x00\x01\x14\x0f\x02\x0e\x01#\x15\x14\x06+\x01\"&5\x1146;\x012\x16\x1d\x012\x16\x177654\x02$ \x04\x02\x15\x14\x1f\x01>\x013546;\x012\x16\x15\x11\x14\x06+\x01\"&=\x01\"&/\x02&54\x126$ \x04\x16\x12\x06\x80<\x14\xb9\x16\x89X\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12Gv\"D\x1d\xb0\xfe\xd7\xfe\xb2\xfeװ\x1dD\"vG\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12X\x89\x16\xb9\x14<\x86\xe0\x014\x01L\x014\xe0\x86\x02\x8a\xa6\x941!Sk \x0e\x12\x12\x0e\x02@\x0e\x12\x12\x0e G<\f_b\x94\x01\x06\x9c\x9c\xfe\xfa\x94b_\f\x034.\x0354632\x17\x16\x03\x00&4\x13\xfe\xb3\xfe\xfa\x1a&&\x1a\x01\x06\x01M\x134&\x01\x80UF\n\x0f\x1a&\x18\"\"\x18\x18\"\"\x18&\x1a\x0f\nF\x04\xa0\xfb\xc0\x1a&\x13\x01M&\x1a\x01\x80\x1a&\x01M\x13&\xfe\x12\x98\x83\x1c\x05%\x1b\x15\x1d\x15\x19/B/\x19\x15\x1d\x15\x1b%\x05\x1b\x00\x00\x00\x00\x04\x00\x00\xff\xb9\x06\x80\x05G\x00\x13\x00-\x00I\x00k\x00\x00\x01\x11\x14\x06\"'\x01!\"&5\x11463!\x0162\x16\x00\x14\x06\a\x06#\"&54>\x034.\x0354632\x17\x16\x04\x10\x02\a\x06#\"&54767>\x014&'&'&54632\x17\x16\x04\x10\x02\a\x06#\"&547>\x017676\x12\x10\x02'&'.\x01'&54632\x17\x16\x03\x00&4\x13\xfe\xb3\xfe\xfa\x1a&&\x1a\x01\x06\x01M\x134&\x01\x80UF\n\x0f\x1a&\x18\"\"\x18\x18\"\"\x18&\x1a\x0f\nF\x01U\xaa\x8c\r\f\x1b&'8\x14JSSJ\x148'&\x1a\r\r\x8c\x01\xaa\xfe\xd3\r\r\x1a&'\a\x1f\a.${\x8a\x8a{$.\a\x1f\a'&\x1a\r\r\xd3\x04\xa0\xfb\xc0\x1a&\x13\x01M&\x1a\x01\x80\x1a&\x01M\x13&\xfe\x12\x98\x83\x1c\x05%\x1b\x15\x1d\x15\x19/B/\x19\x15\x1d\x15\x1b%\x05\x1b7\xfe\xce\xfe\xfd;\x05&\x1a'\x14\x1d\x0f6\xa3\xb8\xa36\x0f\x1d\x14'\x1a&\x05;\xb6\xfe4\xfe\u007f[\x05&\x1a$\x17\x04\r\x04\x19\x1a[\x01\x10\x012\x01\x10[\x1a\x19\x04\r\x04\x17$\x1a&\x05[\x00\f\x00\x00\x00\x00\x05\x80\x05\x80\x00\x03\x00\a\x00\v\x00\x0f\x00\x13\x00\x17\x00\x1b\x00\x1f\x00#\x00/\x003\x007\x00\x00\x01\x15#5\x13\x15#5!\x15#5\x01!\x11!\x11!\x11!\x01!\x11!\x01\x11!\x11\x01\x15#5!\x15#5\x13\x11!5#\x11#\x11!\x1535\x01\x11!\x11!\x11!\x11\x01\x80\x80\x80\x80\x03\x80\x80\xfc\x80\x01\x80\xfe\x80\x01\x80\xfe\x80\x03\x00\x01\x80\xfe\x80\xff\x00\xfd\x80\x04\x80\x80\x01\x80\x80\x80\xfe\x80\x80\x80\x01\x80\x80\xfd\x80\xfd\x80\x05\x80\xfd\x80\x01\x80\x80\x80\x03\x00\x80\x80\x80\x80\xfc\x01\x01\u007f\x01\x80\x01\x80\xfe\x80\x01\x80\xfd\x80\xfd\x80\x02\x80\xfe\x00\x80\x80\x80\x80\x02\x00\xfe\x80\x80\xfe\x80\x02\x80\x80\x80\x03\x00\xfd\x80\x02\x80\xfd\x80\x02\x80\x00\x00\x00\x00\x10\x00\x00\x00\x00\a\x00\x05\x80\x00\x03\x00\a\x00\v\x00\x0f\x00\x13\x00\x17\x00\x1b\x00\x1f\x00#\x00'\x00+\x00/\x003\x007\x00;\x00?\x00\x003#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113???? ^\x1f\x1f\x9d\x1f\x1f\x9d>>~\x1f\x1f?\x1f\x1f?\x1f\x1f\x9d??\x9d??~??~??^??\xbd^^? ^??\x05\x80\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x80\x05\x80\x00\x00\x00\x02\x00\x00\xff\x95\x05\xeb\x05\x80\x00\a\x00\x1d\x00\x00\x004&\"\x06\x14\x162\x01\x14\a\x01\x06#\"'\x01.\x015\x11463!2\x16\x17\x01\x16\x01\xc0KjKKj\x04v%\xfe\x15'45%\xfd5&5L4\x01\xa05\x80&\x02\xcb%\x04\vjKKjK\xfe@5%\xfe\x14%%\x02\xcc%\x805\x01\xa04L5&\xfd6'\x00\x00\x00\x00\x03\x00\x00\xff\x95\ak\x05\x80\x00\a\x00\x1d\x005\x00\x00\x004&\"\x06\x14\x162\x01\x14\a\x01\x06#\"'\x01.\x015\x11463!2\x16\x17\x01\x16\x05\x14\a\x01\x06#\"&'\x01654'\x01.\x01#32\x16\x17\x01\x16\x01\xc0KjKKj\x04v%\xfe\x15'45%\xfd5&5L4\x01\xa05\x80&\x02\xcb%\x01\x80%\xfe\x15'4$.\x1e\x01\xd6%%\xfd5&\x805\xe05\x80&\x02\xcb%\x04\vjKKjK\xfe@5%\xfe\x14%%\x02\xcc%\x805\x01\xa04L5&\xfd6'45%\xfe\x14%\x1c\x1f\x01\xd6%54'\x02\xca&55&\xfd6'\x00\x03\x00\n\xff\x80\x06y\x05\x80\x00T\x00d\x00t\x00\x00\x01\x16\a\x01\x0e\x01#!\"&'&74676&7>\x027>\x0176&7>\x017>\x0176&7>\x017>\x0176&7>\x027>\x06\x17\a63!2\x16\a\x01\x0e\x01#!\"\a\x06\x17\x163!267\x016'\x16\x05\x06\x163!26?\x016&#!\"\x06\a\x03\x06\x163!26?\x016&#!\"\x06\a\x06g(\x16\xfe\xed\x13sA\xfceM\x8f\x1c\x18\x16\x06\x01\x01\b\x01\x02\f\x15\x06\x17,\b\x03\x05\x02\x03\x1c\x03\x15*\x04\x01\a\x04\x04$\x04\x13/\x04\x01\b\x02\x02\x0e\x16\x06\b\x11\r\x13\x14!'\x1c\x01&\r\x02\xf9JP\x16\xfe\xee$G]\xfc\x9b\x1b\v\v\n\x18x\x03\x9b\x1d6\b\x01,\a\x02&\xfb\xed\x04\f\x0e\x02`\r\x19\x04\x15\x04\f\x0e\xfd\xa0\r\x19\x04h\x04\f\x0e\x02`\r\x19\x04\x15\x04\f\x0e\xfd\xa0\r\x19\x04\x04\"9H\xfcv@WkNC<\x04.\x0e\b\x1b\x06\v\x14\x1b\n&k&\n(\b\v\"\x06$p\"\t.\x05\r#\x05\x1au&\b#\t\b\x14\x1a\b\f%!'\x19\x16\x01\x06\x03\tpJ\xfcvwE\x0f\x10\x1bF\x1f\x1a\x03\xdb\x16#\x0f\x1e\r\x13\x13\r@\r\x13\x13\r\xfe\xc0\r\x13\x13\r@\r\x13\x13\r\x00\x00\x01\x00\x00\xff\x97\x05\x00\x05\x80\x00\x1c\x00\x00\x012\x17\x1e\x01\x15\x11\x14\x06\a\x06#\"'\t\x01\x06#\"'.\x015\x1146763\x04\x8c\x17\x15!''!\x13\x190#\xfeG\xfeG$/\x17\x15!''!\x15\x17\x05\x80\t\r8\"\xfa\xf7\"8\r\b \x01\xa8\xfeX!\t\r8\"\x05\t\"8\r\t\x00\x00\x00\x00\x04\x00\x00\xff\x80\x06\x80\x05\x80\x00\x03\x00\f\x00\x14\x00<\x00\x00)\x01\x11!\x11!\x11#\"&=\x01!\x004&\"\x06\x14\x1627\x11\x14\x06+\x01\x15\x14\x06#!\"&=\x01#\"&5\x1146;\x01\x11463!2\x16\x1f\x01\x1e\x01\x15\x1132\x16\x01\x80\x03\x80\xfc\x80\x03\x80\xa0(8\xfd\x80\x04\x80&4&&4\xa6\x13\r\xe08(\xfc@(8\xe0\r\x13qO@8(\x02\xa0(`\x1c\x98\x1c(@Oq\x01\x00\x01\x80\x01\x808(\xa0\xfd&4&&4&@\xfe`\r\x13\xa0(88(\xa0\x13\r\x01\xa0Oq\x02 (8(\x1c\x98\x1c`(\xff\x00q\x00\x03\x00\x00\xff\x80\a\x80\x06\x00\x00\a\x00!\x00)\x00\x00\x002\x16\x14\x06\"&4\x012\x16\x15\x11\x14\x06#!\"&5\x1146;\x017>\x013!2\x16\x1f\x01\x00 \x00\x10\x00 \x00\x10\x03I\uea69\xee\xa9\x03\xe0j\x96\x96j\xfa\x80j\x96\x96j\xe03\x13e5\x02\x005e\x133\xfdg\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\x03`\xa9\uea69\xee\x02I\x96j\xfc\x80j\x96\x96j\x03\x80j\x96\x881GG1\x88\xfb\x80\x01\a\x01r\x01\a\xfe\xf9\xfe\x8e\x00\x00\x00\x00\x02\x00\x00\xff\x80\x06\x80\x05\x80\x00\a\x00P\x00\x00\x01\x032\x16327&\x017>\x047\x13\x01;\x01\x16\x17\x13\x16\x12\x17\x1e\x01\x17\x16\x17\x1e\x01\x17\x16\x15\x14\x06\x15\"&#\"\x04\a4?\x012>\x0554.\x01'%\x06\x02\x15\x14\x1e\x033\x16\x15\x14\a\"&#\"\x06#\x06\x02ժ!\xcf9\x13&W\xfc\xca\x02\x17B03&\f\xed\x01\x18K5\b\x03\xcd!\x92)\x0fV\x1d\x14\x0f\x13\x8a\x0f\x06\x01?\xfe@L\xfe\xea'\x04\x83\x01\x17\b\x15\t\r\x05>R\x01\xfe>\x1ae\x1c;&L\x03\x01\x02:\xe9:\b%\x03P\x03\xd1\xfe>\x04\x02\xfd\xfcvO\a\v\n\x13'\x1f\x02h\x02\xd4\x0e\a\xfe N\xfe\x99_\"\xdd:-\f\x0f\x1d\x06&\x13\x05\x11\x04\x10\x0e\x01+#\x1c\x05\x02\a\x06\n\f\b\x10\xa1\xc2\x03\x02:\xfe\xed\x19\x16\x1f\x12\t\b\x13'\t\x12\x14\b\x0e\x00\x00\x03\x00\x00\xff\x80\x05\x80\x05\x80\x00\x15\x00+\x00a\x00\x00%\x163 \x114'.\x04#\"\a\x14\x06\x15\x14\x06\x1e\x01\x03\x1632>\x0254.\x02#\"\a\x14\x16\x15\x14\x06\x15\x14\x017>\x017>\x04<\x015\x10'.\x04/\x016$32\x1632\x1e\x03\x15\x14\x0e\x03\a\x1e\x01\x15\x14\x0e\x03#\"&#\"\x04\x02+JB\x01x)\x1bEB_I:I\x1c\x01\x02\x01\b\x06*CRzb3:dtB2P\b\x01\xfd\xe4\x02\x0f\x8c$\a\v\x06\x05\x01\x16\x04$5.3\x05\x04b\x01\xe4\x83\x17Z\x17F\x85|\\8!-T>5\x9a\xcdFu\x9f\xa8\\,\xb0,j\xfen\x0f \x01OrB,\x027676\x1a\x01'5.\x02'7\x1e\x0232>\x017\x06\a\x0e\x01\a\x0e\x03\a\x06\x02\a\x0e\x03\x1f\x01\x16\x17\x06\a\"\x06#\"&#&#\"\x06\x11\x16OA\x1b\x1c\r\x01zj\x01\x18=N\x13\x13!\xae}:0e\x8d\x1c\x05\x0e\x1e\x8f%\b\f\x06\t\x02\x1by\x11\x02\x16\x12\x0e\x01\x01\x11\xa8\x03\r\v+\v\x1dt\x1c\x8aD3\xb8~U\a\x13\x13\x0e#B\a\x024\x02\v#\x19\r\v\x05\x03g\x02\t\x05\x05\t\x02'2\n%\x0f\x13/!:\r\x94\xfd\xe1T\tbRU\x0f\x12\x04\x1b,7\x03\x14\x02\x12\x00\x00\x00\x00\x02\x00\x00\xff\x80\x06\xfa\x05\x80\x00\x1b\x00}\x00\x00%2\x16\x0f\x01\x06\"/\x01&6;\x01\x11#\"&?\x0162\x1f\x01\x16\x06+\x01\x11\x01\x17\x1632632\x163!2\x16>\x02?\x012\x163\x16\x15\x14\a\x06\a&'.\x02'.\x03\x06#\"&\"\x06\a\x06\x17\x14\x12\x15\x14\x06\x16\x17\x1e\x01\x17\x16\x15\x14\x0f\x01\x06$#\"\x06#&=\x01>\x0276\x114\x02=\x01464.\x01'&#\"\x06\a\x0e\x02\a&'\x11\x06\xd0!\x12\x14~\x14:\x14~\x14\x12!PP!\x12\x14~\x14:\x14~\x14\x12!P\xf9\xd16\f\xc7,\xb0,$\x8f$\x01%\x06\x1e\v\x15\x0e\b*\x04\x14\x04\x02\x05'\x1d\x19\x1d\x03\x10\r\x01\x06\f\x13\a\x1d\x02\x11c2N \t\x01\x04\x05\x05\n(\xa8$\x05\x03\"L\xfe\xe4A2\xca3\x03\x11Yl\x18\x13\x06\x01\x02\x04\x03\v\x97!x\x14\x13\x1e!\x1a*\x0e\x80%\x1a\xa2\x1a\x1a\xa2\x1a%\x04\x00%\x1a\xa2\x1a\x1a\xa2\x1a%\xfc\x00\x04\xff\x1b\x05\x04\x01\x01\x01\x05\r\v\x01\x01p\xe0P\x1d\x0e\x04,T\tNE\x01\b\t\x03\x02\x01\x01\x04\x04Q7^\xfd\xb4\xa1\x10oH!\x15+\x10(\n\x0e\x0f\x01\x02\x14\x123\x01\t\x1b \x1a\x0e*\x01Ue\x01\x94eu\x02\x1b\x17\x1c\x14\x04\f\x18\x0e\rwg\x02\x1a\x12\x01\u007f\x00\x00\x02\x00\x00\xff\x03\x06\x00\x05\x80\x00a\x00\x95\x00\x00\x13\x17\x1632632$\x04\x17\x16?\x012\x163\x16\x15\x14\a\x06\a&'.\x025&'&#\"&\"\x06\a\x06\x1f\x015\x14\x1e\x01\x15\x14\x06\x16\x17\x1e\x01\x17\x16\x15\x14\x0f\x01\x06$#\"\x06#&=\x01>\x027>\x024&54&54>\x01.\x01'&#\"\x06\a\x0e\x02\a&'\x11\x012\x1e\x02\x17\x16\x14\a\x0e\x03#\".\x01465!\x14\x16\x14\x0e\x01#\".\x02'&47>\x0332\x1e\x01\x14\x06\x15!4&4>\x01Q6\f\xc7,\xb0,F\x01a\x01\x00w!\x17*\x04\x14\x04\x02\x05'\x1d\x19\x1d\x03\x10\x0e\n\x11\x05=\x1e~Pl*\t\x01\x01\x02\x01\x05\x05\n(\xa8$\x05\x03\"L\xfe\xe4A2\xca3\x03\x11Yl\x18\a\t\x03\x01\x05\x01\x01\x01\x05\x04\v\x97)\xf4\x10\x13\x1e!\x1a*\x0e\x05\x1e\f<7@\x04\x1a\x1a\x04@7<\f\r\x0f\x05\x03\xfc\x00\x03\x05\x0f\r\f<7@\x04\x1a\x1a\x04@7<\f\r\x0f\x05\x03\x04\x00\x03\x05\x0f\x05\u007f\x1b\x05\x04\x02\x01\x04\x01 \x01\x01p\xe0P\x1d\x0e\x04,T\tMF\x01\r\x06\x02\x02\x04\x05Q7\x9847ƢH\x10oH!\x15+\x10(\n\x0e\x0f\x01\x02\x14\x123\x01\t\x1b \x1a\x0e\x10t\xaf\x87\xac\x03\a\x1d\b\aJHQ6\x05\f\x1b\v\fwh\x02\x1a\x12\x01\u007f\xfa\xff',6\x03\x158\x15\x036,'\x15$\x1f#\x02\x02#\x1f$\x15',6\x03\x158\x15\x036,'\x15$\x1f#\x02\x02#\x1f$\x15\x00\x00\x04\x00\x00\x00\x00\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00\x00%\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\a\x00&\x1a\xf9\x80\x1a&&\x1a\x06\x80\x1a&\xfe\x80&\x1a\xfb\x00\x1a&&\x1a\x05\x00\x1a&\x01\x00&\x1a\xfa\x00\x1a&&\x1a\x06\x00\x1a&\xfe\x80&\x1a\xfb\x80\x1a&&\x1a\x04\x80\x1a&\xc0\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x00\x00\x04\x00\x00\x00\x00\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00\x00%\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\a\x00&\x1a\xf9\x80\x1a&&\x1a\x06\x80\x1a&\xfe\x80&\x1a\xfc\x80\x1a&&\x1a\x03\x80\x1a&\x01\x00&\x1a\xfa\x80\x1a&&\x1a\x05\x80\x1a&\xfe\x80&\x1a\xfd\x80\x1a&&\x1a\x02\x80\x1a&\xc0\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x00\x00\x04\x00\x00\x00\x00\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00\x00%\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\a\x00&\x1a\xf9\x80\x1a&&\x1a\x06\x80\x1a&&\x1a\xfb\x00\x1a&&\x1a\x05\x00\x1a&&\x1a\xfa\x00\x1a&&\x1a\x06\x00\x1a&&\x1a\xfb\x80\x1a&&\x1a\x04\x80\x1a&\xc0\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x00\x00\x00\x00\x04\x00\x00\x00\x00\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00\x00%\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\a\x00&\x1a\xf9\x80\x1a&&\x1a\x06\x80\x1a&&\x1a\xf9\x80\x1a&&\x1a\x06\x80\x1a&&\x1a\xf9\x80\x1a&&\x1a\x06\x80\x1a&&\x1a\xf9\x80\x1a&&\x1a\x06\x80\x1a&\xc0\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x00\x00\x00\x00\b\x00\x00\x00\x00\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00o\x00\u007f\x00\x00%\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x11\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x11\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x01\x00\x13\r\xc0\r\x13\x13\r\xc0\r\x13\x13\r\xc0\r\x13\x13\r\xc0\r\x13\x13\r\xc0\r\x13\x13\r\xc0\r\x13\x06\x00\x13\r\xfa\xc0\r\x13\x13\r\x05@\r\x13\xfa\x00\x13\r\xc0\r\x13\x13\r\xc0\r\x13\x06\x00\x13\r\xfa\xc0\r\x13\x13\r\x05@\r\x13\x13\r\xfa\xc0\r\x13\x13\r\x05@\r\x13\x13\r\xfa\xc0\r\x13\x13\r\x05@\r\x13\xe0\xc0\r\x13\x13\r\xc0\r\x13\x13\x01s\xc0\r\x13\x13\r\xc0\r\x13\x13\x01s\xc0\r\x13\x13\r\xc0\r\x13\x13\xfc\xf3\xc0\r\x13\x13\r\xc0\r\x13\x13\x04s\xc0\r\x13\x13\r\xc0\r\x13\x13\xfc\xf3\xc0\r\x13\x13\r\xc0\r\x13\x13\x01s\xc0\r\x13\x13\r\xc0\r\x13\x13\x01s\xc0\r\x13\x13\r\xc0\r\x13\x13\x00\x00\x05\x00\x00\x00\x00\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00O\x00\x00\x01\x11\x14\x06#\"'\x01&47\x01632\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x01\x80\x13\r\x0e\t\xfe\xe0\t\t\x01 \t\x0e\r\x13\x05\x80\x13\r\xf9@\r\x13\x13\r\x06\xc0\r\x13\x13\r\xfb\xc0\r\x13\x13\r\x04@\r\x13\x13\r\xfb\xc0\r\x13\x13\r\x04@\r\x13\x13\r\xf9@\r\x13\x13\r\x06\xc0\r\x13\x03\xe0\xfd\xc0\r\x13\t\x01 \t\x1c\t\x01 \t\x13\xfc\xf3\xc0\r\x13\x13\r\xc0\r\x13\x13\x01s\xc0\r\x13\x13\r\xc0\r\x13\x13\x01s\xc0\r\x13\x13\r\xc0\r\x13\x13\x01s\xc0\r\x13\x13\r\xc0\r\x13\x13\x00\x05\x00\x00\x00\x00\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00O\x00\x00\x00\x14\a\x01\x06#\"&5\x114632\x17\t\x01\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x01`\t\xfe\xe0\t\x0e\r\x13\x13\r\x0e\t\x01 \x05\xa9\x13\r\xf9@\r\x13\x13\r\x06\xc0\r\x13\x13\r\xfb\xc0\r\x13\x13\r\x04@\r\x13\x13\r\xfb\xc0\r\x13\x13\r\x04@\r\x13\x13\r\xf9@\r\x13\x13\r\x06\xc0\r\x13\x02\xce\x1c\t\xfe\xe0\t\x13\r\x02@\r\x13\t\xfe\xe0\xfe\t\xc0\r\x13\x13\r\xc0\r\x13\x13\x01s\xc0\r\x13\x13\r\xc0\r\x13\x13\x01s\xc0\r\x13\x13\r\xc0\r\x13\x13\x01s\xc0\r\x13\x13\r\xc0\r\x13\x13\x00\x00\x01\x00\x00\x00\x00\a\x00\x05\x00\x00\x1f\x00\x00\x01\x11\x14\a\x06#\"'\x01\x15\x14\x06#!\"&5\x11463!2\x16\x1d\x01\x01632\x17\x16\a\x00'\r\f\x1b\x12\xfem\xa9w\xfd@w\xa9\xa9w\x02\xc0w\xa9\x01\x93\x12\x1b\f\r'\x04\xa0\xfb\xc0*\x11\x05\x13\x01\x93\xa6w\xa9\xa9w\x02\xc0w\xa9\xa9w\xa5\x01\x92\x13\x05\x11\x00\x00\x00\x00\x04\x00\x00\xff\x80\a\x80\x05\x80\x00\a\x00\x0e\x00\x1e\x00.\x00\x00\x00\x14\x06\"&462\x01\x11!5\x01\x17\t\x01!\"\x06\x15\x11\x14\x163!265\x114&\x17\x11\x14\x06#!\"&5\x11463!2\x16\x02\x80p\xa0pp\xa0\x04p\xfa\x80\x01@\xa0\x02\x00\x02\x00\xf9\xc0\r\x13\x13\r\x06@\r\x13\x13\x93^B\xf9\xc0B^^B\x06@B^\x04\x10\xa0pp\xa0p\xfd\xc0\xfe@\xc0\x01@\xa0\x02\x00\x01 \x13\r\xfb@\r\x13\x13\r\x04\xc0\r\x13 \xfb@B^^B\x04\xc0B^^\x00\x04\x00\x00\xff\x80\x05\xeb\x05k\x00\x06\x00\x14\x00\x19\x00%\x00\x00!7'\a\x153\x15\x014#\"\a\x01\x06\x15\x14327\x016'\t\x01!\x11\x01\x14\x0f\x01\x017632\x1f\x01\x16\x01k[\xeb[\x80\x02v\x16\n\a\xfd\xe2\a\x16\n\a\x02\x1e\a6\x01\xa0\xfc\xc0\xfe`\x05\xeb%\xa6\xfe`\xa6$65&\xeb%[\xeb[k\x80\x03\xa0\x16\a\xfd\xe2\a\n\x16\a\x02\x1e\a\xca\xfe`\xfc\xc0\x01\xa0\x02\xe05%\xa6\x01\xa0\xa5&&\xea'\x00\x00\x02\x00\x00\xff\x80\x04\x00\x05\x80\x00\a\x00\x17\x00\x00\x004&\"\x06\x14\x162\x01\x14\a\x01\x0e\x01\"&'\x01&54\x00 \x00\x03\x00\x96Ԗ\x96\xd4\x01\x96!\xfe\x94\x10?H?\x0f\xfe\x93!\x01,\x01\xa8\x01,\x03\x16Ԗ\x96Ԗ\x01\x00mF\xfc\xfa!&&!\x03\x06Fm\xd4\x01,\xfe\xd4\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\a\x00\x13\x00\x00%\x11\"\x0e\x01\x10\x1e\x01\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x03\x00\x94\xfa\x92\x92\xfa\x03\x94\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a`\x04@\x92\xfa\xfe\xd8\xfa\x92\x02\xf1\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x00\x02\x00\x00\x00\x00\x04\x00\x05\xc0\x00\x15\x00-\x00\x00\x014'.\x03'&\"\a\x0e\x03\a\x06\x15\x14\x1626%\x14\x00 \x00547>\x037>\x012\x16\x17\x1e\x03\x17\x16\x02\x00\x14\x01\x1d\x16\x1c\a\x04\"\x04\a\x1c\x16\x1d\x01\x14KjK\x02\x00\xfe\xd4\xfeX\xfe\xd4Q\x06qYn\x1c\t243\b\x1cnYq\x06Q\x01\x80$!\x01+!7\x17\x10\x10\x177!+\x01!$5KK\xb5\xd4\xfe\xd4\x01,ԑ\x82\t\xa3\x8b\xd9]\x1e\"\"\x1e]ً\xa3\t\u007f\x00\x05\x00\x00\x00\x00\x06\xf8\x05\x80\x00\x06\x00\x0e\x009\x00>\x00H\x00\x00\x017'\a\x153\x15\x00&\a\x01\x06\x167\x01\x13\x15\x14\x06#!\"&5\x11463!2\x17\x16\x17\x16\x0f\x01\x06'&#!\"\x06\x15\x11\x14\x163!26=\x014?\x016\x16\x03\t\x01!\x11\x01\a\x01762\x1f\x01\x16\x14\x03xt\x98t`\x02\x00 \x11\xfe\xa2\x11 \x11\x01^Q\xa9w\xfc\xc0w\xa9\xa9w\x03@?6\x0f\x03\x03\f1\x0e\x12\x17\x16\xfc\xc0B^^B\x03@B^\t@\x0f(`\x01 \xfd`\xfe\xe0\x04\\\\\xfe\xe0\\\x1cP\x1c\x98\x1c\x01`t\x98t8`\x02\xc0 \x11\xfe\xa2\x11 \x11\x01^\xfdϾw\xa9\xa9w\x03@w\xa9\x19\a\x10\x11\f1\x0e\x06\x06^B\xfc\xc0B^^B~\r\t@\x0f\x10\x02\xcd\xfe\xe0\xfd`\x01 \x02\x1c\\\x01 \\\x1c\x1c\x98\x1cP\x00\x00\x00\x00\x02\x00\x00\x00\x00\x06\x80\x06\x00\x00+\x00Z\x00\x00\x01\x11\x14\x06#!\"&5\x11463!12\x16\x15\x14\a\x06\a\x06+\x01\"\x06\x15\x11\x14\x163!26=\x0147676\x17\x16\x13\x01\x06#\"'&=\x01# \a\x06\x13\x16\a\x06#\"'.\x0454>\a;\x01547632\x17\x01\x16\x14\x05\x80\xa9w\xfc\xc0w\xa9\xa9w\x00\xff\r\x13\x1aM8\n\x06pB^^B\x03@B^\x12\x1c\x1a\x10\x13\x15\xed\xfe\x80\x12\x1b\f\r'\xa0\xfe\xbdsw-\x03\x17\b\x04\x10\n\n\x169*#\a\x15#;No\x8a\xb5j\xa0'\r\f\x1a\x13\x01\x80\x13\x02#\xfe\xfdw\xa9\xa9w\x03@w\xa9\x13\r\x1b\x05\x1a\"\x04^B\xfc\xc0B^^B\xd6\x13\n\r\x18\x10\b\t\x01\xdc\xfe\x80\x13\x05\x11*\xc0\x83\x89\xfe\xb0\x17\v\x02\r\x0e\"g`\x8481T`PSA:'\x16\xc0*\x11\x05\x13\xfe\x80\x134\x00\x00\x02\x00\x00\x00\x00\x06\u007f\x05\x80\x00/\x00D\x00\x00\x01\x11\x14\x06#!\"&5\x11463!2\x17\x16\x17\x16\x0f\x01\x06#\"'&#!\"\x06\x15\x11\x14\x163!26=\x014?\x01632\x17\x16\x13\x01\x06\"'\x01&4?\x0162\x17\t\x0162\x1f\x01\x16\x14\x05\x80\xa9w\xfc\xc0w\xa9\xa9w\x03@?6\x0f\x03\x03\f1\n\r\x03\x06\x17\x16\xfc\xc0B^^B\x03@B^\t@\n\r\x06\x06\x14\xe7\xfc\xd2\x18B\x18\xfeR\x18\x18n\x18B\x18\x01\a\x02\x87\x18B\x18n\x18\x02^\xfe\xc2w\xa9\xa9w\x03@w\xa9\x19\a\x10\x11\f1\n\x02\x06^B\xfc\xc0B^^B\xfe\r\t@\n\x03\b\x01\xd4\xfc\xd2\x18\x18\x01\xae\x18B\x18n\x18\x18\xfe\xf9\x02\x87\x18\x18n\x18B\x00\x00\x00\x00\x01\x00\x00\xff\x00\a\x00\x06\x00\x00C\x00\x00\x00\x14\a\x01\x06\"&=\x01!\x1132\x16\x14\a\x01\x06\"'\x01&46;\x01\x11!\x15\x14\x06\"'\x01&47\x0162\x16\x1d\x01!\x11#\"&47\x0162\x17\x01\x16\x14\x06+\x01\x11!5462\x17\x01\a\x00\x13\xff\x00\x134&\xfe\x80\x80\x1a&\x13\xff\x00\x134\x13\xff\x00\x13&\x1a\x80\xfe\x80&4\x13\xff\x00\x13\x13\x01\x00\x134&\x01\x80\x80\x1a&\x13\x01\x00\x134\x13\x01\x00\x13&\x1a\x80\x01\x80&4\x13\x01\x00\x02\x9a4\x13\xff\x00\x13&\x1a\x80\xfe\x80&4\x13\xff\x00\x13\x13\x01\x00\x134&\x01\x80\x80\x1a&\x13\x01\x00\x134\x13\x01\x00\x13&\x1a\x80\x01\x80&4\x13\x01\x00\x13\x13\xff\x00\x134&\xfe\x80\x80\x1a&\x13\xff\x00\x00\x01\x00\x00\xff\x80\x04\x00\x05\x80\x00\x1d\x00\x00\x016\x16\x15\x11\x14\x06'\x01&'\x11\x14\x06+\x01\"&5\x1146;\x012\x16\x15\x1167\x03\xd3\x13\x1a\x1a\x13\xfd:\t\x04&\x1a\x80\x1a&&\x1a\x80\x1a&\x04\t\x05s\x13\f\x1a\xfa@\x1a\f\x13\x02\xc6\t\n\xfdZ\x1a&&\x1a\x05\x80\x1a&&\x1a\xfdZ\n\t\x00\x01\x00\x00\xff\x80\a\x00\x05\x80\x00+\x00\x00\x016\x16\x15\x11\x14\x06'\x01&'\x11\x14\x06'\x01&'\x11\x14\x06+\x01\"&5\x1146;\x012\x16\x15\x1167\x016\x16\x15\x1167\x06\xd3\x13\x1a\x1a\x13\xfd:\t\x04\x1a\x13\xfd:\t\x04&\x1a\x80\x1a&&\x1a\x80\x1a&\x04\t\x02\xc6\x13\x1a\x04\t\x05s\x13\f\x1a\xfa@\x1a\f\x13\x02\xc6\t\n\xfd:\x1a\f\x13\x02\xc6\t\n\xfdZ\x1a&&\x1a\x05\x80\x1a&&\x1a\xfdZ\n\t\x02\xc6\x13\f\x1a\xfd:\n\t\x00\x01\x00z\xff\x80\x06\x80\x05\x80\x00\x19\x00\x00\x016\x16\x15\x11\x14\x06'\x01&'\x11\x14\x06'\x01&47\x016\x16\x15\x1167\x06S\x13\x1a\x1a\x13\xfd:\t\x04\x1a\x13\xfd:\x13\x13\x02\xc6\x13\x1a\x04\t\x05s\x13\f\x1a\xfa@\x1a\f\x13\x02\xc6\t\n\xfd:\x1a\f\x13\x02\xc6\x134\x13\x02\xc6\x13\f\x1a\xfd:\n\t\x00\x00\x01\x00\x00\xff|\x05\u007f\x05\x84\x00\v\x00\x00\t\x01\x06&5\x1146\x17\x01\x16\x14\x05h\xfa\xd0\x17!!\x17\x050\x17\x02a\xfd\x1e\r\x14\x1a\x05\xc0\x1a\x14\r\xfd\x1e\r$\x00\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x1f\x00\x00\x01\x11\x14\x06#!\"&5\x11463!2\x16\x05\x11\x14\x06#!\"&5\x11463!2\x16\x06\x00&\x1a\xfe\x00\x1a&&\x1a\x02\x00\x1a&\xfc\x80&\x1a\xfe\x00\x1a&&\x1a\x02\x00\x1a&\x05@\xfa\x80\x1a&&\x1a\x05\x80\x1a&&\x1a\xfa\x80\x1a&&\x1a\x05\x80\x1a&&\x00\x00\x00\x00\x01\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x00\x01\x11\x14\x06#!\"&5\x11463!2\x16\x06\x00&\x1a\xfa\x80\x1a&&\x1a\x05\x80\x1a&\x05@\xfa\x80\x1a&&\x1a\x05\x80\x1a&&\x00\x00\x00\x00\x01\x00\x00\xff\x80\x06\x06\x05\x80\x00\x19\x00\x00\x17\x06&5\x1146\x17\x01\x16\x17\x1146\x17\x01\x16\x14\a\x01\x06&5\x11\x06\a-\x13\x1a\x1a\x13\x02\xc6\t\x04\x1a\x13\x02\xc6\x13\x13\xfd:\x13\x1a\x04\ts\x13\f\x1a\x05\xc0\x1a\f\x13\xfd:\t\n\x02\xc6\x1a\f\x13\xfd:\x134\x13\xfd:\x13\f\x1a\x02\xc6\n\t\x00\x00\x00\x00\x01\x00\x00\xff\x80\a\x00\x05\x80\x00+\x00\x00\x17\x06&5\x1146\x17\x01\x16\x17\x1146\x17\x01\x16\x17\x1146;\x012\x16\x15\x11\x14\x06+\x01\"&5\x11\x06\a\x01\x06&5\x11\x06\a-\x13\x1a\x1a\x13\x02\xc6\t\x04\x1a\x13\x02\xc6\t\x04&\x1a\x80\x1a&&\x1a\x80\x1a&\x04\t\xfd:\x13\x1a\x04\ts\x13\f\x1a\x05\xc0\x1a\f\x13\xfd:\t\n\x02\xc6\x1a\f\x13\xfd:\t\n\x02\xa6\x1a&&\x1a\xfa\x80\x1a&&\x1a\x02\xa6\n\t\xfd:\x13\f\x1a\x02\xc6\n\t\x00\x00\x00\x01\x00\x00\xff\x80\x04\x00\x05\x80\x00\x1d\x00\x00\x17\x06&5\x1146\x17\x01\x16\x17\x1146;\x012\x16\x15\x11\x14\x06+\x01\"&5\x11\x06\a-\x13\x1a\x1a\x13\x02\xc6\t\x04&\x1a\x80\x1a&&\x1a\x80\x1a&\x04\ts\x13\f\x1a\x05\xc0\x1a\f\x13\xfd:\t\n\x02\xa6\x1a&&\x1a\xfa\x80\x1a&&\x1a\x02\xa6\n\t\x00\x00\x00\x02\x00\x01\x00\x00\x06\x01\x05\x06\x00\v\x00\x1b\x00\x00\x13\x0162\x17\x01\x16\x06#!\"&\x01!\"&5\x11463!2\x16\x15\x11\x14\x06\x0e\x02\xc6\x134\x13\x02\xc6\x13\f\x1a\xfa@\x1a\f\x05\xc6\xfa\x80\x1a&&\x1a\x05\x80\x1a&&\x02-\x02\xc6\x13\x13\xfd:\x13\x1a\x1a\xfd\xe6&\x1a\x01\x00\x1a&&\x1a\xff\x00\x1a&\x00\x00\x00\x00\x01\x00\x9a\xff\x9a\x04\xa6\x05\xe6\x00\x14\x00\x00\t\x02\x16\x14\x0f\x01\x06\"'\x01&47\x0162\x1f\x01\x16\x14\x04\x93\xfd\xed\x02\x13\x13\x13\xa6\x134\x13\xfd\x1a\x13\x13\x02\xe6\x134\x13\xa6\x13\x04\xd3\xfd\xed\xfd\xed\x134\x13\xa6\x13\x13\x02\xe6\x134\x13\x02\xe6\x13\x13\xa6\x134\x00\x00\x00\x00\x01\x00Z\xff\x9a\x04f\x05\xe6\x00\x14\x00\x00\t\x01\x06\"/\x01&47\t\x01&4?\x0162\x17\x01\x16\x14\x04S\xfd\x1a\x134\x13\xa6\x13\x13\x02\x13\xfd\xed\x13\x13\xa6\x134\x13\x02\xe6\x13\x02\x93\xfd\x1a\x13\x13\xa6\x134\x13\x02\x13\x02\x13\x134\x13\xa6\x13\x13\xfd\x1a\x134\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00#\x00/\x00\x00\x0154&#!\x114&+\x01\"\x06\x15\x11!\"\x06\x1d\x01\x14\x163!\x11\x14\x16;\x01265\x11!26\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04\xc0&\x1a\xff\x00&\x1a\x80\x1a&\xff\x00\x1a&&\x1a\x01\x00&\x1a\x80\x1a&\x01\x00\x1a&\x01@\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02@\x80\x1a&\x01\x00\x1a&&\x1a\xff\x00&\x1a\x80\x1a&\xff\x00\x1a&&\x1a\x01\x00&\x01+\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x1b\x00\x00\x0154&#!\"\x06\x1d\x01\x14\x163!26\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04\xc0&\x1a\xfd\x00\x1a&&\x1a\x03\x00\x1a&\x01@\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02@\x80\x1a&&\x1a\x80\x1a&&\x01+\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00+\x007\x00\x00\x014/\x017654/\x01&#\"\x0f\x01'&#\"\x0f\x01\x06\x15\x14\x1f\x01\a\x06\x15\x14\x1f\x01\x1632?\x01\x17\x1632?\x016\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04}\x13\xb5\xb5\x13\x13Z\x13\x1b\x1a\x13\xb5\xb5\x13\x1a\x1b\x13Z\x13\x13\xb5\xb5\x13\x13Z\x13\x1b\x1a\x13\xb5\xb5\x13\x1a\x1b\x13Z\x13\x01\x83\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01\x9e\x1a\x13\xb5\xb5\x13\x1a\x1b\x13Z\x13\x13\xb5\xb5\x13\x13Z\x13\x1b\x1a\x13\xb5\xb5\x13\x1a\x1b\x13Z\x13\x13\xb5\xb5\x13\x13Z\x13\x01\xce\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x17\x00#\x00\x00\x014/\x01&\"\a\x01'&\"\x0f\x01\x06\x15\x14\x17\x01\x16327\x01>\x01\x10\x02\x04 $\x02\x10\x12$ \x04\x05\x04\x12[\x134\x13\xfeh\xe2\x134\x13[\x12\x12\x01j\x13\x1a\x1b\x13\x02\x1f\x12\xfc\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x03\"\x1c\x12Z\x13\x13\xfei\xe2\x13\x13Z\x12\x1c\x1b\x12\xfe\x96\x13\x13\x02\x1f\x12J\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00:\x00F\x00\x00%54&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x014.\x01#\"\a\x06\x1f\x01\x1632767632\x16\x15\x14\x06\a\x0e\x01\x1d\x01\x14\x16;\x01265467>\x04$\x10\x02\x04 $\x02\x10\x12$ \x04\x03\x80\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x01\x00o\xa6W\xf3\x80\x0f\x17\x84\a\f\x10\t5!\"40K(0?i\x12\x0e\xc0\x0e\x12+! \":\x1f\x19\x01\x80\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xa0\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x02\xaeX\x96R\xd5\x18\x12d\x06\fD\x18\x184!&.\x16\x1cuC$\x0e\x12\x12\x0e\x13=\x13\x12\x151/J=\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x1e\x00.\x00:\x00\x00%54&+\x01\x114&#!\"\x06\x1d\x01\x14\x16;\x01\x11#\"\x06\x1d\x01\x14\x163!26\x0354&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x04\x10\x02\x04 $\x02\x10\x12$ \x04\x04\x00\x12\x0e`\x12\x0e\xfe\xc0\x0e\x12\x12\x0e``\x0e\x12\x12\x0e\x01\xc0\x0e\x12\x80\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x02\x80\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xa0\xa0\x0e\x12\x02\x00\x0e\x12\x12\x0e\xa0\x0e\x12\xfe\xc0\x12\x0e\xa0\x0e\x12\x12\x03\x8e\xa0\x0e\x12\x12\x0e\xa0\x0e\x12\x12\xc1\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00/\x00_\x00\x00\x01#\"&=\x0146;\x01.\x01'\x15\x14\x06+\x01\"&=\x01\x0e\x01\a32\x16\x1d\x01\x14\x06+\x01\x1e\x01\x17546;\x012\x16\x1d\x01>\x01\x01\x15\x14\x06+\x01\x0e\x01\a\x15\x14\x06+\x01\"&=\x01.\x01'#\"&=\x0146;\x01>\x017546;\x012\x16\x1d\x01\x1e\x01\x1732\x16\x04\xadm\x1a&&\x1am \xa1l&\x1a\x80\x1a&l\xa1 m\x1a&&\x1am \xa1l&\x1a\x80\x1a&l\xa1\x01s&\x1a\x8f%\xeb\xa1&\x1a\x80\x1a&\xa1\xeb%\x8f\x1a&&\x1a\x8f%\xeb\xa1&\x1a\x80\x1a&\xa1\xeb%\x8f\x1a&\x02\x00&\x1a\x80\x1a&l\xa1 m\x1a&&\x1am \xa1l&\x1a\x80\x1a&l\xa1 m\x1a&&\x1am \xa1\x01,\x80\x1a&\xa1\xeb%\x8f\x1a&&\x1a\x8f%\xeb\xa1&\x1a\x80\x1a&\xa1\xeb%\x8f\x1a&&\x1a\x8f%\xeb\xa1&\x00\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00#\x00/\x00;\x00\x00\x01\a\x06\"/\x01\a\x06\"/\x01&4?\x01'&4?\x0162\x1f\x01762\x1f\x01\x16\x14\x0f\x01\x17\x16\x146\x10.\x01 \x0e\x01\x10\x1e\x01 6\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04I\x92\n\x1a\n\x89\x89\n\x1a\n\x92\n\n\x89\x89\n\n\x92\n\x1a\n\x89\x89\n\x1a\n\x92\n\n\x89\x89\n͒\xfa\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\x01r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01ɒ\n\n\x89\x89\n\n\x92\n\x1a\n\x89\x89\n\x1a\n\x92\n\n\x89\x89\n\n\x92\n\x1a\n\x89\x89\n\x1a\x19\x01(\xfa\x92\x92\xfa\xfe\xd8\xfa\x92\x92\x02_\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x14\x00 \x00,\x00\x00\t\x01\x06\"'\x01&4?\x0162\x1f\x01\x0162\x1f\x01\x16\x14\x16\x10.\x01 \x0e\x01\x10\x1e\x01 6\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04\x93\xfeZ\x134\x13\xfe\xda\x13\x13f\x134\x13\x93\x01\x13\x134\x13f\x13z\x92\xfa\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\x01r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02\xd3\xfeZ\x13\x13\x01&\x134\x13f\x13\x13\x93\x01\x13\x13\x13f\x134\xfa\x01(\xfa\x92\x92\xfa\xfe\xd8\xfa\x92\x92\x02_\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x85\x00\t\x00\x12\x00\"\x00\x00\x014'\x01\x1632>\x02\x05\x01&#\"\x0e\x01\x15\x14\x00\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x05 W\xfd\x0e\x89\xa0oɒV\xfc\x19\x02\U000c7954\xfa\x92\x05 z\xcd\xfe\xe3\xfe\xc8\xfe\xe3\xcdzz\xcd\x01\x1d\x018\x01\x1d\xcd\x02\x83\xa1\x86\xfd\x0fYW\x92˼\x02\xf2[\x92\xfc\x94\xa2\x01?\xfe\xc6\xfe\xe2\xcezz\xce\x01\x1e\x01:\x01\x1d\xcezz\xce\x00\x00\x01\x00@\xff5\x06\x00\x05K\x00 \x00\x00\x01\x15\x14\x06#!\x01\x16\x14\x0f\x01\x06#\"'\x01&547\x01632\x1f\x01\x16\x14\a\x01!2\x16\x06\x00A4\xfd@\x01%&&K%54'\xfdu%%\x02\x8b&54&K&&\xfe\xdb\x02\xc04A\x02\x80\x805K\xfe\xda$l$L%%\x02\x8c%54'\x02\x8a&&J&j&\xfe\xdbK\x00\x00\x01\x00\x00\xff5\x05\xc0\x05K\x00 \x00\x00\x01\x14\a\x01\x06#\"/\x01&47\x01!\"&=\x01463!\x01&4?\x01632\x17\x01\x16\x05\xc0%\xfdu'43'K&&\x01%\xfd@4AA4\x02\xc0\xfe\xdb&&K&45&\x02\x8b%\x02@6%\xfdu%%K&j&\x01%K5\x805K\x01&$l$K&&\xfdu#\x00\x00\x01\x005\xff\x80\x06K\x05@\x00!\x00\x00\x01\x14\x0f\x01\x06#\"'\x01\x11\x14\x06+\x01\"&5\x11\x01\x06\"/\x01&547\x01632\x17\x01\x16\x06K%K&56$\xfe\xdaK5\x805K\xfe\xda$l$K&&\x02\x8b#76%\x02\x8b%\x0253'K&&\x01%\xfd@4AA4\x02\xc0\xfe\xdb&&K&45&\x02\x8b%%\xfdu'\x00\x00\x00\x00\x01\x005\xff\xb5\x06K\x05\x80\x00\"\x00\x00\x01\x14\a\x01\x06#\"'\x01&54?\x01632\x17\x01\x1146;\x012\x16\x15\x11\x01632\x1f\x01\x16\x06K%\xfdu'45%\xfdu&&J'45%\x01&L4\x804L\x01&%54'K%\x02\xc05%\xfdt%%\x02\x8c$65&K%%\xfe\xda\x02\xc04LL4\xfd@\x01&%%K'\x00\x00\x01\x00\x00\xff\x80\a\x00\x05\xc0\x00,\x00\x00\x00\x14\a\x01\x06\"&5\x11#\"\x0e\x05\x15\x14\x17\x14\x16\x15\x14\x06#\"'.\x02'\x02547\x12!3\x11462\x17\x01\a\x00\x13\xfe\x00\x134&\xe0b\x9b\x99qb>#\x05\x05\x11\x0f\x10\f\a\f\x0f\x03\u007f5\xa2\x02\xc9\xe0&4\x13\x02\x00\x03\x9a4\x13\xfe\x00\x13&\x1a\x01\x00\f\x1f6Uu\xa0e7D\x06#\t\x0f\x14\x11\t\x1a\"\a\x01\x1d\xa6dž\x01\x93\x01\x00\x1a&\x13\xfe\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x17\x00/\x00\x00\x00\x14\a\x01\x17\x16\x14\x06#!\"&5\x11462\x1f\x01\x0162\x1f\x01\x01\x11\x14\x06\"/\x01\x01\x06\"/\x01&47\x01'&463!2\x16\x02\xf3\n\xfe\xb4\x90\x13&\x1a\xfe@\x1a&&4\x13\x90\x01L\n\x1a\nr\x03\x17&4\x13\x90\xfe\xb4\n\x1a\nr\n\n\x01L\x90\x13&\x1a\x01\xc0\x1a&\x01\xed\x1a\n\xfe\xb4\x90\x134&&\x1a\x01\xc0\x1a&\x13\x90\x01L\n\nr\x03I\xfe@\x1a&\x13\x90\xfe\xb4\n\nr\n\x1a\n\x01L\x90\x134&&\x00\x00\x00\x00\x02\x00\r\xff\x8d\x05\xf3\x05s\x00\x17\x00/\x00\x00\x01\x11\x14\x06\"/\x01\x01\x06\"/\x01&47\x01'&463!2\x16\x00\x14\a\x01\x17\x16\x14\x06#!\"&5\x11462\x1f\x01\x0162\x1f\x01\x03\x00&4\x13\x90\xfe\xb4\n\x1a\nr\n\n\x01L\x90\x13&\x1a\x01\xc0\x1a&\x02\xf3\n\xfe\xb4\x90\x13&\x1a\xfe@\x1a&&4\x13\x90\x01L\n\x1a\nr\x02@\xfe@\x1a&\x13\x90\xfe\xb4\n\nr\n\x1a\n\x01L\x90\x134&&\x02\x93\x1a\n\xfe\xb4\x90\x134&&\x1a\x01\xc0\x1a&\x13\x90\x01L\n\nr\x00\x00\x00\x00\x01\x00\x00\x00\x00\x05\x80\x05\x80\x00#\x00\x00\x01\x15\x14\x06#!\x11\x14\x06+\x01\"&5\x11!\"&=\x01463!\x1146;\x012\x16\x15\x11!2\x16\x05\x808(\xfe`8(\xc0(8\xfe`(88(\x01\xa08(\xc0(8\x01\xa0(8\x03 \xc0(8\xfe`(88(\x01\xa08(\xc0(8\x01\xa0(88(\xfe`8\x00\x00\x00\x00\x01\x00\x00\x02\x00\x05\x80\x03\x80\x00\x0f\x00\x00\x01\x15\x14\x06#!\"&=\x01463!2\x16\x05\x808(\xfb@(88(\x04\xc0(8\x03 \xc0(88(\xc0(88\x00\x00\x01\x00z\xff\x80\x06\x06\x05\x80\x005\x00\x00\x01\x1e\x01\x0f\x01\x0e\x01'%\x11\x14\x06+\x01\"&5\x11\x05\x06&/\x01&67-\x01.\x01?\x01>\x01\x17\x05\x1146;\x012\x16\x15\x11%6\x16\x1f\x01\x16\x06\a\x05\x05\xca.\x1b\x1a@\x1ag.\xfe\xf6L4\x804L\xfe\xf6.g\x1a@\x1a\x1b.\x01\n\xfe\xf6.\x1b\x1a@\x1ag.\x01\nL4\x804L\x01\n.g\x1a@\x1a\x1b.\xfe\xf6\x01\xe6\x1ag.n.\x1b\x1a\x99\xfe\xcd4LL4\x013\x99\x1a\x1b.n.g\x1a\x9a\x9a\x1ag.n.\x1b\x1a\x99\x0134LL4\xfe͙\x1a\x1b.n.g\x1a\x9a\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\v\x00\x1b\x00-\x00\x00\x00 \x04\x12\x10\x02\x04 $\x02\x10\x12\x0154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x03\x134'&+\x01\"\a\x06\x15\x13\x14\x16;\x0126\x02/\x01\xa2\x01a\xce\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x02\xb2\x12\r\xc0\r\x14\x14\r\xc0\r\x12\x02\x12\n\n\x0e\xdc\x0e\n\n\x11\x14\x0e\xb9\x0e\x13\x05\x80\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xfb\xef\xbe\x0e\x13\x14\r\xbe\r\x14\x13\x01f\x02m\f\x06\b\b\x06\f\xfd\x93\n\x0f\x0f\x00\x00\x00\x04\x00\x00\x00\x00\x06\x00\x05@\x00\r\x00\x16\x00\x1f\x00J\x00\x00%5\x115!\x15\x11\x15\x14\x16;\x0126\x013'&#\"\x06\x14\x16$4&#\"\x0f\x0132\x05\x11\x14\x06+\x01\x11\x14\x06#!\"&5\x11#\"&5\x11463!\"&4632\x1f\x017632\x16\x14\x06#!2\x16\x03\xa0\xfe\xc0$\x1c\xc0\x1c$\xfe8\xc3~\x1a+(88\x02\xd88(+\x1a}\xc2(\x01\xb0\x12\x0e`8(\xfb\xc0(8`\x0e\x12\x12\x0e\x01\xb8]\x83\x83]k=\x80\x80=k]\x83\x83]\x01\xb8\x0e\x12\xb48\x01\xd4\xc0\xc0\xfe,8\x19\x1b\x1b\x03e\xa1\x1f8P88P8\x1f\xa1\xa0\xfe\xc0\x0e\x12\xfe`(88(\x01\xa0\x12\x0e\x01@\x0e\x12\x83\xba\x83M\xa5\xa5M\x83\xba\x83\x12\x00\x02\x00\x00\x00\x00\a\x00\x05\x80\x00\x15\x00N\x00\x00\x004&#\"\x04\x06\a\x06\x15\x14\x16327>\x0176$32\x01\x14\a\x06\x00\a\x06#\"'.\x01#\"\x0e\x02#\"&'.\x0354>\x0254&'&54>\x027>\x047>\x0432\x1e\x02\x05\x00&\x1a\xac\xfe\xdc\xe3z\x13&\x1a\x18\x15\x1b^\x14\x89\x01\a\xb6\x1a\x02&\x14.\xfe\xeb\xdb\xd6\xe0\x94\x8a\x0f\x92\x17\x10/+>\x1d+)\x19\x02\b\x03\x03>J>\x1c\x02\tW\x97\xbem7\xb4\xb3\xb2\x95'\n'\x14\"'\x18'? \x10\x03&4&c\xa9\x87\x15\x18\x1a&\x13\x18^\x13|h\x01\x06_b\xe0\xfe\xc2ml/\x05J@L@#*\x04\x0e\x06\r\a#M6:\x13\x04D\n35sҟw$\x12\x0f\x03\t'%\n'\x11\x17\t\\\x84t\x00\x00\x00\x00\x02\x00\x00\xff\x00\x05\x80\x06\x00\x00\x0f\x003\x00\x00\x05\x15\x14\x06#!\"&=\x01463!2\x16\x01\x14\x0e\x05\x15\x14\x17'\x17.\x0454>\x0554'\x17'\x1e\x04\x05\x80\x13\r\xfa\xc0\r\x13\x13\r\x05@\r\x13\xff\x001O``O1C\x04\x01Z\x8c\x89Z71O``O1B\x03\x01Z\x8c\x89Z7\xa0@\r\x13\x13\r@\r\x13\x13\x04\x13N\x84]SHH[3`\x80\x01\x01)Tt\x81\xacbN\x84]SHH[3^\x82\x01\x01)Tt\x81\xac\x00\x00\x00\x00\x03\x00\x00\x00\x00\a\x00\x04\x80\x00\x11\x00!\x001\x00\x00\x01&'\x16\x15\x14\x00 \x00547\x06\a\x16\x04 $\x004&#\"\x06\x15\x14\x162654632\x00\x14\a\x06\x00 \x00'&476\x00 \x00\x17\x06\x80\x98\xe5=\xfe\xf9\xfe\x8e\xfe\xf9=嘅\x01\x91\x01\xd4\x01\x91\xfd\xb5\x1c\x14}\xb3\x1c(\x1czV\x14\x03l\x14\x8c\xfe'\xfd\xf2\xfe'\x8c\x14\x14\x8c\x01\xd9\x02\x0e\x01ٌ\x02@\xecuhy\xb9\xfe\xf9\x01\a\xb9yhu\xec\xcd\xf3\xf3\x029(\x1c\xb3}\x14\x1c\x1c\x14Vz\xfe\xd2D#\xe6\xfe\xeb\x01\x16\xe5#D#\xe5\x01\x16\xfe\xea\xe5\x00\x05\x00\x00\xff\xa0\a\x00\x04\xe0\x00\t\x00\x19\x00=\x00C\x00U\x00\x00%7.\x01547\x06\a\x12\x004&#\"\x06\x15\x14\x162654632%\x14\a\x06\x00\x0f\x01\x06#\"'&547.\x01'&476\x00!2\x177632\x1e\x03\x17\x16\x13\x14\x06\a\x01\x16\x04\x14\a\x06\a\x06\x04#76$7&'7\x1e\x01\x17\x02+NWb=嘧\x02\x89\x1c\x14}\xb3\x1c(\x1czV\x14\x01\x87\x01j\xfe\\i1\n\x12\fz\x10,\x8f\xf1X\x14\x14\x99\x01\xc6\x01\rY[6\n\x12\x05\x1a$\x1e!\x03\x10%\x9e\x82\x01\x18\b\x01\xc0\x14'F\x96\xfeu\xdeJ\xd4\x01iys\xa7?_\xaf9ɍ?\xc0kyhu\xec\xfe\xfe\x02n(\x1c\xb3}\x14\x1c\x1c\x14Vz\xef\a\x02\xbd\xfd\f\xbcY\x10F\n\x12\fKA؉\x1fL\x1f\xeb\x01\x10\x11a\x10\f\x13\x12\x13\x02\n\xfe0\x8b\xe52\x01\xf6-\x84F\"@Q\xac\xbe\x84\x12\uef33sp@\xb2_\x00\x00\x00\x00\x03\x00\x10\xff\x80\x06\xf0\x06\x00\x00\x0f\x00!\x003\x00\x00%54&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x03\x134'&+\x01\"\a\x06\x15\x13\x14\x16;\x0126\x03\x01\x16\a\x0e\x01#!\"&'&7\x01>\x012\x16\x04\x00\x13\r\xc0\r\x13\x13\r\xc0\r\x13\x02\x12\n\r\v\xdc\v\r\n\x11\x14\x0e\xb9\x0e\x13\r\x03\x00#%\x11;\"\xfa\x00\";\x11%#\x03\x00\x11\x01\x05`,@L\xa1\xa0\x05\x11\x80\a\f\x04\x03\x0f\x06\xfe\xe9\xfe\xfd5\x05\r`\t\x0e\x02\x0f\t\xbd\xfc\v\x02\x01\n`\t\x0e\x06\x02\xc2\x01\x03\xfe\x04\x0e\x03\x02\v\x80\x0e\x10\x02\x99\xa0L\xc0\x05`4\xc0L\xa1\xfdH\x13\x0e`\x06\x01\x03\r\x01\xfc\xfe\xfd\xc2\x11\x0e`\t\x02\v\xfc\xbd\a\x10\r\fa\t\x015\x01\x03\x01\x17\b\x10\x10\v\x80\r\x05\x9f\xa0L@\x00\x0f\x00\x00\xff\x00\x06\x80\x06\x00\x00\x03\x00\a\x00\v\x00\x0f\x00\x13\x00\x17\x00\x1b\x00\x1f\x00#\x003\x007\x00;\x00?\x00O\x00s\x00\x00\x17!\x11!\x01!\x11!%!\x11!\x01!\x11!%!\x11!\x01!\x11!\x01!\x11!\x01!\x11!%!\x11!\x01\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126\x01!\x11!%!\x11!\x01!\x11!7\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126%\x11\x14\x06#!\"&5\x1146;\x01546;\x012\x16\x1d\x01!546;\x012\x16\x1d\x0132\x16\x80\x01 \xfe\xe0\x01`\x01@\xfe\xc0\xfe\xa0\x01 \xfe\xe0\x01`\x01@\xfe\xc0\xfe\xa0\x01 \xfe\xe0\x02\xe0\x01@\xfe\xc0\xfe\x80\x01@\xfe\xc0\x03\x00\x01 \xfe\xe0\xfe\x80\x01@\xfe\xc0\xfe\xa0\x13\r@\r\x13\x13\r@\r\x13\x02\xe0\x01 \xfe\xe0\xfe\x80\x01@\xfe\xc0\x01\x80\x01 \xfe\xe0 \x13\r@\r\x13\x13\r@\r\x13\x01\x80L4\xfa\x804LL4\x80^B@B^\x01\x80^B@B^\x804L\x80\x01 \xfe\xe0\x01 @\x01@\xfe\xc0\x01@@\x01 \xfc\x00\x01 \x01\xc0\x01 \xfc\x00\x01 @\x01@\x02 \x01 \r\x13\x13\r\xfe\xe0\r\x13\x13\xfc\xad\x01@@\x01 \xfe\xe0\x01 \xc0\x01 \r\x13\x13\r\xfe\xe0\r\x13\x13M\xfb\x004LL4\x05\x004L`B^^B``B^^B`L\x00\x00\x00\x03\x00\x00\xff\xa0\a\x00\x05\xe0\x00\x12\x007\x00q\x00\x00\x01\x06\a.\x04+\x01\"&=\x0146;\x012\x00\x14\a\x01\x06#\"&=\x01\"\x0e\x01.\x06'67\x1e\x043!54632\x17\x01\x12\x14\a\x01\x06#\"&=\x01!\"\x0e\x02\a\x06\a\x0e\x06+\x01\"&=\x0146;\x012>\x02767>\x063!54632\x17\x01\x02\x9amBZxPV3!\x12\x0e\xc0\x0e\x12\x1emBZxPV3!\xc0\x0e\x12\n\xfe\xc1\x00\x00\x00\x01\x00\x00\xff\x00\a\x00\x05\x00\x00&\x00\x00\x00\x10\x02\x04#\"'\x06\x05\x06\a\x06&'5&6&>\x027>\x057&\x0254>\x01$32\x04\a\x00\xf0\xfed\xf4FK\xc6\xfe\xfa1A\x11\x1b\x04\x03\x05\x01\n\x02\f\x02\a0\x15)\x18\x1e\v\x9d\xb5\x8e\xf0\x01L\xb6\xf4\x01\x9c\x03.\xfe\xa4\xfe٫\b\xafC\x0e\b\x02\x16\x12\x01\x04\x10\x04\x0f\x03\x0e\x02\b5\x178.H(Y\x01\x06\x96\x82\xed\xace\xab\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00#\x003\x00C\x00\x00\x01\x15\x14\x02\x04 $\x02=\x01463!2\x16\x1d\x01\x14\x1e\x032>\x03=\x01463!2\x16\x01\x11\x14\x06#!\"&5\x11463!2\x16\x05\x11\x14\x06#!\"&5\x11463!2\x16\x06\x00\xc5\xfe\xa1\xfeH\xfe\xa1\xc5&\x1a\x01\x80\x1a&/\x027\x03#\"&463!2\x1e\x04\x17!2\x16\x02\x80LhLLh\x03\xccLhLLh\xcc!\x18\xfb\xec\r\x18\x03\x98\x1a&&\x1a\xfc\x00\x1a&\x10\x10\x1b\x02\xb1\xcc\x1a&&\x1a\x01\x00\x10\x19\x0e\f\x04\a\x01\x04\xb1\x1a&4hLLhLLhLLhL\x03\xc0\xfe\x00\x18%\x03z<\n\x100&4&&\x1a\v)\x1f1\x05\x037&4&\r\x12\x1f\x15&\a&\x00\x00\x00\x00\x01\x00\x00\x00\x00\x06\x80\x05\x80\x00\x14\x00\x00\x01\x11\x14\x06#!\"&5\x11463!2\x16\x1d\x01!2\x16\x06\x80\x84\\\xfb@\\\x84\x84\\\x01@\\\x84\x02\xa0\\\x84\x03\xa0\xfd@\\\x84\x84\\\x03\xc0\\\x84\x84\\ \x84\x00\x00\x00\x00\x02\x00\x00\x00\x00\aW\x05\x80\x00\x13\x00*\x00\x00\x01\x14\a\x01\x0e\x01#!\"&547\x01>\x013!2\x16\x01\x15!\"\x06\a\x01\a4&5\x11463!2\x16\x1d\x01!2\x16\aW\x1f\xfe\xb0+\x9bB\xfb\xc0\"5\x1f\x01P+\x9bB\x04@\"5\xfe\xa9\xfc\xc0^\xce=\xfe\xaf\x05\x01\x84\\\x01@\\\x84\x02 \\\x84\x02H\x1f#\xfet3G\x1a\x1e\x1f#\x01\x8c3G\x1a\x01:\xa0_H\xfet\x06\x04\x11\x04\x03\xc0\\\x84\x84\\ \x84\x00\x00\x00\x01\x00@\xff\x00\x02\xc0\x06\x00\x00\x1f\x00\x00\x00\x14\x06+\x01\x1132\x16\x14\a\x01\x06\"'\x01&46;\x01\x11#\"&47\x0162\x17\x01\x02\xc0&\x1a\x80\x80\x1a&\x13\xff\x00\x134\x13\xff\x00\x13&\x1a\x80\x80\x1a&\x13\x01\x00\x134\x13\x01\x00\x04\xda4&\xfc\x00&4\x13\xff\x00\x13\x13\x01\x00\x134&\x04\x00&4\x13\x01\x00\x13\x13\xff\x00\x00\x00\x00\x01\x00\x00\x01@\a\x00\x03\xc0\x00\x1f\x00\x00\x00\x14\a\x01\x06\"&=\x01!\x15\x14\x06\"'\x01&47\x0162\x16\x1d\x01!5462\x17\x01\a\x00\x13\xff\x00\x134&\xfc\x00&4\x13\xff\x00\x13\x13\x01\x00\x134&\x04\x00&4\x13\x01\x00\x02\x9a4\x13\xff\x00\x13&\x1a\x80\x80\x1a&\x13\x01\x00\x134\x13\x01\x00\x13&\x1a\x80\x80\x1a&\x13\xff\x00\x00\x00\x00\x05\x00\x00\xff\x80\b\x00\x05\x80\x00\x03\x00\a\x00\r\x00\x11\x00\x15\x00\x00\x01\x11!\x11\x01\x11!\x11\x01\x15!\x113\x11\x01\x11!\x11\x01\x11!\x11\x02\x80\xff\x00\x02\x80\xff\x00\x05\x00\xf8\x00\x80\x05\x00\xff\x00\x02\x80\xff\x00\x02\x80\xfe\x00\x02\x00\x02\x00\xfc\x00\x04\x00\xfb\x80\x80\x06\x00\xfa\x80\x03\x80\xfd\x00\x03\x00\x01\x80\xfb\x80\x04\x80\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x000\x00@\x00\x00\x01\x06\a67\x06\a&#\"\x06\x15\x14\x17.\x01'\x06\x15\x14\x17&'\x15\x14\x16\x17\x06#\"'\x1e\x01\x17\x06#\"'\x1632>\x0354'6\x01\x11\x14\x06#!\"&5\x11463!2\x16\x05\x008AD\x19AE=\\W{\x05\x81\xe2O\x1d[/5dI\x1d\x16\r\x1a\x15kDt\x91\x1a\x18\x94\xaepČe1\x01?\x01*\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x03\x9e\x19\t(M&\rB{W\x1d\x13\ata28r=\x01\x19\x02Ku\x0e\b\x04?R\x01Z\x03^Gw\x9b\xa9T\x12\t-\x01\x02\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x01\x00\x00\xff\x80\x06\x00\x05\x80\x00$\x00\x00\x012\x16\x15\x11\x14\x06+\x01\x1137#546375&#\"\x06\x1d\x01#\x153\x11!\"&5\x11463\x04\xe0w\xa9\xa9w\xbc\xc7\x1e\xe5/Dz?s\x88\xa3\xc8\xc8\xfd\xecw\xa9\xa9w\x05\x80\xa9w\xfc@w\xa9\x02S\xe8\x9488\x01\xcf\t\xa0\x92\xab\xe8\xfd\xad\xa9w\x03\xc0w\xa9\x00\x00\x00\x00\a\x00\x00\xff\x80\a\x00\x05\x80\x00\x0f\x00\x17\x00\x1b\x00#\x00'\x00.\x00>\x00\x00\x004&#\"\x06\x15\x14\x1626546326\x14\x06\"&462\x01!5!\x00\x10& \x06\x10\x16 \x01!5!\x03!=\x01!\a!%\x11\x14\x06#!\"&5\x11463!2\x16\x03\xa0\x12\x0eB^\x12\x1c\x128(\x0e\xf2\x96Ԗ\x96\xd4\xfc\x96\x06\x00\xfa\x00\x04\x80\xe1\xfe\xc2\xe1\xe1\x01>\xfc\xe1\x01\x80\xfe\x80\x80\x06\x00\xfc\xc4@\xfd|\x06\x80K5\xfa\x005KK5\x06\x005K\x02\xb2\x1c\x12^B\x0e\x12\x12\x0e(8\bԖ\x96Ԗ\xfc\u0080\x01\x1f\x01>\xe1\xe1\xfe\xc2\xe1\x04\x02\x80\xfe\xc0v\x8a\x80\x80\xfb\x005KK5\x05\x005KK\x00\x02\x00\x00\xffH\x06\x93\x05\x80\x00\x15\x00G\x00\x00\x004&\"\x06\x15\x14\x17&#\"\x06\x14\x162654'\x1632\x01\x14\x06#\".\x02'\a\x17\x16\x15\x14\x06#\"'\x01\x06#\"&54\x12$32\x16\x15\x14\a\x017.\x0354632\x17\x1e\x04\x03@p\xa0p\x13)*Ppp\xa0p\x13)*P\x03\xc3b\x11\t'\"+\x03`\xdc\x1cN*(\x1c\xfda\xb0\xbd\xa3;\x012\xa0\xa3̓\x01c`\x03.\" b\x11\r\n\x06PTY9\x03\xb0\xa0ppP*)\x13p\xa0ppP*)\x13\xfe\x00\x11b \".\x03`\xdc\x1c(*N\x1c\x02\x9f\x83ͣ\xa0\x012\xbeͣ\xbd\xb0\xfe\x9d`\x03+\"'\t\x11b\n\x06MRZB\x00\x00\x00\x00\x06\x00\x00\xff\x0f\a\x80\x05\xf0\x00\a\x00\x11\x00\x1b\x00\u007f\x00\xbd\x00\xfb\x00\x00\x004&\"\x06\x14\x162\x014&\"\x06\x15\x14\x1626\x114&\"\x06\x15\x14\x1626\x01\x15\x14\x06\x0f\x01\x06\a\x16\x17\x16\x15\x14\a\x0e\x01#\"/\x01\x06\a\x06\a\x06+\x01\"&/\x01&'\a\x06#\"'&547>\x017&/\x01.\x01=\x0146?\x0167&'&547>\x0132\x1f\x0167676;\x012\x16\x1f\x01\x16\x177632\x17\x16\x15\x14\a\x0e\x01\a\x16\x1f\x01\x1e\x01\x01\x15\x14\a\x06\a\x16\x15\x14\a\x06#\"&'\x06\"'\x0e\x01#\"'&547&'&=\x014767&547>\x0232\x16\x1762\x176?\x012\x17\x16\x15\x14\a\x16\x17\x16\x11\x15\x14\a\x06\a\x16\x15\x14\a\x06#\"&'\x06\"'\x0e\x01#\"'&547&'&=\x014767&547>\x0232\x16\x1762\x176?\x012\x17\x16\x15\x14\a\x16\x17\x16\x03\x80\x96Ԗ\x96\xd4\x03\x96LhLKjKLhLKjK\xfe\x80\x0e\t\x9b\v\x15\"8\a\a\x17w\x13\v\ns%(\v\f\a\x17\xba\v\x12\x01\x17\")v\a\r\v\n\x90\a\n>\x10\x17\f\x98\n\x0e\x0e\t\x9b\v\x15\"8\a\a\x16x\x13\v\ns\"+\v\f\a\x17\xba\v\x12\x01\x17\")v\b\f\v\n\x90\a\f<\x0f\x17\v\x98\n\x0e\x02\x80\x95\f\x123\x04z\x02\bL\x0e\x14\x14\x14\x0eL\b\x02z\x043\x12\f\x95\x95\r\x113\x04\x04>8\x02\bL\x0e\x14\x14\x143)\x06\x04x\x043\x11\r\x95\x95\f\x123\x04z\x02\bL\x0e\x14\x14\x14\x0eL\b\x02z\x043\x12\f\x95\x95\r\x113\x04\x04>8\x02\bL\x0e\x14\x14\x143)\x06\x04x\x043\x11\r\x95\x02\x16Ԗ\x96Ԗ\xff\x004LL45KK\x0454LL45KK\xfe\x90\xb9\n\x13\x01\x18#)0C\v\t\f\a\x1ew\aZ\x13\fl/\x18\x0f\n\x99\n\x15Y\a\b\x85\x1b\t\n\x0eN\x16,&\x18\x01\x11\v\xb9\n\x13\x01\x18#)0C\v\t\f\b\x1ev\aZ\x12\x0el.\x18\x0f\n\x99\n\x15Y\a\b\x85\x1b\b\v\x10L\x160\"\x17\x02\x11\xfd\xe0\x8c\x10\x0f\x1b\x19q\x19\x04\x03G^\x15\x02\x02\x15^G\x03\x04\x19q\x19\x1b\x0f\x10\x8c\x10\x0f\x1d\x17q\x19\x04\x03\x02$ ]\x15\x02\x02G)\x02F\x03\x04\x19q\x17\x1d\x0f\x03\xf0\x8c\x10\x0f\x1b\x19q\x19\x04\x03G^\x15\x02\x02\x15^G\x03\x04\x19q\x19\x1b\x0f\x10\x8c\x10\x0f\x1d\x17q\x19\x04\x03\x02$ ]\x15\x02\x02G)\x02F\x03\x04\x19q\x17\x1d\x0f\x00\x00\x00\x00\x02\x00\x00\xff\x80\a\x00\x05\x00\x00%\x00O\x00\x00\x00\x10\x06\x04#\"'\x06\a\x06\a#\"&'&4>\x057>\x047.\x01546$ \x04\x01\x14\x06\a\x1e\x04\x17\x1e\x06\x14\a\x0e\x01'&'&'\x06# '\x1632$7>\x0154'\x1e\x01\x05\x80\xbc\xfe\xbb\xbfVZ|\x9a$2\x03\v\x13\x02\x01\x01\x03\x02\x05\x03\x06\x01\x05$\x10\x1d\x15\n|\x8e\xbc\x01E\x01~\x01E\x02<\x8e|\n\x15\x1d\x10$\x05\x01\x06\x03\x05\x02\x03\x01\x01\x03\x14\f2$\x9a|ZV\xfe\xf1\xc9:\x1e\xa1\x01(t}\x86\x17\x81\x96\x03\x8b\xfe\xea\xec\x89\x10X(\t\a\x10\r\x03\a\x06\x06\x04\a\x03\a\x01\x06&\x15%(\x18H\xd2w\x8b쉉\xfd\x89x\xd1H\x18(%\x15&\x06\x01\a\x03\a\x04\x06\x06\a\x03\x0e\x10\x01\a\t(X\x10\x84\x04ZT\\\xf0\x86MKG\xd6\x00\x00\x03\x00\x00\xff\x80\x06\x00\x06\x00\x00\a\x00<\x00m\x00\x00$4&\"\x06\x14\x162\x014&#!4654&#\x0e\x02\a\x06\a\x0e\x06+\x01\x1132\x1e\x04\x17\x16;\x01254'>\x014'654&'>\x017\x14\a\x16\x15\x14\a\x16\x15\x14\a\x16\x06+\x02\"&'&#!\"&5\x11463!6767>\x027632\x1e\x01\x15\x14\a32\x16\x01\x00&4&&4\x04\xa6N2\xfe\xa0`@`\x1a\x18%)\x167\x04&\x19,$)'\x10 \r%\x1d/\x170\x05Ӄy\xc0\x05\x1e#\x125\x14\x0f +\x801\t&\x03<\x01\xac\x8d$]`\xbb{t\x16\xfe\xe05KK5\x01\x12$e:1\x18\x17&+'3T\x86F0\xb0h\x98\xa64&&4&\x02\x803M:\xcb;b^\x1av\x85+\x17D\x052 5#$\x12\xfd\x80\x06\a\x0f\b\x11\x02I\xa7\x1a\x1e\x10IJ 2E\x19=\x11\x01\\$YJ!$MC\x15\x16eM\x8b\xa1-+(K5\x02\x805K\x18\x83K5\x19y\x84*%A\x8au]c\x98\x00\x00\x00\x03\x00\x00\xff\x00\x06\x00\x05\x80\x00\a\x00>\x00q\x00\x00\x004&\"\x06\x14\x162\x014&'>\x0154'654&'654&+\x01\"\a\x0e\x05+\x01\x1132\x1e\x05\x17\x16\x17\x1e\x02\x172654&5!267\x14\x06+\x01\x16\x15\x14\a\x0e\x01#\"'.\x03'&'&'!\"&5\x11463!27>\x01;\x012\x16\a\x15\x16\x15\x14\a\x16\x15\x14\a\x16\x01\x00&4&&4\x04\xa6+ \x0f\x145\x12#\x1e\x05bW\x80\x83\xd3\x050\x17/\x1d%\r \x10')$,\x19&\x047\x16)%\x18\x1a`@`\x01`2N\x80\x98h\xb00##\x86T3'\"(\v\x18\x130;e$\xfe\xee5KK5\x01 \x16t\x80\xbeip\x8c\xad\x01<\x03&\t1\x04&4&&4&\xfe\x00#\\\x01\x11=\x19E2\x1f&%I\x10\x1e\x1aURI\x02\x11\b\x0f\a\x06\xfd\x80\x12$#5 2\x05D\x17+\x85v\x1a^b;\xcb:M2g\x98c]vDEA%!bSV\x152M\x83\x18K5\x02\x805K(,,\x9e\x89\x05Me\x16\x15CM$!I\x00\x00\x00\x01\x00\x00\xff\xad\x03@\x05\xe0\x00\x12\x00\x00\x01\x11\x05\x06#\"&547\x13\x01&547%\x136\x03@\xfe?\x16\x12\x15\x15\x02V\xfe\x94\x198\x01\xf6\xe1\x13\x05\xe0\xfa\xc5\xec\f\x1d\x15\x06\x0e\x01\xf4\x01b\x1b\x15%\tI\x01\xc7)\x00\x00\x00\x00\x02\x00\x00\xff\x80\a\x00\x05\x80\x00\x1c\x009\x00\x00\x014.\x03\"\x0e\x02\a\x06\"'.\x03\"\x0e\x03\x15\x14\x17\t\x0167\x14\a\x01\x06\"'\x01.\x0454632\x1e\x02\x17>\x0332\x16\x06\x80+C`\\hxeH\x18\x12>\x12\x18Hexh\\`C+\xbb\x02E\x02D\xbc\x80\xe5\xfd\x91\x124\x12\xfd\x90\n#L\x81oP$$Po\x81>\xe0\xfe\x03\xacQ|I.\x103MC\x1c\x16\x16\x1cCM3\x10.I|Q\xa8\xbb\xfd\xd0\x02/\xbc\xa8\xdd\xe5\xfd\xa8\x12\x12\x02Z\b$_d\x8eC\xdc\xf8+I@$$@I+\xf8\x00\x00\x00\x00\x02\x00\x00\x00\x00\x06 \x05\x00\x00(\x00@\x00\x00%\x14\x16\x0e\x02#!\"&5\x11463!2\x16\x15\x14\x16\x0e\x02#!\"\x06\x15\x11\x14\x163!:\x02\x1e\x03\x00\x14\a\x01\x06\"&5\x11!\"&5\x11463!\x11462\x17\x01\x02\x80\x02\x01\x05\x0f\r\xfe\xc0w\xa9\xa9w\x01@\r\x13\x02\x01\x05\x0f\r\xfe\xc0B^^B\x01 \x01\x14\x06\x11\x06\n\x04\x03\xa0\x13\xfd\xe0\x134&\xfe@\x1a&&\x1a\x01\xc0&4\x13\x02 `\x04 \x15\x1a\r\xa9w\x02\xc0w\xa9\x13\r\x04 \x15\x1a\r^B\xfd@B^\x02\x04\a\v\x0224\x13\xfd\xe0\x13&\x1a\x01 &\x1a\x01\x80\x1a&\x01 \x1a&\x13\xfd\xe0\x00\x00\x04\x00\x00\xff\x80\x06\x00\x05\x80\x00\x03\x00\x0f\x00%\x005\x00\x0073\x11#7.\x01\"\x06\x15\x14\x16;\x0126\x013\x114&#\"\a35#\x16\x033\x1147>\x0132\x15\x01\x11\x14\x06#!\"&5\x11463!2\x16\xed\xe7\xe7\xf6\x01FtIG9\x01;H\x02I\xe7\x92x\x88I\x02\xe7\x03\x03\xe7\a\x0f<,t\x01ԩw\xfc@w\xa9\xa9w\x03\xc0w\xa9z\x02\xb6\xd64DD43EE\xfc\xa7\x01\x8e\x9a\x9eueB\xfd\x8c\x01\x84&\x12#1\x9d\x02s\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x02\x00\x00\xff\x00\x04\x80\x05\x80\x00\v\x00.\x00\x00\x01\x114&\"\x06\x15\x11\x14\x1626\x01\x14\x06#!\x03\x0e\x01+\x01\"'\x03!\"&5463\x11\"&463!2\x16\x14\x06#\x112\x16\x01\xe0\x12\x1c\x12\x12\x1c\x12\x02\xa0&\x1a\xfeS3\x02\x11\f\x01\x1b\x05L\xfel\x1a&\x9dc4LL4\x02\x804LL4c\x9d\x02\xa0\x01\xc0\x0e\x12\x12\x0e\xfe@\x0e\x12\x12\xfe\xae\x1a&\xfe\x1d\f\x11\x1b\x01\xe5&\x1a{\xc5\x02\x00LhLLhL\xfe\x00\xc5\x00\x00\x00\x02\x00\x00\x00\x00\a\x00\x06\x00\x00'\x00?\x00\x00\x01\x11\x14\x06#!\"&5\x11463!2\x16\x1d\x01\x14\x06#!\"\x06\x15\x11\x14\x163!265\x1146;\x012\x16\x01\x11\x14\x06\"/\x01\x01\x06\"/\x01&47\x01'&463!2\x16\x05\x80\xa9w\xfc\xc0w\xa9\xa9w\x02\xc0\x0e\x12\x12\x0e\xfd@B^^B\x03@B^\x12\x0e@\x0e\x12\x01\x80&4\x13\xb0\xfdt\n\x1a\nr\n\n\x02\x8c\xb0\x13&\x1a\x02\x00\x1a&\x02`\xfe\xc0w\xa9\xa9w\x03@w\xa9\x12\x0e@\x0e\x12^B\xfc\xc0B^^B\x01@\x0e\x12\x12\x03R\xfe\x00\x1a&\x13\xb0\xfdt\n\nr\n\x1a\n\x02\x8c\xb0\x134&&\x00\x02\x00\x00\x00\x00\x06\x00\x05\x00\x00\x17\x00@\x00\x00\x00\x14\a\x01\x06\"&5\x11!\"&5\x11463!\x11462\x17\t\x01\x11\x14\x06#!\"&54&>\x023!265\x114&#!*\x02.\x0354&>\x023!2\x16\x04\xa0\x13\xfd\xe0\x134&\xfe@\x1a&&\x1a\x01\xc0&4\x13\x02 \x01s\xa9w\xfe\xc0\r\x13\x02\x01\x05\x0f\r\x01@B^^B\xfe\xe0\x01\x14\x06\x11\x06\n\x04\x02\x01\x05\x0f\r\x01@w\xa9\x02\x9a4\x13\xfd\xe0\x13&\x1a\x01 &\x1a\x01\x80\x1a&\x01 \x1a&\x13\xfd\xe0\x013\xfd@w\xa9\x13\r\x04 \x15\x1a\r^B\x02\xc0B^\x02\x04\a\v\b\x04 \x15\x1a\r\xa9\x00\x03\x00\x00\xff\x80\x06\x80\x05\x80\x00\x06\x00\r\x00I\x00\x00\x01&5!\x15\x14\x16%5!\x14\a>\x017\x15\x14\x0e\x02\a\x06\a\x0e\x01\x15\x14\x1632\x16\x1d\x01\x14\x06#!\"&=\x014632654&'&'.\x03=\x01463!5463!2\x16\x1d\x01!2\x16\x01\xcaJ\xff\x00\xbd\x04\xc3\xff\x00J\x8d\xbd\x80S\x8d\xcdq*5&\x1d=CKu\x12\x0e\xfc\xc0\x0e\x12uKC=\x1d&5*q͍S8(\x01 ^B\x02@B^\x01 (8\x02\x8d\xa2\xd1`N\xa8\xf6`Ѣ\x1d\xa8\u0380G\x90tO\x056)\"M36J[E@\x0e\x12\x12\x0e@E[J63M\")6\x05Ot\x90G\x80(8`B^^B`8\x00\x00\x00\t\x00\x00\xff\x80\x06\x00\x05\x80\x00\a\x00\x0f\x00\x17\x00\x1f\x00'\x00,\x002\x00\x81\x00\x91\x00\x00\x016'&\a\x06\x17\x16'&\a\x06\x17\x1676'6'&\a\x06\x17\x16\x176&'&\x06\x17\x16\x176'&\a\x06\x17\x1e\x014#\"\x147&\x06\x17\x166\x014\x00 \x00\x15\x14\x12\x17\x16654'\x0e\x02.\x01'&'.\x03632\x1e\x01\x17\x1e\x0126767.\x03547&76\x16\x1f\x0162\x17>\x02\x17\x16\a\x16\x15\x14\x0e\x03\a\x16\x15\x14\x06\x15\x14\x1676\x12\x01\x11\x14\x06#!\"&5\x11463!2\x16\x02\a\x04\a\t\x05\x04\a\t\x17\x05\a\x06\x06\a\x05\x06/\x02\a\a\x01\x03\a\b\x16\x02\x01\x03\x06\b\x05\x06[\x02\v\t\x04\x02\v\t.\f\n=\x02\x16\x02\x02\x14\x02\x82\xfe\xd4\xfeX\xfe\xd4Ě\x12\x11\x01\x06\x134,+\b\x17\"\x02\x05\v\x03\v\x0e\x06\x12*\f\x10+, \x0e\a\x1a1JH'5\x18\x1d\x13G\x19\x1a:\x8c:\v#L\x13\x1d\x185\x1c+@=&#\x01\x11\x12\x9a\xc4\x01\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x01P\x06\a\a\x05\x06\a\a.\a\x03\x04\b\b\x03\x041\x04\x04\x02\x04\x05\x03\x02\x13\x01\a\x02\a\b\a\x06G\a\x04\x03\a\a\x04\x03\x04\x10\x10\x0f\a\x04\a\b\x04\x01E\xd4\x01,\xfe\xd4ԧ\xfe\xf54\x03\x10\f4+\x01\x03\x01\t\x1f\x1a;\x0f\x01\x05\v\b\a\x04\x1b\x16\x1c\x1c\a\x06/\x16\x06\x195cFO:>J\x06\x1b\x10\x10\x11\x11\a\x16\x1e\x06J>:O9W5$\x10\x04\x1f@(b\x02\f\x10\x034\x01\v\x02\x87\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x04\x00\x00\xff\x80\x06\x80\x05\xc0\x00\a\x00\x0f\x00'\x00?\x00\x00$4&\"\x06\x14\x162$4&\"\x06\x14\x162\x13\x11\x14\x06#!\"&5\x11463!\x1e\x013!267!2\x16\x01\x06#!\x11\x14\x06#!\"&5\x11!\"'&7\x0162\x17\x01\x16\x05\x00&4&&4\x01&&4&&4\xa68(\xfa@(88(\x01\xab\x15c=\x01\x00=c\x15\x01\xab(8\xfe\xbb\x11*\xff\x00&\x1a\xff\x00\x1a&\xff\x00*\x11\x11\x1f\x01\xc0\x126\x12\x01\xc0\x1f&4&&4&&4&&4&\x01 \xfe\xc0(88(\x01@(88HH88\x02`(\xfe@\x1a&&\x1a\x01\xc0('\x1e\x01\xc0\x13\x13\xfe@\x1e\x00\x00\x00\x00\x02\x00\x00\xff\x80\x05\xff\x05\x80\x001\x00c\x00\x00\x014&'.\x0254654'&#\"\x06#\"&#\"\x0e\x01\a\x06\a\x0e\x02\x15\x14\x16\x15\x14\x06\x14\x1632632\x16327>\x01\x127\x14\x02\x06\a\x06#\"&#\"\x06#\"&54654&54>\x02767632\x1632632\x16\x15\x14\x06\x15\x14\x1e\x02\x17\x1e\x01\x05\u007f\x0e\v\f\n\b\n\n\x04\t\x13N\x14<\xe8;+gC8\x89A`\u007f1\x19\x16\x18\x16\x18a\x199\xe19\xb5g\x81\xd5w\x80\x8c\xfc\x9b|\xca9\xe28\x18a\x19Ie\x16\x19$I\x80VN\x9a\xc2z<\xe7:\x13L\x14QJ\n\x04\x03\f\x02\x10\x12\x02\xc6,\x8b\x1b\x1e\x1c-\x1a\x17[\x16%\x12\x01\t0\x17\x18\x1661I\xe9\xef\x81(\xa0)\x17W,\x1d\x16\x1f$-\xd7\x01\x14\x8b\xa5\xfe\xbb\xfb7,\x1d\x1doI\x18X\x17(\xa1)o\xd5ζA;=N0\neT\x17Z\x17\r\x18\t \x04(\x9d\x00\x00\x01\x00\x00\x00\x00\x05\x80\x05\x80\x00O\x00\x00\x01\x14\x06\a\x06\a\x06#\".\x03'&'&\x00'&'.\x0454767>\x0132\x17\x16\x17\x1e\x02\x17\x1e\x02\x15\x14\x0e\x02\x15\x14\x1e\x02\x17\x1e\x01\x17\x1e\x0332>\x0232\x1e\x01\x17\x1e\x02\x17\x16\x17\x16\x05\x80\x14\v\x15e^\\\x1b4?\x1fP\tbM\u007f\xfe\xeeO0#\x03\x1e\v\x12\a382\x19W\x1b\x0e\a\x12#\v& \x0f\x03\x1d\x0e9C9\n\a\x15\x01Lĉ\x02\"\x0e\x1b\t\x1282<\x14\x0e\x1d*\x04\x199F\x13F\x06\x03\x01(\x1bW\x19283\a\x12\v\x1e\x03#0O\x01\x12\u007fMb\tP\x1f?4\x1b\\^e\x15\v\x14\x03\x06F\x13F9\x19\x04*\x1d\x0e\x14<28\x12\t\x1b\x0e\"\x02\x89\xc4L\x01\x15\a\n9C9\x0e\x1d\x03\x0f &\v#\x12\a\x00\x00\x00\x02\x00\x00\x00\x00\x05\x80\x05\x80\x00\x0f\x00\x1f\x00\x00\x01!\"\x06\x15\x11\x14\x163!265\x114&\x17\x11\x14\x06#!\"&5\x11463!2\x16\x04`\xfc\xc0B^^B\x03@B^^ީw\xfc\xc0w\xa9\xa9w\x03@w\xa9\x05\x00^B\xfc\xc0B^^B\x03@B^\xa0\xfc\xc0w\xa9\xa9w\x03@w\xa9\xa9\x00\x02\x00\x00\xff\x97\x05\x00\x05\x80\x00\x06\x00#\x00\x00\x01!\x11\x017\x17\x01\x132\x17\x1e\x01\x15\x11\x14\x06\a\x06#\"'\t\x01\x06#\"'.\x015\x1146763\x04\x80\xfc\x00\x01\xa7YY\x01\xa7\f\x17\x15!''!\x13\x190#\xfeG\xfeG$/\x17\x15!''!\x15\x17\x05\x00\xfb&\x01\x96UU\xfej\x05Z\t\r8\"\xfa\xf7\"8\r\b \x01\xa8\xfeX!\t\r8\"\x05\t\"8\r\t\x00\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00G\x00W\x00\x00\x014.\x04'.\x02#\"\x0e\x02#\".\x02'.\x01'.\x0354>\x0254.\x01'.\x05#\"\a\x0e\x01\x15\x14\x1e\x04\x17\x16\x00\x17\x1e\x0532676\x01\x11\x14\x06#!\"&5\x11463!2\x16\x05\x00\x04 1.-\x06\x05\x1c\x16\n\x0f+$)\r\a\x13\f\x16\x03c\x8e8\x02\r\x06\a)1)\n\x14\x03\x03\x18\x1a\x1b\x17\n\v05.D\x05\x05\r\a\x12\x02<\x019\xa4\x060\x12)\x19$\x109\x93\x15\x16\x01\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x01W\v\n\x17\x1b\x1a\x18\x03\x03\x14\n)1)\a\x06\r\x027\x8fc\x03\x16\f\x13\a\r)$+\x0f\n\x16\x1c\x05\x06-.1 \x04\x16\x15\x939\x10$\x19)\x120\x06\xa4\xfe\xc7<\x02\x12\a\r\x05\x05D.5\x039\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x01\x00,\x00\x00\x06T\x05\x00\x001\x00\x00\x01\x06\a\x16\x15\x14\x02\x0e\x01\x04# '\x16327.\x01'\x16327.\x01=\x01\x16\x17.\x01547\x16\x04\x17&54632\x1767\x06\a6\x06TC_\x01L\x9b\xd6\xfeҬ\xfe\xf1\xe1#+\xe1\xb0i\xa6\x1f!\x1c+*p\x93DNBN,y\x01[\xc6\b\xbd\x86\x8c`m`%i]\x04hbE\x0e\x1c\x82\xfe\xfd\xee\xb7m\x91\x04\x8a\x02}a\x05\v\x17\xb1u\x04&\x03,\x8eSXK\x95\xb3\n&$\x86\xbdf\x159s?\n\x00\x00\x00\x01\x00_\xff\x80\x03\xbf\x06\x00\x00\x14\x00\x00\x01\x11#\"\x06\x1d\x01!\x03#\x11!\x11#\x11!54632\x03\xbf\x9dV<\x01%'\xfe\xfe\xce\xff\x00\xffЭ\x93\x05\xf4\xfe\xf8HH\xbd\xfe\xd8\xfd\t\x02\xf7\x01(ں\xcd\x00\x00\x00\b\x00\x00\xff\xa7\x06\x00\x05\x80\x00T\x00\\\x00d\x00k\x00s\x00z\x00\x82\x00\x88\x00\x00\x00 \x04\x12\x15\x14\x00\a\x06&54654'>\x0454'6'&\x06\x0f\x01&\"\a.\x02\a\x06\x17\x06\x15\x14\x1e\x03\x17\x06\a\x0e\x01\"&'.\x01/\x01\"\x06\x1e\x01\x1f\x01\x1e\x01\x1f\x01\x1e\x03?\x01\x14\x16\x15\x14\x06'&\x0054\x12\x136'&\a\x06\x17\x16\x176'&\a\x06\x17\x16\x176'&\a\x06\x16\x176'&\a\x06\x17\x16\x176'&\x06\x17\x1674\a\"\x15\x14727&\a\x06\x166\x02/\x01\xa2\x01a\xce\xfe\xdb\xe8\x1b\x1a\x0149[aA)O%-\x1cj'&]\xc6]\x105r\x1c-%O)@a[9'\n\x150BA\x17\x13;\x14\x14\x15\x10\x06\f\a\a\x16+\n\n\r>HC\x16\x17\x01\x1a\x1b\xe8\xfe\xdb\xceU\x03\n\n\x03\x03\n\t#\a\t\n\x06\a\t\n$\t\t\b\t\t\x122\b\f\f\b\t\r\fA\x03\x10\x0f\b\x11\x0fC\x11\x10\x11\x10:\x02\x10\x10\x04 \x05\x80\xce\xfe\x9f\xd1\xfb\xfeoM\x05\x18\x12\x03\x93=a-\x06\x186O\x83UwW[q\t(\x18\x18\x1a\x1a\v -\tq[WwU\x82P6\x18\x06$C\n\n+) (\x04\x03\t\x0e\x0e\x05\x05\n8\x17\x17&/\r\x01\x04\x04&e\x04\x12\x18\x05M\x01\x91\xfb\xd1\x01a\xfc\u007f\a\x05\x03\x05\a\x05\x06\x1a\x05\v\t\x06\x05\v\n&\a\f\r\a\x05\x1a$\b\v\f\t\b\v\f\x10\v\x05\x04\x16\x04\x06\a\r\x02\v\r\x02\x15\v\x02\x03\x18\b\x00\x00\x00\x01\x00\x00\x00\x00\x06\x80\x05\x80\x00%\x00\x00\x01\x11\x14\x06+\x01\"&5\x114&\"\x06\x1d\x0132\x16\x15\x11\x14\x06#!\"&5\x11463!54\x00 \x00\x06\x80&\x1a@\x1a&\x96Ԗ`(88(\xfc@(88(\x02\xa0\x01\a\x01r\x01\a\x03\xc0\xff\x00\x1a&&\x1a\x01\x00j\x96\x96j\xc08(\xfd\xc0(88(\x02@(8\xc0\xb9\x01\a\xfe\xf9\x00\x00\x00\x05\x00\x00\xff\x80\a\x80\x05\x80\x00\x0f\x00\x19\x00#\x00'\x00+\x00\x00\x012\x16\x15\x11\x14\x06#!\"&5\x11463\x15\"\x06\x1d\x01!54&#\x11265\x11!\x11\x14\x16375!\x1535!\x15\x06\xe0B^^B\xf9\xc0B^^B\r\x13\x06\x80\x13\r\r\x13\xf9\x80\x13\r`\x01\x00\x80\x01\x80\x05\x80^B\xfb@B^^B\x04\xc0B^\x80\x13\r\xe0\xe0\r\x13\xfb\x00\x13\r\x02`\xfd\xa0\r\x13\x80\x80\x80\x80\x80\x00\x03\x00\x00\x00\x00\x05\x80\x05\x80\x00\a\x00!\x00=\x00\x00\x00\x14\x06\"&462\x01\x16\a\x06+\x01\"&'&\x00'.\x01=\x01476;\x01\x16\x04\x17\x16\x12\x05\x16\a\x06+\x01\"&'&\x02\x00$'.\x01=\x01476;\x01\f\x01\x17\x16\x12\x01\x80p\xa0pp\xa0\x02p\x02\x13\x12\x1d\x87\x19$\x02\x16\xfe\xbb\xe5\x19!\x15\x11\x1a\x05\xa0\x01$qr\x87\x02\r\x02\x14\x12\x1c\x8f\x1a%\x01\f\xb2\xfe\xe3\xfe}\xd7\x19#\x14\x12\x1a\x03\x01\x06\x01ߺ\xbb\xd6\x01\x10\xa0pp\xa0p\xfe\xc5\x1c\x14\x15!\x19\xe5\x01E\x16\x02$\x19\x87\x1d\x12\x11\r\x87rq\xfeܢ\x1b\x14\x14#\x19\xd7\x01\x83\x01\x1d\xb2\r\x01%\x19\x8f\x1c\x12\x12\rֻ\xba\xfe!\x00\x05\x00\x00\x00\x00\x06\x00\x05\x00\x00\a\x00\x0f\x00\x1f\x00)\x00?\x00\x00\x00\x14\x06\"&462\x04\x14\x06\"&462\x17\x114&#!\"\x06\x15\x11\x14\x163!26\x01!\x03.\x01#!\"\x06\a\x01\x11\x14\x06#!\"&5\x1147\x13>\x013!2\x16\x17\x13\x16\x04\x10/B//B\x01//B//B\x9f\x13\r\xfb@\r\x13\x13\r\x04\xc0\r\x13\xfb2\x04\x9c\x9d\x04\x18\x0e\xfc\xf2\x0e\x18\x04\x04\xb1^B\xfb@B^\x10\xc5\x11\\7\x03\x0e7\\\x11\xc5\x10\x01aB//B//B//B/\xf0\x01@\r\x13\x13\r\xfe\xc0\r\x13\x13\x01\xed\x01\xe2\r\x11\x11\r\xfd~\xfe\xc0B^^B\x01@\x192\x02^5BB5\xfd\xa22\x00\x02\x00\x00\xff\x83\a\x00\x05\x80\x00.\x004\x00\x00\x012\x16\x14\x06#\x11\x14\x06#\x00%\x0e\x01\x16\x17\x0e\x01\x1e\x02\x17\x0e\x01&'.\x0467#\"&=\x01463! \x012\x16\x15\x03\x11\x00\x05\x11\x04\x06\x805KK5L4\xfe_\xfeu:B\x04&\x14\x06\x121/&\x1d\xa5\xac.\a-\x13\x1b\x03\n\x11zB^^B\x01\xe0\x01\xb3\x01\xcd4L\x80\xfev\xfe\x8a\x01y\x03\x80KjK\xfe\x804L\x01[!\x13^k'!A3;)\x1e:2\x1b*\x17\x81\x0454\x127&5462\x16\x15\x14\a\x16\x12\x15\x14\x1e\x03\x03\x90\x10;U gI\xfdv\x05\x14\xfe\xf60Z\x99\xba\x99Z0\x04\xc0L4\xfe@\x96Ԗ\xfe@4L2RX='\xea\xbe\b8P8\b\xbe\xea'=XR\xb0 U;\x10\x10Ig\x010\x01,\x02\x143lb??bl3\xfd\xec\xfe\xd44Lj\x96\x96jL4*\\\x93\xaa\xf2\x8b\x98\x01\x05\x1c\x13\x14(88(\x14\x13\x1c\xfe\xfb\x98\x8b\xf2\xaa\x93\\\x00\x00\x00\x01\x00\x02\xff\x80\x05\xfe\x05}\x00I\x00\x00\x01\x17\x16\a\x06\x0f\x01\x17\x16\a\x06/\x01\a\x06\a\x06#\"/\x01\a\x06'&/\x01\a\x06'&?\x01'&'&?\x01'&76?\x01'&76\x1f\x017676\x1f\x0176\x17\x16\x1f\x0176\x17\x16\x0f\x01\x17\x16\x17\x16\a\x05`\x8a\x1e\n\f(\xbc5\f\x1f\x1d)\xba0\n)\f\a\x1f\x14\x87\x87\x1c*)\n0\xba)\x1d\x1f\f5\xbc(\f\n\x1e\x8a\x8a\x1e\n\f(\xbc5\f\x1f\x1d)\xba0\n))\x1d\x87\x87\x1d))\n0\xba)\x1d\x1f\f5\xbc(\f\n\x1e\x02\x80\x87\x1c*)\n0\xba)\x1d\x1f\f5\xbc(\f\x02\x16\x8a\x8a\x1e\n\v)\xbc5\f\x1f\x1d)\xba0\n)*\x1c\x87\x87\x1c*)\n0\xba)\x1d\x1f\f5\xbc)\n\f\x1f\x8b\x8b\x1e\v\n)\xbc5\f\x1f\x1d)\xba0\n)*\x1c\x00\x03\x00\x00\xff\x80\a\x00\x05\x80\x00\a\x005\x00h\x00\x00$4&\"\x06\x14\x162\x014&#!4>\x0254&#\"\a\x06\a\x06\a\x06\a\x06+\x01\x1132\x1e\x013254'>\x014'654&'!267\x14\x06+\x01\x06\a\x16\x15\x14\a\x16\x06#\"'&#!\"&5\x11463!2>\x05767>\x0432\x16\x15\x14\a!2\x16\x01\x00&4&&4\x05\xa6N2\xfd\xc0\x1e$\x1eYG\x18B\x18\r(HG\x1eEG H\xbe\xc5Q\xbd\x05\x1e#\x125\x14\x0f\x01K4L\x80\x97i\xa9\x04!\x03<\x01\xac\x8d\x85\xbd\xa4;\xfe\xe05KK5\x01 \n\x17\x18\x15\x1b\x0e\x18\x02A#\r(\"/?&}\xa3\x16\x01vh\x98\xa64&&4&\x02\x803M\x1495S+C=\x8b,\x15@QQ\x199\xfd\x80@@\xa7\x1a\x1e\x10IJ 2E\x19=\x11L5i\x98>9\x15\x16eM\x8b\xa1E;K5\x02\x805K\t\x13\x11\x1c\x0f\x1c\x03J7\x15R>@#\x86zD<\x98\x00\x00\x03\x00\x00\xff\x80\a\x00\x05\x80\x005\x00=\x00q\x00\x00%3\x11#\".\x02'&'&'&'.\x04#\"\x06\x15\x14\x1e\x02\x15!\"\x06\x15\x14\x163!\x0e\x01\x15\x14\x17\x06\x14\x16\x17\x06\x15\x14\x1632>\x01$4&\"\x06\x14\x162\x13\x11\x14\x06#!\"\a\x06#\"&?\x01&547&'#\"&5463!&54632\x1e\x03\x17\x16\x17\x1e\x063!2\x16\x05` #A<(\x1d\b\x04H(\x0e\x18\x01\x13\x12\x16\x15\bGY\x1e$\x1e\xfd\xc02NL4\x01K\x0f\x145\x12#\x1e\x04aWTƾ\x01h&4&&4\xa6K5\xfe\xe0;\xa4\xbe\u007f\x8e\xb0\x01\x01=\x03!\x04\xa9i\x97\x98h\x01v\x16\xa3}&?/\"(\r#A\x02\x18\x0e\x1b\x15\x18\x17\n\x01 5K\x80\x02\x80\x182*!\t\x05Q@\x16.\x03'!&\x17=C+S59\x14M34L\x11=\x19E2 JI\x10\x18 UR@@&4&&4&\x02\x80\xfd\x805K;E\x9b\x8c\x05Lf\x16\x159>\x98ig\x98R\x157J\x03\x1c\x0f\x1c\x11\x13\tK\x00\x00\x00\x03\x00\x00\xff\x00\x06\x00\x06\x00\x00\a\x005\x00h\x00\x00\x044&\"\x06\x14\x162\x134#\"\a.\x01\"\a&#\"\x06\a\x114&#\"\x06\x15\x11\".\x02#\"\x06\x15\x14\x17\x16\x17\x16\x17\x16\x17\x16\x1d\x01!54>\x017\x14\a\x06\x15\x11\x14\x06#!\"&5\x114.\x05'&'.\x0454632\x17\x114632\x16\x1d\x01\x16\x17632\x176\x16\x05\x00&4&&4\xa6\xa7\x1a\x1e\x10IJ 2E\x19=\x11L43M\x1495S+C=\x8b,\x15@QQ\x199\x02\x80@@\x80E;K5\xfd\x805K\t\x13\x11\x1c\x0f\x1c\x03J7\x15R>@#\x86zD<\x98gi\x98>9\x15\x16eM\x8b\xa1Z4&&4&\x03<\xbd\x05\x1e#\x125\x14\x0f\x01K4LN2\xfd\xc0\x1e$\x1eYG\x18B\x18\r(HG\x1eEG H\xbe\xc5V\x85\xbd\xa4;\xfe\xe05KK5\x01 \n\x17\x18\x15\x1b\x0e\x18\x02A#\r(\"/?&}\xa3\x16\x01vh\x98\x97i\xa9\x04!\x03<\x01\xac\x00\x00\x00\x03\x00\x00\xff\x00\x06\x00\x06\x00\x004\x00<\x00p\x00\x00\x014.\x01=\x01!\x15\x14\x0e\x02\a\x06\a\x06\a\x06\a\x0e\x04\x15\x14\x1632>\x023\x11\x14\x163265\x11\x16327\x16267\x16326\x024&\"\x06\x14\x162\x01\x14\x06/\x01\x06#\"'\x06\a\x15\x14\x06#\"&5\x11\x06#\"&54>\x03767>\x065\x11463!2\x16\x15\x11\x14\x17\x16\x05\x80@@\xfd\x80\x182*!\t\x05Q@\x16.\x03'!&\x17=C+S59\x14M34L.9E2 JI\x10\x18 UR\x80&4&&4\x01&\x9b\x8c\x05Lf\x16\x156A\x98ig\x986Jy\x87#@>R\x157J\x03\x1c\x0f\x1c\x11\x13\tK5\x02\x805K;E\x02@TƾH #A<(\x1d\b\x04H(\x0e\x18\x01\x13\x12\x16\x15\bGY\x1e$\x1e\xfd\xc02NL4\x01K#5\x12#\x1e\x04a\x03=4&&4&\xfdD\x8e\xb0\x01\x01=\x03\x1e\a\xa9i\x97\x98h\x01v\x16\xa3}&?/\"(\r#A\x02\x18\x0e\x1b\x15\x18\x17\n\x01 5KK5\xfe\xe0;\xa4\xbe\x00\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x1f\x00+\x00\x00\x0154&#!764/\x01&\"\a\x01\a\x06\x14\x1f\x01\x01\x162?\x0164/\x01!26\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x05\x00&\x1a\xfe\n\xbd\x13\x13[\x126\x12\xfe\x96[\x12\x12[\x01j\x126\x12[\x12\x12\xbd\x01\xf6\x1a&\x01\x00\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02@\x80\x1a&\xbd\x134\x13[\x12\x12\xfe\x96[\x126\x12[\xfe\x96\x12\x12[\x126\x12\xbd&\x01+\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x1f\x00+\x00\x00\x004/\x01\x01&\"\x0f\x01\x06\x14\x1f\x01!\"\x06\x1d\x01\x14\x163!\a\x06\x14\x1f\x01\x1627\x017$\x10\x02\x04 $\x02\x10\x12$ \x04\x05\x05\x12[\xfe\x96\x126\x12[\x12\x12\xbd\xfe\n\x1a&&\x1a\x01\xf6\xbd\x13\x13[\x126\x12\x01j[\x01\r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02e6\x12[\x01j\x12\x12[\x126\x12\xbd&\x1a\x80\x1a&\xbd\x134\x13[\x12\x12\x01j[\xfe\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x1f\x00+\x00\x00\x004'\x01'&\"\x0f\x01\x01\x06\x14\x1f\x01\x162?\x01\x11\x14\x16;\x01265\x11\x17\x162?\x01$\x10\x02\x04 $\x02\x10\x12$ \x04\x05\x04\x12\xfe\x96[\x126\x12[\xfe\x96\x12\x12[\x126\x12\xbd&\x1a\x80\x1a&\xbd\x134\x13[\x01\x0e\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02f6\x12\x01j[\x12\x12[\xfe\x96\x126\x12[\x12\x12\xbd\xfe\n\x1a&&\x1a\x01\xf6\xbd\x13\x13[\xfd\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x1f\x00+\x00\x00\x004/\x01&\"\x0f\x01\x114&+\x01\"\x06\x15\x11'&\"\x0f\x01\x06\x14\x17\x01\x17\x162?\x01\x01\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x05\x04\x12[\x126\x12\xbd&\x1a\x80\x1a&\xbd\x134\x13[\x12\x12\x01j[\x126\x12[\x01j\x01\x0e\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02d6\x12[\x12\x12\xbd\x01\xf6\x1a&&\x1a\xfe\n\xbd\x13\x13[\x126\x12\xfe\x96[\x12\x12[\x01j\x00\xff\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\v\x01\xd8\x02\x18\x00\x00\x00 \x04\x12\x10\x02\x04 $\x02\x10\x12\x01\x0e\x01\a2>\x01767676\x17&67>\x01?\x01\x06&'\x14\a4&\x06'.\x02'.\x01'.\x03\"\x0e\x01#&\x0e\x02\a\x0e\x01\a6'&\a6&'3.\x02'.\x01\a\x06\x1e\x01\x15\x16\x06\x15\x14\x16\a\x0e\x01\a\x06\x16\x17\x16\x0e\x02\x0f\x01\x06&'&'&\a&'&\a6'&\a>\x01567>\x02#\x167>\x0176\x1e\x013\x166'\x16'&'&\a\x06\x17&\x0e\x01'.\x01'\"\a6&'6'.\x01\a\x0e\x01\x1e\x02\x17\x16\a\x0e\x02\a\x06\x16\a.\x01'\x16/\x01\"\x06&'&76\x17.\x01'\x06\a\x167>\x0176\x177\x16\x17&\a\x06\a\x16\a.\x02'\"\a\x06\a\x16\x17\x1e\x027\x16\a6\x17\x16\x17\x16\a.\x01\a\x06\x167\"\x06\x14\a\x17\x06\x167\x06\x17\x16\x17\x1e\x02\x17\x1e\x01\x17\x06\x16\a\"\x06#\x1e\x01\x17\x1e\x0276'&'.\x01'2\x1e\x02\a\x06\x1e\x02\x17\x1e\x01#2\x16\x17\x1e\x01\x17\x1e\x03\x17\x1e\x01\x17\x162676\x16\x17\x167\x06\x1e\x02\x17\x1e\x01\x1767\x06\x16765\x06'4.\x026326&'.\x01'\x06&'\x14\x06\x15\"'>\x017>\x03&\a\x06\a\x0e\x02\a\x06&'.\x0154>\x01'>\x017>\x01\x1667&'&#\x166\x17\x1674&7\x167\x1e\x01\x17\x1e\x0267\x16\x17\x16\x17\x16>\x01&/\x0145'.\x0167>\x0276'27\".\x01#6'>\x017\x1676'>\x017\x16647>\x01?\x016#\x1676'6&'6\x1676'&\x0367.\x01'&'6.\x02'.\x03\x06#\a\x0e\x03\x17&'.\x02\x06\a\x0e\x01\a&6'&\x0e\x04\a\x0e\x01\a.\x015\x1e\x01\x17\x16\a\x06\a\x06\x17\x14\x06\x17\x14\x02/\x01\xa2\x01a\xce\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x03D\x02\x0f\x06\x02\x05\x05\x01\x06\x10\x0e&\"\x11\x02\x17\x03\x03\x18\x03\x02\f\v\x01\x06\t\x0e\x02\n\n\x06\x01\x02\x0f\x02\x01\x03\x03\x05\x06\b\a\x01\x03\x06\x03\x06\x02\x03\v\x03\x0f\x10\n\x06\t\x03\a\x05\x01\x0f\x14\x03\b4\a\x05\x01\a\x01\r\x1c\x04\x03\x1a\x03\x05\a\a\x02\x01\x06\x05\x04\x03\v\x13\x04\a\t\x17\x06\x05$\x19!\x06\x06\a\f\x03\x02\x03\t\x01\f\a\x03#\x0f\x05\r\x04\t\n\x13\x05\x0e\x03\t\f\t\x04\x04\f\x0f\b\n\x01\x11\x10\b\x01\t\x05\b\b\x03\x1c\n\x13\x1b\a\x1b\x06\x05\x01\v\n\r\x02\x0e\x06\x02\r\n\x01\x03\x06\x05\x05\b\x03\a \n\x04\x18\x11\x05\x04\x04\x01\x03\x04\x0e\x03.0\x06\x06\x05\x10\x02\"\b\x05\x0e\x06\a\x17\x14\x02\a\x02\x04\x0f\x0e\b\x10\x06\x92Y\a\x05\x04\x02\x03\n\t\x06\x01+\x13\x02\x03\r\x01\x10\x01\x03\a\a\a\x05\x01\x02\x03\x11\r\r!\x06\x02\x03\x12\f\x04\x04\f\b\x02\x17\x01\x01\x03\x01\x03\x19\x03\x01\x02\x04\x06\x02\x1a\x0f\x02\x03\x05\x02\x02\b\t\x06\x01\x03\n\x0e\x14\x02\x06\x10\b\t\x16\x06\x05\x06\x02\x02\r\f\x14\x03\x05\x1b\b\n\f\x11\x05\x0f\x1c\a$\x13\x02\x05\v\a\x02\x05\x1a\x05\x06\x01\x03\x14\b\x0e\x1f\x12\x05\x03\x02\x02\x04\t\x02\x06\x01\x01\x14\x02\x05\x16\x05\x03\r\x02\x01\x03\x02\x01\t\x06\x02\v\f\x13\a\x01\x04\x06\x06\a\"\a\r\x13\x05\x01\x06\x03\f\x04\x02\x05\x04\x04\x01\x01\x03\x03\x01\a+\x06\x0f\a\x05\x02\x05\x18\x03\x19\x05\x03\b\x03\a\x05\n\x02\v\b\a\b\x01\x01\x01\x01\x01\x0f\a\n\n\x01\x0e\x11\x04\x15\x06\a\x04\x01\b\a\x01\t\a\x05\x05\x05\t\f\b\a\x05\x1f\x03\a\x02\x03\x04\x16\x02\x11\x03\x03\x12\r\n\x10\x03\f\t\x03\x11\x02\x0f\x16\x11\xbdΑ\x03\x13\x03\x12\x06\x01\a\t\x10\x03\x02\n\x04\v\x06\a\x03\x03\x05\x06\x02\x01\x15\x0f\x05\f\t\v\x06\x05\x02\x01\a\x0e\x05\x03\x0f\t\x0e\x04\r\x02\x03\x06\x02\x02\x13\x02\x04\x03\a\x13\x1b\x02\x04\x10\x10\x01\x05\x80\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xfe\xc5\x01\x11\x01\n\f\x01\a\b\x06\x06\b\x13\x02\x16\x01\x02\x05\x05\x16\x01\x10\r\x02\x06\a\x02\x04\x01\x03\t\x18\x03\x05\f\x04\x02\a\x06\x05\n\n\x02\x01\x01\x05\x01\x02\x02\x01\x05\x06\x04\x01\x04\x10\x06\x04\t\b\x02\x05\t\x04\x06\t\x13\x03\x06\x0e\x05\a\x11\r\b\x10\x04\b\x15\x06\x02\x04\x05\x03\x02\x02\x05\x16\x0f\x19\x05\b\t\r\r\t\x05\x01\x0e\x0f\x03\x06\x17\x02\r\n\x01\x0f\f\x04\x0f\x05\x18\x05\x06\x01\n\x01\x18\b\x01\x12\a\x02\x04\t\x04\x04\x01\x17\f\v\x01\x19\x01\x0f\b\x0e\x01\f\x0f\x04\x02\x05\a\t\a\x04\x04\x01\n\x04\x01\x05\x04\x02\x04\x14\x04\x05\x19\x04\t\x03\x01\x04\x02\a\b\f\x04\x02\x03\r\x02\x0f\x1a\x01\x02\x02\t\x01\x0e\a\x05\x10\t\x04\x03\x06\x06\f\x06\x03\x0e\b\x01\x01P\x8e\a\x01\x01\x10\x06\x06\b\v\x01\x1c\x11\x04\v\a\x02\x0e\x03\x05\x1b\x01 '\x04\x01\f-\x03\x03(\b\x01\x02\v\t\x06\x05#\x06\x06\x1c\t\x02\a\x0e\x06\x03\x0e\b\x02\x14*\x19\x04\x05\x15\x04\x03\x04\x04\x01\a\x15\x10\x16\x02\x06\x1b\x15\t\b$\x06\a\r\x06\n\x02\x02\x11\x03\x04\x05\x01\x02\"\x04\x13\b\x01\r\x12\v\x03\x06\x12\x06\x04\x05\b\x18\x02\x03\x1d\x0f!\x01\t\b\t\x06\a\x12\x04\b\x18\x03\t\x02\b\x01\t\x02\x01\x03\x1d\b\x04\x10\r\f\a\x01\x01\x13\x03\x0f\b\x03\x03\x02\x04\b*\x10\n!\x11\x10\x02\x0f\x03\x01\x01\x01\x04\x04\x01\x02\x03\x03\t\x06\v\r\x01\x11\x05\x1b\x12\x03\x04\x03\x02\a\x02\x03\x05\x0e\n(\x04\x03\x02\x11\v\a\b\t\t\b\x03\x12\x13\t\x01\x05\b\x04\x13\x10\t\x06\x04\x05\v\x03\x10\x02\f\n\b\b\a\a\x06\x02\b\x10\x04\x05\b\x01\v\x04\x02\r\v\t\x06\a\x02\x01\x01\x02\n\x06\x05\xfc\x82$\x99\x03\x03\x02\a\x01\a\f\x06\n\x02\x02\b\x03\x06\x02\x01\x01\x03\x03\x03\x01\x11\x05\x01\t\x05\x02\x06\x05\x14\x03\x05\x19\x06\x06\x03\x06\v\x02\t\x03\x04\x10\x03\x04\x05\x03\n2\r\x1f\x11\x19\x0f\x16\x04\a\x1b\b\x06\x00\x00\x03\x00\x15\xff\x15\x06~\x05\x80\x00\a\x00\x15\x00/\x00\x00$4&\"\x06\x14\x162\t\x01\x06#\"/\x01&547\x01\x1e\x01\x01\x14\a\x0e\x01#\"\x00\x10\x0032\x16\x17\x16\x14\a\x05\x15\x17>\x0232\x16\x01\x80&4&&4\x02\xaa\xfdV%54'j&&\x02\xa9'\x97\x02\xdc\x17/덹\xfe\xf9\x01\a\xb9:\u007f,\x10\x10\xfe\xdb\xc1\x05\x94{\t\x0f\x11&4&&4&\x01\xe4\xfdV%%l$65&\x02\xa9b\x97\x01\x8c'C\x86\xa7\x01\a\x01r\x01\a!\x1e\v\"\v\xa9\xe0k\x03[G\x14\x00\x00\x00\x06\x00\x00\x00\x00\a\x00\x05\x80\x00\x03\x00\a\x00\v\x00\x1b\x00+\x00;\x00\x00%!5!\x01!5!\x01!5!\x01\x11\x14\x06#!\"&5\x11463!2\x16\x19\x01\x14\x06#!\"&5\x11463!2\x16\x19\x01\x14\x06#!\"&5\x11463!2\x16\x04\x00\x02\x80\xfd\x80\xfe\x80\x04\x00\xfc\x00\x02\x80\x01\x80\xfe\x80\x02\x00&\x1a\xf9\x80\x1a&&\x1a\x06\x80\x1a&&\x1a\xf9\x80\x1a&&\x1a\x06\x80\x1a&&\x1a\xf9\x80\x1a&&\x1a\x06\x80\x1a&\x80\x80\x01\x80\x80\x01\x80\x80\xfc@\xff\x00\x1a&&\x1a\x01\x00\x1a&&\x01\xe6\xff\x00\x1a&&\x1a\x01\x00\x1a&&\x01\xe6\xff\x00\x1a&&\x1a\x01\x00\x1a&&\x00\x00\x01\x00\x05\xff\x80\x05{\x05\x00\x00\x15\x00\x00\x01\x16\a\x01\x11\x14\a\x06#\"'\x01&5\x11\x01&763!2\x05{\x11\x1f\xfe\x13'\r\f\x1b\x12\xff\x00\x13\xfe\x13\x1f\x11\x11*\x05\x00*\x04\xd9)\x1d\xfe\x13\xfd\x1a*\x11\x05\x13\x01\x00\x13\x1a\x01\xe6\x01\xed\x1d)'\x00\x00\x00\x04\x00\x00\x00\x00\a\x00\x06\x00\x00\x03\x00\x17\x00\x1b\x00/\x00\x00\x01!5!\x01\x11\x14\x06#!\"&5\x11!\x15\x14\x163!26=\x01#\x15!5\x01\x11!\x11463!5463!2\x16\x1d\x01!2\x16\x02\x80\x02\x00\xfe\x00\x04\x80^B\xfa@B^\x02\xa0&\x1a\x01@\x1a&`\xff\x00\x04\x00\xf9\x00^B\x01`8(\x02@(8\x01`B^\x05\x00\x80\xfd\x00\xfe B^^B\x01\xe0\xa0\x1a&&\x1a\xa0\x80\x80\x01\xe0\xfe\x80\x01\x80B^\xa0(88(\xa0^\x00\x00\x01\x00\x00\xff\x80\x06\x00\x05\x80\x00G\x00\x00\t\x0276\x17\x16\x15\x11\x14\x06#!\"'&?\x01\t\x01\x17\x16\a\x06#!\"&5\x11476\x1f\x01\t\x01\a\x06#\"'&5\x11463!2\x17\x16\x0f\x01\t\x01'&763!2\x16\x15\x11\x14\a\x06#\"'\x05\x03\xfe\x9d\x01c\x90\x1d)'&\x1a\xfe@*\x11\x11\x1f\x90\xfe\x9d\xfe\x9d\x90\x1f\x11\x11*\xfe@\x1a&('\x1e\x90\x01c\xfe\x9d\x90\x13\x1a\f\f(&\x1a\x01\xc0*\x11\x11\x1f\x90\x01c\x01c\x90\x1f\x11\x11*\x01\xc0\x1a&'\r\f\x1a\x13\x03\xe3\xfe\x9d\xfe\x9d\x90\x1f\x11\x11*\xfe@\x1a&('\x1e\x90\x01c\xfe\x9d\x90\x1e'(&\x1a\x01\xc0*\x11\x11\x1f\x90\x01c\x01c\x90\x13\x05\x11*\x01\xc0\x1a&('\x1e\x90\xfe\x9d\x01c\x90\x1e'(&\x1a\xfe@*\x11\x05\x13\x00\x00\x06\x00\x00\xff\x00\a\x80\x06\x00\x00\x11\x001\x009\x00A\x00S\x00[\x00\x00\x01\x06\a#\"&5\x1032\x1e\x01327\x06\x15\x14\x01\x14\x06#!\"&54>\x0532\x1e\x022>\x0232\x1e\x05\x00\x14\x06\"&462\x00\x10\x06 &\x106 \x01\x14\x06+\x01&'654'\x1632>\x0132\x02\x14\x06\"&462\x02Q\xa2g\x86Rp|\x06Kx;CB\x05\x04\x80\x92y\xfc\x96y\x92\a\x15 6Fe=\nBP\x86\x88\x86PB\n=eF6 \x15\a\xfc\x00\x96Ԗ\x96\xd4\x03V\xe1\xfe\xc2\xe1\xe1\x01>\x03!pR\x86g\xa2Q\x05BC;xK\x06|\x80\x96Ԗ\x96\xd4\x02\x80\x05{QN\x01a*+\x17%\x1d\x8b\xfd\x0ex\x8b\x8bx5eud_C(+5++5+(C_due\x052Ԗ\x96Ԗ\xfe\x1f\xfe\xc2\xe1\xe1\x01>\xe1\xfd\x9fNQ{\x05u\x8b\x1d%\x17+*\x01jԖ\x96Ԗ\x00\x00\x00\x00\x03\x00\x10\xff\x90\x06p\x05\xf0\x00!\x00C\x00i\x00\x00\x014/\x01&#\"\a\x1e\x04\x15\x14\x06#\".\x03'\x06\x15\x14\x1f\x01\x1632?\x016\x014/\x01&#\"\x0f\x01\x06\x15\x14\x1f\x01\x16327.\x0454632\x1e\x03\x176\x00\x14\x0f\x01\x06#\"/\x01&547'\x06#\"/\x01&4?\x01632\x1f\x01\x16\x15\x14\a\x17632\x1f\x01\x05\xb0\x1c\xd0\x1c(*\x1e\x03 \v\x13\a8(\x0f\x19\x1a\f\x1f\x03!\x1c\xce\x1b)(\x1c\x93\x1c\xfdA\x1c\xce\x1c('\x1d\x93\x1c\x1c\xd0\x1b)*\x1e\x03 \v\x13\a8(\x0f\x19\x1a\f\x1f\x03!\x03\u007fU\x93SxyS\xceSXXVzxT\xd0TU\x93SxyS\xceSXXVzxT\xd0\x01@(\x1c\xd0\x1c \x03\x1f\f\x1a\x19\x0f(8\a\x13\v \x03\x1f*(\x1c\xcf\x1b\x1a\x92\x1c\x02\xe8(\x1c\xcf\x1c\x1b\x92\x1c'(\x1c\xd0\x1b\x1f\x03\x1f\f\x1a\x19\x0f(8\a\x13\v \x03\x1f\xfd\xe1\xf0S\x92SU\xcfSx{VXXT\xd0T\xf0S\x92SU\xcfSx{VXXT\xd0\x00\x01\x00\x00\x00\x00\a\x80\x05\x80\x00\x1b\x00\x00\x01\x14\x06#!\"\x005467&54\x0032\x04\x17632\x16\x15\x14\a\x1e\x01\a\x80\xe1\x9f\xfb\xc0\xb9\xfe\xf9\x8et\x02\x01,Ԟ\x01\x01;F`j\x96)\x81\xa8\x01\x80\x9f\xe1\x01\a\xb9\x84\xdb6\x1c\x0f\xd4\x01,\xb0\x8e>\x96jK?\x1e\xd1\x00\x02\x00s\xff\x80\x06\r\x05\x80\x00\x17\x00!\x00\x00%\x16\x06#!\"&7\x01\x11#\"&463!2\x16\x14\x06+\x01\x11\x05\x01!\x01'5\x11#\x11\x15\x05\xf78Ej\xfb\x80jE8\x01\xf7@\x1a&&\x1a\x02\x00\x1a&&\x1a@\xfe\xec\xfe\xf0\x02\xc8\xfe\xf0\x14\x80XY\u007f\u007fY\x03\x19\x01\x8f&4&&4&\xfeqD\xfeS\x01\xad\x1f%\x01\x8f\xfeq%\x00\x00\x00\x00\a\x00\x01\xff\x80\a\x00\x05\x00\x00\a\x00N\x00\\\x00j\x00x\x00\x86\x00\x8c\x00\x00\x002\x16\x14\x06\"&4\x05\x01\x16\a\x06\x0f\x01\x06#\"'\x01\a\x06\a\x16\a\x0e\x01\a\x06#\"'&7>\x017632\x176?\x01'&'\x06#\"'.\x01'&67632\x17\x1e\x01\x17\x16\a\x16\x1f\x01\x01632\x1f\x01\x16\x17\x16\a\x056&'&#\"\a\x06\x16\x17\x1632\x03>\x01'&#\"\a\x0e\x01\x17\x1632\x01\x1754?\x01'\a\x0e\x01\a\x0e\x01\a\x1f\x01\x01'\x01\x15\a\x17\x16\x17\x1e\x01\x1f\x01\x017\x01\a\x06\a\x03\xa64&&4&\x01l\x01\xfb\x1c\x03\x05\x1e\x80\r\x10\x11\x0e\xfdNn\b\x04\x0e\x04\abS\x84\x91\x88VZ\v\abR\x84\x92SD\t\rzz\r\tDS\x92\x84Rb\a\x05)+U\x89\x91\x84Sb\a\x04\x0e\x04\bn\x02\xb2\x0e\x11\x10\r\x80\x1e\x05\x03\x1c\xfb\\.2Q\\dJ'.2Q\\dJ.Q2.'Jd\\Q2.'Jd\x01\x0e`!\x0eO\x1a\x03\x0e\x05\x02\x04\x01\xd7`\x02\xe0\x80\xfd\x00\xa0\t\x02\x05\x04\x0e\x04\x1a\x03`\x80\xfd\xf8\xb1\x02\v\x02\x80&4&&4\x1a\xfer\x14$#\x10@\a\b\x01\x83B\x04\x0110M\x8d5TNT{L\x8e5T\x1f\r\tII\t\r\x1fT5\x8eL;l'OT4\x8eM01\x01\x04B\x01\x83\b\a@\x10#$\x14\x8a*\x843;$*\x843;\xfd;3\x84*$;3\x84*$\x02\xa0:\v$\x14\b/\x1a\x03\x10\x04\x02\x03\x01\xe9 \x02@@\xfeQq`\b\x02\x04\x04\x10\x04\x1a\xfe\xc0@\x01\x98\x8a\x03\x04\x00\x00\x05\x00\x00\xff\x00\a\x00\x06\x00\x00\x1f\x00\"\x00%\x003\x00<\x00\x00\x012\x16\x15\x11\x14\x06#!\"&5\x11!\"&5\x11467\x01>\x013!2\x16\x15\x1163\a\x01!\t\x01!\x13\x01\x11!\x11\x14\x06#!\x11!\x1146\x01\x11!\x11\x14\x06#!\x11\x06\xa0(88(\xfc@(8\xfd\xe0(8(\x1c\x01\x98\x1c`(\x01\xa0(8D<\x80\xfe\xd5\x01+\xfd\x80\xfe\xd5\x01+\xc4\x01<\xfe\x808(\xfe`\x02\x00(\x03\xd8\xfe\x808(\xfe`\x04\x808(\xfb@(88(\x01 8(\x02\xa0(`\x1c\x01\x98\x1c(8(\xfe\xb8(\xd5\xfe\xd5\x02\xab\xfe\xd5\xfe\xa4\x01<\x01\xa0\xfe`(8\xfd\x80\x01\x00(`\xfc\xf8\x04\x80\xfe`(8\xfd\x80\x00\x00\x00\x01\x00\x04\xff\x84\x05|\x05|\x00?\x00\x00%\x14\x06#\"'\x01&54632\x17\x01\x16\x15\x14\x06#\"'\x01&#\"\x06\x15\x14\x17\x01\x1632654'\x01&#\"\x06\x15\x14\x17\x01\x16\x15\x14\x06#\"'\x01&54632\x17\x01\x16\x05|\x9eu\x87d\xfc\xf7qܟ\x9es\x02]\n=\x10\r\n\xfd\xa2Ofj\x92L\x03\b?R@T?\xfd\xbb\x1a\"\x1d&\x19\x01\x9a\n>\x10\f\n\xfef?rRX=\x02Ed\x97u\x9ed\x03\bs\x9c\x9f\xdeq\xfd\xa2\n\f\x10=\n\x02_M\x96jiL\xfc\xf7?T@R?\x02E\x18&\x1d \x1b\xfef\n\f\x10>\n\x01\x9a=XRr?\xfd\xbbb\x00\x04\x00\x00\xff\x80\x06\x00\x05\x80\x00\x03\x00!\x001\x00E\x00\x00)\x01\x11!\x013\x114&'\x01.\x01#\x11\x14\x06#!\"&5\x11#\x113\x11463!2\x16\x15\x01\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126\x05\x11\x14\x06#!\"&5\x11463!2\x16\x17\x01\x1e\x01\x01\x80\x03\x00\xfd\x00\x03\x80\x80\x14\n\xfe\xe7\n0\x0f8(\xfd\xc0(8\x80\x808(\x03@(8\xfe\x80\x13\r\xc0\r\x13\x13\r\xc0\r\x13\x02\x808(\xfa\xc0(88(\x03\xa0(`\x1c\x01\x18\x1c(\x01\x80\xfe\x80\x03\x80\x0e1\n\x01\x19\n\x14\xfe`(88(\x01\xa0\xfb\x00\x01\xa0(88(\x02\x00\x01@\r\x13\x13\r\xfe\xc0\r\x13\x13\x13\xfc`(88(\x05@(8(\x1c\xfe\xe8\x1c`\x00\x00\x00\x01\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x00\x01\x11\x14\x06#!\"&5\x11463!2\x16\x06\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x04`\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x00\x03\x00\x00\x00\x00\x06\x00\x05\x00\x00\x0f\x00\x1f\x00/\x00\x00%\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x06\x00&\x1a\xfa\x80\x1a&&\x1a\x05\x80\x1a&&\x1a\xfa\x80\x1a&&\x1a\x05\x80\x1a&&\x1a\xfa\x80\x1a&&\x1a\x05\x80\x1a&\xc0\x80\x1a&&\x1a\x80\x1a&&\x01\xe6\x80\x1a&&\x1a\x80\x1a&&\x01\xe6\x80\x1a&&\x1a\x80\x1a&&\x00\x06\x00\x00\xff\xc0\a\x00\x05@\x00\a\x00\x0f\x00\x1f\x00'\x007\x00G\x00\x00$\x14\x06\"&462\x12\x14\x06\"&462\x01\x15\x14\x06#!\"&=\x01463!2\x16\x00\x14\x06\"&462\x01\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x01\x80p\xa0pp\xa0pp\xa0pp\xa0\x05\xf0\x13\r\xfb@\r\x13\x13\r\x04\xc0\r\x13\xfa\x80p\xa0pp\xa0\x05\xf0\x13\r\xfb@\r\x13\x13\r\x04\xc0\r\x13\x13\r\xfb@\r\x13\x13\r\x04\xc0\r\x13Рpp\xa0p\x01\x90\xa0pp\xa0p\xfd\xa0\xc0\r\x13\x13\r\xc0\r\x13\x13\x03\xe3\xa0pp\xa0p\xfd\xa0\xc0\r\x13\x13\r\xc0\r\x13\x13\x01\xf3\xc0\r\x13\x13\r\xc0\r\x13\x13\x00\x00\x00\x00\x06\x00\x0f\xff\x00\a\x00\x05\xf7\x00\x1e\x00<\x00L\x00\\\x00l\x00|\x00\x00\x05\x14\x06#\"'7\x1632654\a'>\x0275\"\x06#\x15#5!\x15\a\x1e\x01\x13\x15!&54>\x0354&#\"\a'>\x0132\x16\x15\x14\x0e\x02\a35\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15!5346=\x01#\x06\a'73\x11\x01\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x01}mQjB919\x1d+i\x1a\b1$\x13\x10A\x10j\x01M_3<\x02\xfe\x96\x06/BB/\x1d\x19.#U\x18_:IdDRE\x01\u007f\x05\xea\x13\r\xfb@\r\x13\x12\x0e\x04\xc0\r\x13\xfa\x80\xfe\xb1k\x01\x02\b*G\x88j\x05\xec\x13\r\xfb@\r\x13\x12\x0e\x04\xc0\r\x13\x13\r\xfb@\r\x13\x13\r\x04\xc0\r\x13TP\\BX-\x1d\x1c@\b8\nC)\x12\x01\x025\x98Xs\fJ\x02@\x9f$\x123T4+,\x17\x19\x1b:;39SG2S.7\x19<\xfe\xc1\xc0\r\x13\x13\r\xc0\x0e\x12\x13\x03vcc)\xa1)\f\x11%L\u007f\xfel\xfe}\xc0\r\x13\x13\r\xc0\x0e\x12\x13\x01\xf3\xc0\r\x13\x13\r\xc0\r\x13\x13\x00\x00\x00\x00\x03\x00\x00\xff\x80\a\x00\x05\x80\x00\x0f\x005\x00e\x00\x00\x012\x16\x1d\x01\x14\x06#!\"&=\x01463%&'&5476!2\x17\x16\x17\x16\x17\x16\x15\x14\x0f\x01/\x01&'&#\"\a\x06\x15\x14\x17\x16\x17\x16\x17\x16\x17\x03!\x16\x15\x14\a\x06\a\x06\a\x06\a\x06#\"/\x01&'&=\x014'&?\x0157\x1e\x02\x17\x16\x17\x16\x17\x1632767654'&\x06\xe0\x0e\x12\x12\x0e\xf9@\x0e\x12\x12\x0e\x01\xc3\x1c\x170\x86\x85\x01\x042uBo\n\v\x0e\x05\fT\x0e25XzrDCBB\xd5Eh:%\xec\x01\x9b\a)\x170%HPIP{rQ\x8c9\x0f\b\x02\x01\x01\x02f\x0f\x1e\x0f\x05#-+>;I@KM-/Q\"\x02\x80\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12@#-bZ\xb5\x80\u007f\x13\f$&P{<\x12\x1b\x03\x06\x02\x958[;:XICC>\x14.\x1c\x18\xff\x00'5oe80#.0\x12\x15\x17(\x10\f\b\x0e\rl0\x1e&%,\x02\"J&\b9%$\x15\x16\x1b\x1a<=DTI\x1d\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00c\x00s\x00\x00\x13&/\x01632\x17\x163276727\a\x17\x15\x06#\"\a\x06\x15\x14\x16\x15\x17\x13\x16\x17\x16\x17\x16327676767654.\x01/\x01&'&\x0f\x01'73\x17\x167\x17\x16\x15\x14\a\x06\a\x06\a\x06\x15\x14\x16\x15\x16\x13\x16\a\x06\a\x06\a\x06\a\x06#\"'&'&'&5\x114'&\x0154&#!\"\x06\x1d\x01\x14\x163!260%\b\x03\r\x1b<4\x84\"VRt\x1e8\x1e\x01\x02<@<\x13\r\x01\x01\x0e\x06-#=XYhW8+0\x11$\x11\x15\a\x0f\x06\x04\x05\x13\"+d\x0e\x02T\xcdLx\x12\x06\x04-'I\x06\x0f\x03\b\x0e\x06\x15\x0f\x1a&JKkm\x92\xa7uw<=\x16\x10\x11\x19\x05V\x12\x0e\xfa@\x0e\x12\x12\x0e\x05\xc0\x0e\x12\x05!\x02\x02X\x01\x04\a\x03\x04\x01\x02\x0e@\t\t\x19\x0ev\r'\x06\xe5\xfe\xe8|N;!/\x1c\x12!$\x1c8:I\x9cOb\x93V;C\x15#\x01\x02\x03V\n\x03\r\x02&\r\a\x18\f\x01\v\x06\x0f\x1a\a(\v\x13\xfe\x87\xc3mL.A:9 !./KLwP\x9d\x01M\xbc\x19$\xfa\x82@\x0e\x12\x12\x0e@\x0e\x12\x12\x00\x00\n\x00\x00\x00\x00\x06\x80\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00o\x00\u007f\x00\x8f\x00\x9f\x00\x00%54&#!\"\x06\x1d\x01\x14\x163!26\x1154&#!\"\x06\x1d\x01\x14\x163!26\x0154&#!\"\x06\x1d\x01\x14\x163!26\x0154&#!\"\x06\x1d\x01\x14\x163!26\x0154&#!\"\x06\x1d\x01\x14\x163!26\x0154&#!\"\x06\x1d\x01\x14\x163!26\x0154&#!\"\x06\x1d\x01\x14\x163!26\x0154&#!\"\x06\x1d\x01\x14\x163!26\x1154&#!\"\x06\x1d\x01\x14\x163!26\x13\x11\x14\x06#!\"&5\x11463!2\x16\x02\x00\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\x02\x00\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\xfe\x00\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\x02\x00\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\x02\x00\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\xfe\x00\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\x02\x00\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\x80^B\xfa\xc0B^^B\x05@B^\xa0\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x01\x8e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\xfe\x8e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x03\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\xfe\x8e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\xfe\x8e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x03\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\xfe\x8e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x01\x8e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x01N\xfb\xc0B^^B\x04@B^^\x00\x00\x00\x06\x00\x1b\xff\x9b\x06\x80\x06\x00\x00\x03\x00\x13\x00\x1b\x00#\x00+\x003\x00\x00\t\x01'\x01$\x14\a\x01\x06\"/\x01&47\x0162\x1f\x01%\x17\x0f\x01/\x01?\x01\x01\x17\x0f\x01/\x01?\x01\x01\x17\x0f\x01/\x01?\x01\x01\x17\x0f\x01/\x01?\x01\x04\xa6\x01%k\xfe\xdb\x02*\x12\xfa\xfa\x126\x12\xc6\x12\x12\x05\x06\x126\x12\xc6\xfa\xcbbb\x1e\x1ebb\x1e\x01|\xc4\xc4<<\xc4\xc4<\x03\xdebb\x1e\x1ebb\x1e\xfd\x9ebb\x1e\x1ebb\x1e\x03\xbb\x01%k\xfe\xdb\xd56\x12\xfa\xfa\x12\x12\xc6\x126\x12\x05\x06\x12\x12Ƒ\x1e\x1ebb\x1e\x1eb\xfe\xfc<<\xc4\xc4<<\xc4\xfd^\x1e\x1ebb\x1e\x1eb\x02\x1e\x1e\x1ebb\x1e\x1eb\x00\x00\x00\x04\x00@\xff\x80\a\x00\x05\x00\x00\a\x00\x10\x00\x18\x00M\x00\x00$4&\"\x06\x14\x162\x01!\x11#\"\x0f\x01\x06\x15\x004&\"\x06\x14\x162\x01\x11\x14\x0e\x04&#\x14\x06\"&5!\x14\x06\"&5#\"\x06.\x045463\x114&>\x03?\x01>\x01;\x015463!2\x16\x02\x80LhLLh\xfe\xcc\x01\x80\x9e\r\t\xc3\t\x05\x00LhLLh\x01L\b\x13\x0e!\f'\x03\x96Ԗ\xfe\x80\x96Ԗ@\x03'\f!\x0e\x13\b&\x1a\x01\x01\x04\t\x13\r\xc6\x13?\x1b\xa0&\x1a\x04\x00\x1a&LhLLhL\x02\x80\x01\x00\t\xc3\t\r\xfd\xaehLLhL\x04\xc0\xfc\x00\x0f\x17\x0e\t\x03\x01\x01j\x96\x96jj\x96\x96j\x01\x01\x03\t\x0e\x17\x0f\x1a&\x01@\b6\x16/\x1b\"\r\xc6\x13\x1a\xc0\x1a&&\x00\x00\x00\x01\x00\x00\xff\x80\x06\x00\x05\x80\x00J\x00\x00\x00\x10\x02\x04#\"'6767\x1e\x0132>\x0154.\x01#\"\x0e\x03\x15\x14\x16\x17\x167>\x0176'&54632\x16\x15\x14\x06#\"&7>\x0254&#\"\x06\x15\x14\x17\x03\x06\x17&\x0254\x12$ \x04\x06\x00\xce\xfe\x9f\xd1ok;\x13\t-\x14j=y\xbehw\xe2\x8ei\xb6\u007f[+PM\x1e\b\x02\f\x02\x06\x113ѩ\x97\xa9\x89k=J\x0e\b%\x1762>V\x19c\x11\x04\xce\xfe\xce\x01a\x01\xa2\x01a\x03Q\xfe^\xfe\x9f\xce ]G\"\xb1'9\x89\xf0\x96r\xc8~:`}\x86Ch\x9e \f \a0\x06\x17\x14=Z\x97٤\x83\xaa\xeeW=#uY\x1f2BrUI1\xfe^Fk[\x01|\xe9\xd1\x01a\xce\xce\x00\x00\x01\x00\x00\xff\x80\x06\x00\x05\x80\x00L\x00\x00\x012\x16\x15\x11\x14\x06#!6767\x1e\x0132\x1254.\x02#\"\x0e\x03\x15\x14\x16\x17\x1667676'&54632\x16\x15\x14\x06#\"&7>\x0254&#\"\x06\x15\x14\x17\x03\x06\x17#\"&5\x11463\x04\xe0w\xa9\xa9w\xfd+U\x17\t,\x15i<\xb5\xe5F{\xb6jh\xb5}Z+OM\r\x15\x04\n\x05\x06\x112ϧ\x95\xa7\x87jX\x96բ\x81\xa8\xecW<\"uW\x1f1AqSH1\xfebd\x9a\xa9w\x03\xc0w\xa9\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x1b\x00'\x007\x00\x00\x014'!\x153\x0e\x03#\"&4632\x177&#\"\x06\x10\x16326%35#5#\x15#\x153\x153\x01\x11\x14\x06#!\"&5\x11463!2\x16\x03\x95\x06\xfe\x96\xd9\x03\x1b0U6c\x8c\x8cc\\=hl\x95\xa0\xe0ࠥ\xcb\x01Ymmnnnn\x01\x12\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x02w\x1a&\x84\x1846#\x8eȎ;ed\xe1\xfe\xc2\xe1\xd2wnnnnn\x02\x85\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x02\x00\x00\xff\xa3\t\x00\x05]\x00#\x00/\x00\x00\x01\x14\x02\x04#\"$&\x02\x10\x126$3 \x17\a&#\"\x0e\x01\x14\x1e\x0132>\x037!5!\x16%\x15#\x15#5#5353\x15\x05\x9d\xae\xfe\xbeЕ\xfe\xf0\xc4tt\xc4\x01\x10\x95\x01\x1e\xcd\xc7u\xaf{\xd1zz\xd1{S\x8bZC\x1f\x06\xfe`\x02\xb4\f\x03c\xd1\xd2\xd1\xd1\xd2\x02o\xd0\xfe\xbb\xb7t\xc4\x01\x10\x01*\x01\x10\xc4t\xc0\xbfq|\xd5\xfc\xd5|.EXN#\xfc??\xd2\xd1\xd1\xd2\xd1\xd1\x00\x00\x00\x04\x00\x00\x00\x00\a\x80\x05\x00\x00\f\x00\x1c\x00,\x00<\x00\x00\x01!5#\x11#\a\x17673\x11#$\x14\x0e\x02\".\x024>\x022\x1e\x01\x01\x11\"&5!\x14\x06#\x112\x16\x15!46\x13\x11\x14\x06#!\"&5\x11463!2\x16\x03\x00\x01\x80\x80r\x94M*\r\x02\x80\x02\x00*M~\x96~M**M~\x96~M\x02*j\x96\xfb\x80\x96jj\x96\x04\x80\x96\xea&\x1a\xf9\x00\x1a&&\x1a\a\x00\x1a&\x01\x80`\x01\xc0\x89P%\x14\xfe\xe0挐|NN|\x90\x8c\x90|NN|\xfe*\x02\x00\x96jj\x96\xfe\x00\x96jj\x96\x03@\xfb\x80\x1a&&\x1a\x04\x80\x1a&&\x00\x00\x01\x00\x00\x01@\x04\x00\x03\x80\x00\r\x00\x00\x00\x14\a\x01\x06\"'\x01&463!2\x04\x00\x13\xfe@\x134\x13\xfe@\x13&\x1a\x03\x80\x1a\x03Z4\x13\xfe@\x13\x13\x01\xc0\x134&\x00\x00\x00\x00\x01\x00\x00\x01\x00\x04\x00\x03@\x00\r\x00\x00\x00\x14\x06#!\"&47\x0162\x17\x01\x04\x00&\x1a\xfc\x80\x1a&\x13\x01\xc0\x134\x13\x01\xc0\x01Z4&&4\x13\x01\xc0\x13\x13\xfe@\x00\x00\x00\x00\x01\x00@\x00\x80\x02\x80\x04\x80\x00\r\x00\x00\x01\x11\x14\x06\"'\x01&47\x0162\x16\x02\x80&4\x13\xfe@\x13\x13\x01\xc0\x134&\x04@\xfc\x80\x1a&\x13\x01\xc0\x134\x13\x01\xc0\x13&\x00\x00\x00\x01\x00\x00\x00\x80\x02@\x04\x80\x00\r\x00\x00\x00\x14\a\x01\x06\"&5\x11462\x17\x01\x02@\x13\xfe@\x134&&4\x13\x01\xc0\x02\x9a4\x13\xfe@\x13&\x1a\x03\x80\x1a&\x13\xfe@\x00\x00\x00\x00\x03\x00\x00\xff\x80\x06\x80\x05\x80\x00\x06\x00\r\x00\x1d\x00\x003!\x11!\x11\x14\x16%\x11!\x11!26\x13\x11\x14\x06#!\"&5\x11463!2\x16\xa0\x02`\xfd\x80\x13\x05m\xfd\x80\x02`\r\x13\x80^B\xfa\xc0B^^B\x05@B^\x04\x80\xfb\xa0\r\x13 \x04`\xfb\x80\x13\x04\xcd\xfb@B^^B\x04\xc0B^^\x00\x02\x00\x00\xff\xc0\x04\x00\x05@\x00\r\x00\x1b\x00\x00\x00\x14\a\x01\x06\"'\x01&463!2\x12\x14\x06#!\"&47\x0162\x17\x01\x04\x00\x13\xfe@\x134\x13\xfe@\x13&\x1a\x03\x80\x1a&&\x1a\xfc\x80\x1a&\x13\x01\xc0\x134\x13\x01\xc0\x01\xda4\x13\xfe@\x13\x13\x01\xc0\x134&\x01Z4&&4\x13\x01\xc0\x13\x13\xfe@\x00\x00\x00\x00\x01\x00\x00\xff\xc0\x04\x00\x02\x00\x00\r\x00\x00\x00\x14\a\x01\x06\"'\x01&463!2\x04\x00\x13\xfe@\x134\x13\xfe@\x13&\x1a\x03\x80\x1a\x01\xda4\x13\xfe@\x13\x13\x01\xc0\x134&\x00\x00\x00\x00\x01\x00\x00\x03\x00\x04\x00\x05@\x00\r\x00\x00\x00\x14\x06#!\"&47\x0162\x17\x01\x04\x00&\x1a\xfc\x80\x1a&\x13\x01\xc0\x134\x13\x01\xc0\x03Z4&&4\x13\x01\xc0\x13\x13\xfe@\x00\x00\x00\x00\x02\x00\x00\xff\x80\a\x00\x05\x00\x00\x1a\x00:\x00\x00\x01\x11\x14\x06#!\"&5\x11\x16\x17\x04\x17\x1e\x02;\x022>\x0176%6\x13\x14\x06\a\x00\a\x0e\x04+\x02\".\x03'&$'.\x015463!2\x16\a\x00^B\xfa@B^,9\x01j\x879Gv3\x01\x013vG9\xaa\x01H9+bI\xfe\x88\\\nA+=6\x17\x01\x01\x176=+A\n[\xfe\xaa\">nSM\x05\xc0A_\x03:\xfc\xe6B^^B\x03\x1a1&\xf6c*/11/*{\xde'\x01VO\x903\xfe\xfb@\a/\x1d$\x12\x12$\x1d/\a@\xed\x18*\x93?Nh^\x00\x03\x00\x00\xff\xb0\x06\x00\x05l\x00\x03\x00\x0f\x00+\x00\x00\x01\x11!\x11\x01\x16\x06+\x01\"&5462\x16\x01\x11!\x114&#\"\x06\a\x06\x15\x11!\x12\x10/\x01!\x15#>\x0332\x16\x01]\xfe\xb6\x01_\x01gT\x02Rdg\xa6d\x04\x8f\xfe\xb7QV?U\x15\v\xfe\xb7\x02\x01\x01\x01I\x02\x14*Gg?\xab\xd0\x03\x8f\xfc!\x03\xdf\x012IbbIJaa\xfc\xdd\xfd\xc8\x02\x12iwE3\x1e3\xfd\xd7\x01\x8f\x01\xf000\x90 08\x1f\xe3\x00\x00\x00\x00\x01\x00\x00\xff\x80\x06\x00\x05\x80\x004\x00\x00\x00\x10\x02\x06\x04#\"$'&6?\x0163\x16\x17\x1e\x0132>\x024.\x02#\"\x06\a\x17\x16\a\x06#!\"&5\x11476\x1f\x016$32\x04\x16\x06\x00z\xce\xfe䜬\xfe\xcam\a\x01\b\x89\n\x0f\x10\aI\xd4wh\xbd\x8aQQ\x8a\xbdhb\xb4F\x89\x1f\x11\x11*\xfe@\x1a&('\x1e\x82k\x01\x13\x93\x9c\x01\x1c\xce\x03\x1c\xfe\xc8\xfe\xe4\xcez\x91\x84\n\x19\b\x8a\t\x02\n_hQ\x8a\xbdн\x8aQGB\x8a\x1e'(&\x1a\x01\xc0*\x11\x11\x1f\x81eoz\xce\x00\x01\x00(\xff\x15\x06\xeb\x05\xd8\x00q\x00\x00!\x14\x0f\x01\x06#\"'\x01&547\x01\a\x06\"'\x1e\x06\x15\x14\a\x0e\x05#\"'\x01&54>\x047632\x1e\x05\x17&47\x0162\x17.\x06547>\x0532\x17\x01\x16\x15\x14\x0e\x04\a\x06#\".\x05'\x16\x14\x0f\x01\x01632\x17\x01\x16\x06\xeb%k'45%\xfe\x95&+\xff\x00~\x0e(\x0e\x02\x15\x04\x10\x04\b\x03\x1c\x03\x1b\v\x1a\x12\x1a\r(\x1c\xfeh\x1c\t\t\x16\v\x1e\x03\x1e&\n\x10\x11\n\x11\x06\x14\x02\x0e\x0e\x01\\\x0e(\x0e\x02\x15\x04\x10\x04\b\x03\x1c\x03\x1b\v\x1a\x12\x1a\r(\x1c\x01\x98\x1c\t\t\x16\v\x1e\x03\x1e&\n\x10\x11\n\x11\x06\x14\x02\x0e\x0e~\x01\x00+54'\x01k%5%l%%\x01l$65+\x01\x00~\x0e\x0e\x02\x14\x06\x11\n\x11\x10\n&\x1e\x03\x1e\v\x16\t\t\x1c\x01\x98\x1c(\r\x1a\x12\x1a\v\x1b\x03\x1c\x03\b\x04\x10\x04\x15\x02\x0e(\x0e\x01\\\x0e\x0e\x02\x14\x06\x11\n\x11\x10\n&\x1e\x03\x1e\v\x16\t\t\x1c\xfeh\x1c(\r\x1a\x12\x1a\v\x1b\x03\x1c\x03\b\x04\x10\x04\x15\x02\x0e(\x0e~\xff\x00+%\xfe\x95'\x00\x00\a\x00\x00\xff\x80\a\x00\x05\x00\x00\a\x00\x0f\x00!\x00)\x001\x009\x00K\x00\x00\x004&\"\x06\x14\x162\x004&\"\x06\x14\x162\x01\x136.\x01\x06\a\x03\x0e\x01\a\x06\x1e\x01676&$4&\"\x06\x14\x162\x004&\"\x06\x14\x162\x044&\"\x06\x14\x162\x01\x10\a\x06#!\"'&\x114\x126$ \x04\x16\x12\x01\x80KjKKj\x01\vKjKKj\x01\xf7e\x06\x1b2.\ae<^\x10\x14P\x9a\x8a\x14\x10,\x02bKjKKj\xfd\xcbKjKKj\x02\vKjKKj\x01\x8b\x8d\x13#\xfa\x86#\x13\x8d\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x01KjKKjK\x02\vjKKjK\xfe\x9f\x01~\x1a-\x0e\x1b\x1a\xfe\x82\x05M\x027>\x057&\x0254\x12$ \x04\x04L\xfeh\xfe\x9dя\x82W\x1b\x18.\x98{+9E=\xcc\x01c\xd1\xd1\x01Q\xf0\xfed\xf4FK\xc6\xfe\xfa1A\x05\x0f\x18\x04\x03\x05\x01\n\x02\f\x02\a0\x15)\x18\x1e\v\x9d\xb5\xf0\x01\x9c\x01\xe8\x01\x9c\x04\x80\x8b\xec\x89p\xcbJ2`[Q?l&\x06\b\x8b\xec\x01\x12\xec\xc7\xfe\xa4\xfe٫\b\xafC\x0e\b\x15\x11\x01\x04\x10\x04\x0f\x03\x0e\x02\b5\x178.H(Y\x01\x06\x96\xae\x01'\xab\xab\x00\x00\x03\x00\x00\xff\x80\a\x00\x05\x00\x00\x14\x00:\x00d\x00\x00\x00 \x04\x06\x15\x14\x16\x1f\x01\a6?\x01\x17\x1632$64&$ \x04\x16\x10\x06\x04#\"'\x06\a\x06\a#\"&'&4>\x057>\x047.\x01546\x01\x1e\x04\x17\x1e\x06\x14\a\x0e\x01'&'&'\x06# '\x1632$7>\x0154'\x1e\x01\x15\x14\x06\x03Y\xfe\xce\xfe\xf6\x9dj`a#\"\x1c,5NK\x99\x01\n\x9d\x9d\xfd\x9e\x01~\x01E\xbc\xbc\xfe\xbb\xbfVZ|\x9a$2\x03\v\x13\x02\x01\x01\x03\x02\x05\x03\x06\x01\x05$\x10\x1d\x15\n|\x8e\xbc\x05:\n\x15\x1d\x10$\x05\x01\x06\x03\x05\x02\x03\x01\x01\x03\x14\f2$\x9a|ZV\xfe\xf1\xc9:\x1e\xa1\x01(t}\x86\x17\x81\x96\x8e\x04\x80h\xb2fR\x9888T\x14\x13\x1f\n\x0eh\xb2̲\xe8\x89\xec\xfe\xea\xec\x89\x10X(\t\a\x10\r\x03\a\x06\x06\x04\a\x03\a\x01\x06&\x15%(\x18H\xd2w\x8b\xec\xfb\xf8\x18(%\x15&\x06\x01\a\x03\a\x04\x06\x06\a\x03\x0e\x10\x01\a\t(X\x10\x84\x04ZT\\\xf0\x86MKG\xd6{x\xd1\x00\x01\x00\x01\xff\x00\x03|\x05\x80\x00!\x00\x00\x01\x16\a\x01\x06#\"'.\x017\x13\x05\x06#\"'&7\x13>\x013!2\x16\x15\x14\a\x03%632\x03u\x12\v\xfd\xe4\r\x1d\x04\n\x11\x11\x04\xc5\xfej\x04\b\x12\r\x12\x05\xc9\x04\x18\x10\x01H\x13\x1a\x05\xab\x01\x8c\b\x04\x13\x03\xca\x14\x18\xfb{\x19\x02\x05\x1c\x10\x03(e\x01\v\x0f\x18\x039\x0e\x12\x19\x11\b\n\xfe1b\x02\x00\x00\x01\x00\x00\xff\x80\a\x00\x05\x80\x00U\x00\x00\x01\x11\x14\x06#!\"&5\x1146;\x015!\x1532\x16\x15\x11\x14\x06#!\"&5\x1146;\x015!\x1532\x16\x15\x11\x14\x06#!\"&5\x1146;\x015463!5#\"&5\x11463!2\x16\x15\x11\x14\x06+\x01\x15!2\x16\x1d\x0132\x16\a\x008(\xfe\xc0(88(`\xfe\x00`(88(\xfe\xc0(88(`\xfe\x00`(88(\xfe\xc0(88(`L4\x02\x00`(88(\x01@(88(`\x02\x004L`(8\x01 \xfe\xc0(88(\x01@(8\xc0\xc08(\xfe\xc0(88(\x01@(8\xc0\xc08(\xfe\xc0(88(\x01@(8\xc04L\xc08(\x01@(88(\xfe\xc0(8\xc0L4\xc08\x00\x00\x03\x00\x00\xff\x80\x06\x80\x05\xc0\x00\x13\x00O\x00Y\x00\x00\x01\x11\x14\x06\"&5462\x16\x15\x14\x16265\x1162\x05\x14\x06#\"'.\x01#\"\x06\a\x0e\x01\a\x06#\"'.\x01'.\x01\"\x06\a\x0e\x01\a\x06#\"'.\x01'.\x01#\"\x06\a\x06#\"&5476\x00$32\x04\x1e\x01\x17\x16\x01\x15&\"\a5462\x16\x03\x80\x98И&4&NdN!>\x03!\x13\r\v\f1X:Dx+\a\x15\x04\v\x11\x12\v\x04\x15\a+w\x88w+\a\x15\x04\v\x12\x11\v\x04\x15\a+xD:X1\f\v\r\x13\x01-\x00\xff\x01U\xbe\x8c\x01\r\xe0\xa5!\x01\xfd\x00*,*&4&\x02\xc4\xfd\xbch\x98\x98h\x1a&&\x1a2NN2\x02D\v&\r\x13\n..J<\n$\x06\x11\x11\x06$\n\x01767\x14\a\x0e\x02\a\x16\x15\x14\a\x16\x15\x14\a\x16\x15\x14\x06#\x0e\x01\"&'\"&547&547&547.\x02'&54>\x022\x1e\x02\x02\xe0\x13\x1a\x13l4\r\x13\x13\r2cK\xa0Eo\x87\x8a\x87oED\n)\n\x80\r\xe4\r\x80\n)\nD\x80g-;<\x04/\x19\x19-\r?.\x14P^P\x14.?\r-\x19\x19/\x04<;-gY\x91\xb7\xbe\xb7\x91Y\x03\xc0\r\x13\x13\r.2\x13\x1a\x13 L4H|O--O|HeO\v,\v\x99\x91\x91\x99\v,\vOe\x9bq1Ls2\x1c6%\x1b\x1b%4\x1d\x17\x18.2,44,2.\x18\x17\x1d4%\x1b\x1b%6\x1c2sL1q\x9bc\xabqAAq\xab\x00\x02\x00\x00\xff\xa0\a\x00\x04\xe0\x00\x1a\x004\x00\x00\x01\x15\x14\x06#!\x15\x14\x06#\"'\x01&547\x01632\x16\x1d\x01!2\x16\x10\x14\a\x01\x06#\"&=\x01!\"&=\x01463!54632\x17\x01\a\x00\x13\r\xfa\xa0\x13\r\f\f\xfe\xc1\t\t\x01@\t\x0e\r\x13\x05`\r\x13\t\xfe\xc0\t\x0e\r\x13\xfa\xa0\r\x13\x13\r\x05`\x12\x0e\f\f\x01?\x01`\xc0\r\x13\xc0\r\x13\n\x01@\t\r\x0e\t\x01@\t\x13\r\xc0\x13\x02!\x1c\t\xfe\xc0\t\x13\r\xc0\x13\r\xc0\r\x13\xc0\x0e\x12\n\xfe\xc1\x00\x00\x00\x00\x02\x00\x00\x00\x00\a\x80\x05\x80\x00\x19\x005\x00\x00\x014&+\x01\x114&+\x01\"\x06\x15\x11#\"\x06\x15\x14\x17\x01\x1627\x016\x05\x14\x06#!\"\x005467&54\x0032\x04\x17632\x16\x15\x14\a\x1e\x01\x05\x00\x12\x0e\xe0\x13\r\xc0\r\x13\xe0\r\x13\t\x01`\t\x1c\t\x01_\n\x02\x80\xe1\x9f\xfb\xc0\xb9\xfe\xf9\x8cv\x02\x01,Ԝ\x01\x03;G_j\x96)\x82\xa7\x02`\x0e\x12\x01`\r\x13\x13\r\xfe\xa0\x13\r\x0e\t\xfe\xa0\t\t\x01_\fԟ\xe1\x01\a\xb9\x82\xdc7\x1e\r\xd4\x01,\xae\x90>\x96jL>\x1f\xd1\x00\x02\x00\x00\x00\x00\a\x80\x05\x80\x00\x19\x005\x00\x00\x014'\x01&\"\a\x01\x06\x15\x14\x16;\x01\x11\x14\x16;\x01265\x11326\x01\x14\x06#!\"\x005467&54\x0032\x04\x17632\x16\x15\x14\a\x1e\x01\x05\x00\t\xfe\xa0\t\x1c\t\xfe\xa1\n\x12\x0e\xe0\x13\r\xc0\r\x13\xe0\r\x13\x02\x80\xe1\x9f\xfb\xc0\xb9\xfe\xf9\x8cv\x02\x01,Ԝ\x01\x03;G_j\x96)\x82\xa7\x02\xa0\x0e\t\x01`\t\t\xfe\xa1\f\f\x0e\x12\xfe\xa0\r\x13\x13\r\x01`\x13\xfe\xed\x9f\xe1\x01\a\xb9\x82\xdc7\x1e\r\xd4\x01,\xae\x90>\x96jL>\x1f\xd1\x00\x00\x00\x00\x03\x00\x00\xff\x80\x05\x80\x05\x80\x00\a\x00X\x00`\x00\x00$\x14\x06\"&462\x05\x14\x06#!\"&54>\x037\x06\x1d\x01\x0e\x01\x15\x14\x162654&'547\x16 7\x16\x1d\x01\"\x06\x1d\x01\x06\x15\x14\x162654'5462\x16\x1d\x01\x06\x15\x14\x162654'54&'46.\x02'\x1e\x04\x00\x10\x06 &\x106 \x01\x80&4&&4\x04&\x92y\xfc\x96y\x92\v%:hD\x16:Fp\xa0pG9\x19\x84\x01F\x84\x19j\x96 8P8 LhL 8P8 E;\x01\x01\x04\n\bDh:%\v\xfe\xc0\xe1\xfe\xc2\xe1\xe1\x01>\xda4&&4&}y\x8a\x8ayD~\x96s[\x0f4D\xcb\x14d=PppP=d\x14\xcb>\x1fhh\x1f>@\x96jY\x1d*(88(*\x1dY4LL4Y\x1d*(88(*\x1dYDw\"\nA\x1f4*\x13\x0f[s\x96~\x03\xd8\xfe\xc2\xe1\xe1\x01>\xe1\x00\x00\x00\x02\x00\x00\xff\x80\x05\x80\x05\x80\x00\a\x00M\x00\x00\x004&\"\x06\x14\x1627\x14\x06\a\x11\x14\x04 $=\x01.\x015\x114632\x17>\x0132\x16\x14\x06#\"'\x11\x14\x16 65\x11\x06#\"&4632\x16\x17632\x16\x15\x11\x14\x06\a\x15\x14\x16 65\x11.\x015462\x16\x05\x00&4&&4\xa6G9\xfe\xf9\xfe\x8e\xfe\xf9\xa4\xdc&\x1a\x06\n\x11<#5KK5!\x1f\xbc\x01\b\xbc\x1f!5KK5#<\x11\n\x06\x1a&ܤ\xbc\x01\b\xbc9Gp\xa0p\x03&4&&4&@>b\x15\xfeu\x9f\xe1ោ\x14ؐ\x02\x00\x1a&\x02\x1e$KjK\x12\xfenj\x96\x96j\x01\x92\x12KjK$\x1e\x02&\x1a\xfe\x00\x90\xd8\x14\x84j\x96\x96j\x01\x8b\x15b>Ppp\x00\x04\x00\x00\xff\x80\a\x00\x05\x80\x00\x03\x00\r\x00\x1b\x00%\x00\x00\x01!5!\x05\x11#\"&5\x11463!\x11!\x1135463!2\x16\x1d\x01\x05\x11\x14\x06+\x01\x1132\x16\x02\x80\x02\x00\xfe\x00\xfe\xa0@\\\x84\x84\\\x04\xa0\xfc\x00\x808(\x02@(8\x02\x00\x84\\@@\\\x84\x04\x80\x80\x80\xfb\x00\x84\\\x03@\\\x84\xfb\x00\x05\x00\xa0(88(\xa0\xe0\xfc\xc0\\\x84\x05\x00\x84\x00\x02\x00@\xff\x00\x06\xc0\x06\x00\x00\v\x003\x00\x00\x044#\"&54\"\x15\x14\x163\x01\x14\x06#!\x14\x06\"&5!\"&5>\x0454\x127&5462\x16\x15\x14\a\x16\x12\x15\x14\x1e\x03\x03\x90\x10;U gI\x03@L4\xfe@\x96Ԗ\xfe@4L2RX='\xea\xbe\b8P8\b\xbe\xea'=XR\xb0 U;\x10\x10Ig\x0104Lj\x96\x96jL4*\\\x93\xaa\xf2\x8b\x98\x01\x05\x1c\x13\x14(88(\x14\x13\x1c\xfe\xfb\x98\x8b\xf2\xaa\x93\\\x00\x00\x03\x00\x00\xff\x80\a@\x05\x00\x00\a\x00\x0f\x00\"\x00\x00\x004&+\x01\x1132\x01!\x14\x06#!\"&\x00\x10\x06+\x01\x15\x14\x06#!\"&5\x11463!2\x06\x80pP@@P\xf9\xf0\a\x00\x96j\xfb\x00j\x96\a@\xe1\x9f@\x84\\\xfd@\\\x84&\x1a\x04\x80\x9f\x030\xa0p\xfe\x80\xfd\xc0j\x96\x96\x04\t\xfe\xc2\xe1 \\\x84\x84\\\x02\xe0\x1a&\x00\x00\x02\x00\x00\xff\x00\x05\x80\x06\x00\x00-\x00B\x00\x00\x01\x11\x14\x06\a\x11\x14\x06+\x01\"&5\x11.\x015\x11462\x16\x15\x11\x14\x16265\x11462\x16\x15\x11\x14\x16265\x11462\x16\x05\x11\x14\x06+\x01\"&5\x11#\"&5\x11463!2\x16\x02\x80G9L4\x804L9G&4&&4&&4&&4&&4&\x03\x00L4\x804L\xe0\r\x13\xbc\x84\x01\x00\x1a&\x05\xc0\xfd\x80=d\x14\xfc\xf54LL4\x03\v\x14d=\x02\x80\x1a&&\x1a\xfe`\x1a&&\x1a\x01\xa0\x1a&&\x1a\xfe`\x1a&&\x1a\x01\xa0\x1a&&\x1a\xf9\xc04LL4\x02\x00\x13\r\x03 \x84\xbc&\x00\x06\x00\x00\xff\x00\x06\x00\x06\x00\x00\x13\x00\x1a\x00#\x003\x00C\x00S\x00\x00\x01\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x17\a\x11!&'\x01&\x01\x11!\"&5\x11!\x11\x01463!2\x16\x1d\x01\x14\x06#!\"&5\x052\x16\x1d\x01\x14\x06#!\"&=\x01463\x012\x16\x1d\x01\x14\x06#!\"&=\x01463\x05\xbc\x1c(8(\xfa\xc0(88(\x03\x80(`\x1c\x84\x01x\n\f\xfe\xc7\f\x01c\xfe`(8\xfd\x00\x01\x00\x12\x0e\x02\xc0\x0e\x12\x12\x0e\xfd@\x0e\x12\x02\xe0\x0e\x12\x12\x0e\xfd@\x0e\x12\x12\x0e\x02\xc0\x0e\x12\x12\x0e\xfd@\x0e\x12\x12\x0e\x04\x84\x1c`(\xfb\x80(88(\x06@(8(\x1cD\xfe\x88\x1d\f\x019\f\xfa\x12\x04\x008(\x01\xa0\xfa\x00\x03`\x0e\x12\x12\x0e@\x0e\x12\x12\x0e\xa0\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\xff\x00\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x00\x14\x00\x00\xff\x00\x05\x80\x06\x00\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00o\x00\u007f\x00\x8f\x00\x9f\x00\xaf\x00\xbf\x00\xcf\x00\xdf\x00\xef\x00\xff\x01\x0f\x01\x1f\x01-\x01=\x00\x00%\x15\x14\x06+\x01\"&=\x0146;\x012\x165\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x05\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x05\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01!\x11!\x11!5463!2\x16\x15\x01\x11\x14\x06#!\"&5\x11463!2\x16\x01\x80\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x01\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\x03\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\x03\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\x03\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\x02\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\x01\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x01\x80\xfb\x80\x01\x80\x13\r\x01@\r\x13\x02\x00&\x1a\xfb\x00\x1a&&\x1a\x05\x00\x1a&\xe0@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xfd\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xfd\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xfd\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xfe\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\xfa\x93\x06\x00\xfa\x00\xe0\r\x13\x13\r\x05`\xf9\x80\x1a&&\x1a\x06\x80\x1a&&\x00\r\x00\x00\xff\x00\x05\x80\x06\x00\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00o\x00\u007f\x00\x8f\x00\x9f\x00\xb7\x00\xdb\x00\xf5\x00\x00%\x15\x14\x06+\x01\"&=\x0146;\x012\x165\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x05\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x05\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01!\x11!\x15\x14\x06#!\"&=\x01!\x11!5463!2\x16\x15\x19\x014&+\x01\"\x06\x1d\x01#54&+\x01\"\x06\x15\x11\x14\x16;\x0126=\x013\x15\x14\x16;\x0126%\x11\x14\x06#!\"&5\x11463!\x11463!2\x16\x15\x11!2\x16\x01\x80\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x01\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\x03\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\x02\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\x01\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x01\x80\xff\x008(\xfe@(8\xff\x00\x01\x80\x13\r\x01@\r\x13\x13\r@\r\x13\x80\x13\r@\r\x13\x13\r@\r\x13\x80\x13\r@\r\x13\x02\x00&\x1a\xfb\x00\x1a&&\x1a\x01@8(\x01\xc0(8\x01@\x1a&\xe0@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xfd\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xfe\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\xfc\x93\x04\x80 (88( \xfb\x80\xe0\r\x13\x13\r\x03\xc0\x01@\r\x13\x13\r``\r\x13\x13\r\xfe\xc0\r\x13\x13\r``\r\x13\x13-\xfb\x00\x1a&&\x1a\x05\x00\x1a&\x01 (88(\xfe\xe0&\x00\x05\x00@\xff\x80\a\x80\x05\x80\x00\a\x00\x10\x00\x18\x00<\x00c\x00\x00$4&\"\x06\x14\x162\x01!\x11#\x06\x0f\x01\x06\a\x004&\"\x06\x14\x162\x1354&+\x0154&+\x01\"\x06\x1d\x01#\"\x06\x1d\x01\x14\x16;\x01\x15\x14\x16;\x0126=\x01326\x01\x11\x14\x06+\x01\x14\x06\"&5!\x14\x06\"&5#\"&463\x1146?\x01>\x01;\x01\x11463!2\x16\x02\x80KjKKj\xfe\xcb\x01\x80\x9e\x0e\b\xc3\a\x02\x05\x00KjKKj\xcb\x12\x0e\xe0\x12\x0e\xc0\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\x12\x0e\xc0\x0e\x12\xe0\x0e\x12\x01\x00&\x1a\xc0\x96Ԗ\xfe\x80\x96Ԗ\x80\x1a&&\x1a\x1a\x13\xc6\x13@\x1a\xa0&\x1a\x04\x80\x1a&KjKKjK\x02\x80\x01\x00\x02\a\xc3\f\n\xfd\xadjKKjK\x03 \xc0\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\x12\x0e\xc0\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\x12\x02.\xfb\x80\x1a&j\x96\x96jj\x96\x96j&4&\x01\xa0\x1a@\x13\xc6\x13\x1a\x01@\x1a&&\x00\x00\x05\x00\x00\xff\x80\a\x00\x05\x80\x00#\x00'\x001\x00?\x00I\x00\x00\x0154&+\x0154&+\x01\"\x06\x1d\x01#\"\x06\x1d\x01\x14\x16;\x01\x15\x14\x16;\x0126=\x01326\x01!5!\x05\x11#\"&5\x11463!\x11!\x1135463!2\x16\x1d\x01\x05\x11\x14\x06+\x01\x1132\x16\x05\x00\x12\x0e\xe0\x12\x0e\xc0\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\x12\x0e\xc0\x0e\x12\xe0\x0e\x12\xfd\x80\x02\x00\xfe\x00\xfe\x80 \\\x84\x84\\\x04\xc0\xfb\xc0\xa08(\x02@(8\x02\x00\x84\\ \\\x84\x01\xa0\xc0\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\x12\x0e\xc0\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\x12\x02\ue000\xfb\x00\x84\\\x03@\\\x84\xfb\x00\x05\x00\xa0(88(\xa0\xe0\xfc\xc0\\\x84\x05\x00\x84\x00\x00\x00\x00\x01\x00\x00\x00\x00\a\x80\x04\x80\x00:\x00\x00\x01\x06\r\x01\a#\x0132\x16\x14\x06+\x0353\x11#\a#'53535'575#5#573\x173\x11#5;\x022\x16\x14\x06+\x01\x013\x17\x05\x1e\x01\x17\a\x80\x01\xfe\xe1\xfe\xa0\xe0@\xfe\xdbE\x1a&&\x1a`\xa0@@\xa0\xc0` \x80\xc0\xc0\x80 `\xc0\xa0@@\xa0`\x1a&&\x1aE\x01%@\xe0\x01`\x80\x90\b\x02@ @ @\xfe\xa0\t\x0e\t \x01\xa0\xe0 \xc0 \b\x18\x80\x18\b \xc0 \xe0\x01\xa0 \t\x0e\t\xfe\xa0@ \x1c0\n\x00\x00\x00\x02\x00@\x00\x00\x06\x80\x05\x80\x00\x06\x00\x18\x00\x00\x01\x11!\x11\x14\x163\x01\x15!57#\"&5\x11'7!7!\x17\a\x11\x02\x80\xff\x00K5\x04\x80\xfb\x80\x80\x80\x9f\xe1@ \x01\xe0 \x03\xc0 @\x02\x80\x01\x80\xff\x005K\xfe@\xc0\xc0\xc0\xe1\x9f\x01@@\x80\x80\xc0 \xfc\xe0\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00#\x003\x00\x00%\x114&+\x01\"\x06\x15\x11!\x114&+\x01\"\x06\x15\x11\x14\x16;\x01265\x11!\x11\x14\x16;\x0126\x01\x11\x14\x06#!\"&5\x11463!2\x16\x05\x00&\x1a\x80\x1a&\xfe\x00&\x1a\x80\x1a&&\x1a\x80\x1a&\x02\x00&\x1a\x80\x1a&\x01\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\xc0\x03\x80\x1a&&\x1a\xfe\xc0\x01@\x1a&&\x1a\xfc\x80\x1a&&\x1a\x01@\xfe\xc0\x1a&&\x03\xba\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00#\x003\x00\x00\x0154&#!\x114&+\x01\"\x06\x15\x11!\"\x06\x1d\x01\x14\x163!\x11\x14\x16;\x01265\x11!26\x01\x11\x14\x06#!\"&5\x11463!2\x16\x05\x00&\x1a\xfe\xc0&\x1a\x80\x1a&\xfe\xc0\x1a&&\x1a\x01@&\x1a\x80\x1a&\x01@\x1a&\x01\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x02@\x80\x1a&\x01@\x1a&&\x1a\xfe\xc0&\x1a\x80\x1a&\xfe\xc0\x1a&&\x1a\x01@&\x02:\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x02\x00-\x00M\x03\xf3\x043\x00\x14\x00)\x00\x00$\x14\x0f\x01\x06\"'\x01&47\x0162\x1f\x01\x16\x14\a\t\x01\x04\x14\x0f\x01\x06\"'\x01&47\x0162\x1f\x01\x16\x14\a\t\x01\x02s\n2\n\x1a\n\xfe.\n\n\x01\xd2\n\x1a\n2\n\n\xfew\x01\x89\x01\x8a\n2\n\x1a\n\xfe.\n\n\x01\xd2\n\x1a\n2\n\n\xfew\x01\x89\xad\x1a\n2\n\n\x01\xd2\n\x1a\n\x01\xd2\n\n2\n\x1a\n\xfew\xfew\n\x1a\n2\n\n\x01\xd2\n\x1a\n\x01\xd2\n\n2\n\x1a\n\xfew\xfew\x00\x00\x00\x02\x00\r\x00M\x03\xd3\x043\x00\x14\x00)\x00\x00\x00\x14\a\x01\x06\"/\x01&47\t\x01&4?\x0162\x17\x01\x04\x14\a\x01\x06\"/\x01&47\t\x01&4?\x0162\x17\x01\x02S\n\xfe.\n\x1a\n2\n\n\x01\x89\xfew\n\n2\n\x1a\n\x01\xd2\x01\x8a\n\xfe.\n\x1a\n2\n\n\x01\x89\xfew\n\n2\n\x1a\n\x01\xd2\x02M\x1a\n\xfe.\n\n2\n\x1a\n\x01\x89\x01\x89\n\x1a\n2\n\n\xfe.\n\x1a\n\xfe.\n\n2\n\x1a\n\x01\x89\x01\x89\n\x1a\n2\n\n\xfe.\x00\x00\x02\x00M\x00\x8d\x043\x04S\x00\x14\x00)\x00\x00$\x14\x0f\x01\x06\"'\t\x01\x06\"/\x01&47\x0162\x17\x01\x12\x14\x0f\x01\x06\"'\t\x01\x06\"/\x01&47\x0162\x17\x01\x043\n2\n\x1a\n\xfew\xfew\n\x1a\n2\n\n\x01\xd2\n\x1a\n\x01\xd2\n\n2\n\x1a\n\xfew\xfew\n\x1a\n2\n\n\x01\xd2\n\x1a\n\x01\xd2\xed\x1a\n2\n\n\x01\x89\xfew\n\n2\n\x1a\n\x01\xd2\n\n\xfe.\x01v\x1a\n2\n\n\x01\x89\xfew\n\n2\n\x1a\n\x01\xd2\n\n\xfe.\x00\x00\x00\x02\x00M\x00\xad\x043\x04s\x00\x14\x00)\x00\x00\x00\x14\a\x01\x06\"'\x01&4?\x0162\x17\t\x0162\x1f\x01\x12\x14\a\x01\x06\"'\x01&4?\x0162\x17\t\x0162\x1f\x01\x043\n\xfe.\n\x1a\n\xfe.\n\n2\n\x1a\n\x01\x89\x01\x89\n\x1a\n2\n\n\xfe.\n\x1a\n\xfe.\n\n2\n\x1a\n\x01\x89\x01\x89\n\x1a\n2\x02\xad\x1a\n\xfe.\n\n\x01\xd2\n\x1a\n2\n\n\xfew\x01\x89\n\n2\x01v\x1a\n\xfe.\n\n\x01\xd2\n\x1a\n2\n\n\xfew\x01\x89\n\n2\x00\x00\x01\x00-\x00M\x02s\x043\x00\x14\x00\x00\x00\x14\a\t\x01\x16\x14\x0f\x01\x06\"'\x01&47\x0162\x1f\x01\x02s\n\xfew\x01\x89\n\n2\n\x1a\n\xfe.\n\n\x01\xd2\n\x1a\n2\x03\xed\x1a\n\xfew\xfew\n\x1a\n2\n\n\x01\xd2\n\x1a\n\x01\xd2\n\n2\x00\x00\x00\x01\x00\r\x00M\x02S\x043\x00\x14\x00\x00\x00\x14\a\x01\x06\"/\x01&47\t\x01&4?\x0162\x17\x01\x02S\n\xfe.\n\x1a\n2\n\n\x01\x89\xfew\n\n2\n\x1a\n\x01\xd2\x02M\x1a\n\xfe.\n\n2\n\x1a\n\x01\x89\x01\x89\n\x1a\n2\n\n\xfe.\x00\x00\x00\x01\x00M\x01\r\x043\x03S\x00\x14\x00\x00\x00\x14\x0f\x01\x06\"'\t\x01\x06\"/\x01&47\x0162\x17\x01\x043\n2\n\x1a\n\xfew\xfew\n\x1a\n2\n\n\x01\xd2\n\x1a\n\x01\xd2\x01m\x1a\n2\n\n\x01\x89\xfew\n\n2\n\x1a\n\x01\xd2\n\n\xfe.\x00\x00\x00\x01\x00M\x01-\x043\x03s\x00\x14\x00\x00\x00\x14\a\x01\x06\"'\x01&4?\x0162\x17\t\x0162\x1f\x01\x043\n\xfe.\n\x1a\n\xfe.\n\n2\n\x1a\n\x01\x89\x01\x89\n\x1a\n2\x03-\x1a\n\xfe.\n\n\x01\xd2\n\x1a\n2\n\n\xfew\x01\x89\n\n2\x00\x00\x00\x02\x00\x00\xff\x80\a\x80\x06\x00\x00\x0f\x00/\x00\x00\x01\x114&#!\"\x06\x15\x11\x14\x163!26\x13\x11\x14\x06#!\x14\x1e\x01\x15\x14\x06#!\"&54>\x015!\"&5\x11463!2\x16\a\x00\x13\r\xf9\xc0\r\x13\x13\r\x06@\r\x13\x80^B\xfd\xe0 &\x1a\xfe\x00\x1a& \xfd\xe0B^^B\x06@B^\x02 \x03@\r\x13\x13\r\xfc\xc0\r\x13\x13\x03M\xfb\xc0B^%Q=\r\x1a&&\x1a\x0e\x01\x10&\x04\x10\x02\x04 $\x02\x10\x12$ \x04\x03\x94\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\x92\x92\x01r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x04\xa0\x92\xfa\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\xbd\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x02\x00\x00\x00\x00\x06\x80\x05\x80\x00!\x00C\x00\x00\x01\x11\x14\x06#!\"&5\x114>\x02;\x012\x16\x1d\x01\x14\x06+\x01\"\x06\x1d\x01\x14\x16;\x012\x16\x05\x11\x14\x06#!\"&5\x114>\x02;\x012\x16\x1d\x01\x14\x06+\x01\"\x06\x1d\x01\x14\x16;\x012\x16\x03\x00pP\xfe\x80PpQ\x8a\xbdh@\x1a&&\x1a@j\x968(\xe0Pp\x03\x80pP\xfe\x80PpQ\x8a\xbdh@\x1a&&\x1a@j\x968(\xe0Pp\x02@\xfe\x80PppP\x02\xc0h\xbd\x8aQ&\x1a\x80\x1a&\x96j (8pP\xfe\x80PppP\x02\xc0h\xbd\x8aQ&\x1a\x80\x1a&\x96j (8p\x00\x00\x00\x00\x02\x00\x00\x00\x00\x06\x80\x05\x80\x00!\x00C\x00\x00\x01\x11\x14\x0e\x02+\x01\"&=\x0146;\x0126=\x014&+\x01\"&5\x11463!2\x16\x05\x11\x14\x0e\x02+\x01\"&=\x0146;\x0126=\x014&+\x01\"&5\x11463!2\x16\x03\x00Q\x8a\xbdh@\x1a&&\x1a@j\x968(\xe0PppP\x01\x80Pp\x03\x80Q\x8a\xbdh@\x1a&&\x1a@j\x968(\xe0PppP\x01\x80Pp\x04\xc0\xfd@h\xbd\x8aQ&\x1a\x80\x1a&\x96j (8pP\x01\x80PppP\xfd@h\xbd\x8aQ&\x1a\x80\x1a&\x96j (8pP\x01\x80Ppp\x00\x00\x00\x00\b\x00@\xff@\x06\xc0\x06\x00\x00\t\x00\x11\x00\x19\x00#\x00+\x003\x00;\x00G\x00\x00$\x14\x06#\"&5462\x00\x14\x06\"&462\x00\x14\x06\"&462\x01\x14\x06#\"&462\x16\x00\x14\x06\"&462\x00\x14\x06\"&462\x00\x14\x06\"&462\x01\x14\x06#\"&54632\x16\x02\x0eK54LKj\x02=KjKKj\xfd\x8bKjKKj\x04\xfdL45KKjK\xfc<^\x84^^\x84\x04\xf0KjKKj\xfd\xcbp\xa0pp\xa0\x02\x82\x84\\]\x83\x83]\\\x84\xc3jKL45K\xfe\xe7jKKjK\x02ujKKjK\xfd\x8e4LKjKK\x03\xf1\x84^^\x84^\xfd\xa3jKKjK\x02\x90\xa0pp\xa0p\xfer]\x83\x83]\\\x84\x84\x00\x00\x00\x00\x01\x00\x00\xff\x80\x06\x00\x05\x80\x00\v\x00\x00\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x06\x00\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x03Q\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x01\x00\x00\xff\x80\a\x00\x05\xc0\x00,\x00\x00\x01\x14\x03\x0e\x02\a\x06#\"&5465654.\x05+\x01\x11\x14\x06\"'\x01&47\x0162\x16\x15\x113 \x13\x16\a\x00\u007f\x03\x0f\f\a\f\x10\x0f\x11\x05\x05#>bq\x99\x9bb\xe0&4\x13\xfe\x00\x13\x13\x02\x00\x134&\xe0\x02ɢ5\x01\xa0\xa6\xfe\xe3\a\"\x1a\t\x11\x14\x0f\t#\x06D7e\xa0uU6\x1f\f\xff\x00\x1a&\x13\x02\x00\x134\x13\x02\x00\x13&\x1a\xff\x00\xfem\x86\x00\x04\x00\x00\xff\x80\x06\x80\x05\x00\x00\v\x00\x17\x001\x00X\x00\x00\x00\x14\x0e\x01\".\x014>\x012\x16\x04\x14\x0e\x01\".\x014>\x012\x16\x174&#\"\a\x06\"'&#\"\x06\x15\x14\x1e\x03;\x012>\x03\x13\x14\a\x0e\x04#\".\x04'&547&5472\x16\x17632\x17>\x013\x16\x15\x14\a\x16\x02\x80\x19=T=\x19\x19=T=\x02\x99\x19=T=\x19\x19=T=\xb9\x8av)\x9aG\xacG\x98+v\x8a@b\x92\x86R\xa8R\x86\x92b@\xe0=&\x87\x93\xc1\x96\\N\x80\xa7\x8a\x88j!>\x88\x1b3l\xa4k\x93\xa2\x94\x84i\xa4k3\x1b\x88\x01hPTDDTPTDDTPTDDTPTDD|x\xa8\x15\v\v\x15\xa8xX\x83K-\x0e\x0e-K\x83\x01\b\xcf|Mp<#\t\x06\x13)>dA{\xd0\xed\x9fRXtfOT# RNftWQ\xa0\x00\x00\x00\x00\x02\x00\x00\x00\x00\x06\x80\x05\x80\x00\x17\x00,\x00\x00%\x114&#!\"&=\x014&#!\"\x06\x15\x11\x14\x163!26\x13\x11\x14\x06#!\"&5\x11463!2\x16\x1d\x01!2\x16\x06\x008(\xfd@(88(\xfe\xc0(88(\x04\xc0(8\x80\x84\\\xfb@\\\x84\x84\\\x01@\\\x84\x02\xa0\\\x84\xe0\x02\xc0(88(@(88(\xfc@(88\x02\xe8\xfd@\\\x84\x84\\\x03\xc0\\\x84\x84\\ \x84\x00\x00\x03\x00\x00\x00\x00\au\x05\x80\x00\x11\x00'\x00E\x00\x00\x014#!\"\x06\a\x01\x06\x15\x143!267\x016%!54&#!\"&=\x014&#!\"\x06\x15\x11\x01>\x01\x05\x14\a\x01\x0e\x01#!\"&5\x11463!2\x16\x1d\x01!2\x16\x1d\x0132\x16\x17\x16\x06\xf55\xfb\xc0([\x1a\xfe\xda\x125\x04@(\\\x19\x01&\x12\xfb\x8b\x03\x008(\xfd\xc0(88(\xfe\xc0(8\x01\x00,\x90\x059.\xfe\xd9+\x92C\xfb\xc0\\\x84\x84\\\x01@\\\x84\x02 \\\x84\xc06Z\x16\x0f\x02]#+\x1f\xfe\x95\x18\x10#,\x1f\x01k\x16\xb4\xa0(88(@(88(\xfc\xab\x01;5E\xa3>:\xfe\x955E\x84\\\x03\xc0\\\x84\x84\\ \x84\\\xa01. \x00\x00\x00\x00\x05\x00\x00\xff\x80\x06\x00\x05\x80\x00\x14\x00\x1c\x00$\x004\x00@\x00\x00\x01\x0e\x01\"&'&676\x16\x17\x1e\x01267>\x01\x1e\x01\x00\x14\x06\"&462\x04\x14\x06\"&462\x00\x10.\x02 \x0e\x02\x10\x1e\x02 >\x01\x12\x10\x02\x04 $\x02\x10\x12$ \x04\x04n%\xca\xfe\xca%\b\x18\x1a\x19/\b\x19\x87\xa8\x87\x19\b02\x18\xfe\nKjKKj\x02KKjKKj\x01Kf\xab\xed\xfe\xfc\xed\xabff\xab\xed\x01\x04\xed\xab\xe6\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01\xcdy\x94\x94y\x19/\b\b\x18\x1aPccP\x1a\x18\x10/\x01\xcfjKKjKKjKKjK\xfd\xfe\x01\x04\xed\xabff\xab\xed\xfe\xfc\xed\xabff\xab\x02@\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x05\x00\x00\xff\x80\x06\x00\x05\x80\x00\x14\x00\x1c\x00$\x004\x00@\x00\x00\x01\x16\x0e\x01&'.\x01\"\x06\a\x0e\x01'.\x017>\x012\x16\x00\x14\x06\"&462\x04\x14\x06\"&462\x00\x10.\x02 \x0e\x02\x10\x1e\x02 >\x01\x12\x10\x02\x04 $\x02\x10\x12$ \x04\x04n\b\x1820\b\x19\x87\xa8\x87\x19\b/\x19\x1a\x18\b%\xca\xfe\xca\xfe7KjKKj\x02KKjKKj\x01Kf\xab\xed\xfe\xfc\xed\xabff\xab\xed\x01\x04\xed\xab\xe6\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x013\x19/\x10\x18\x1aPccP\x1a\x18\b\b/\x19y\x94\x94\x02\tjKKjKKjKKjK\xfd\xfe\x01\x04\xed\xabff\xab\xed\xfe\xfc\xed\xabff\xab\x02@\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x05\x00\x00\xff\x80\x06\x00\x05\x80\x00\v\x00\x13\x00\x1b\x00+\x007\x00\x00\x00\x14\x06#!\"&463!2\x00\x14\x06\"&462\x04\x14\x06\"&462\x00\x10.\x02 \x0e\x02\x10\x1e\x02 >\x01\x12\x10\x02\x04 $\x02\x10\x12$ \x04\x04\x80&\x1a\xfd\x80\x1a&&\x1a\x02\x80\x1a\xfe&KjKKj\x02KKjKKj\x01Kf\xab\xed\xfe\xfc\xed\xabff\xab\xed\x01\x04\xed\xab\xe6\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01\xda4&&4&\x01\xb5jKKjKKjKKjK\xfd\xfe\x01\x04\xed\xabff\xab\xed\xfe\xfc\xed\xabff\xab\x02@\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x04\x00\x00\x00\x00\a\x80\x04\x00\x00#\x00+\x003\x00C\x00\x00\x0154&+\x0154&+\x01\"\x06\x1d\x01#\"\x06\x1d\x01\x14\x16;\x01\x15\x14\x16;\x0126=\x01326\x044&\"\x06\x14\x162\x004&\"\x06\x14\x162$\x10\x00#\"'#\x06#\"\x00\x10\x003!2\x03@\x12\x0e\xc0\x12\x0e\x80\x0e\x12\xc0\x0e\x12\x12\x0e\xc0\x12\x0e\x80\x0e\x12\xc0\x0e\x12\x02@KjKKj\x01KKjKKj\x01K\xfe\xd4\xd4\xc0\x92ܒ\xc0\xd4\xfe\xd4\x01,\xd4\x03\x80\xd4\x01\xc0\x80\x0e\x12\xc0\x0e\x12\x12\x0e\xc0\x12\x0e\x80\x0e\x12\xc0\x0e\x12\x12\x0e\xc0\x12gjKKjK\x01KjKKjK\xd4\xfeX\xfeԀ\x80\x01,\x01\xa8\x01,\x00\x00\x00\x0f\x00\x00\x00\x00\a\x80\x04\x80\x00\v\x00\x17\x00#\x00/\x00;\x00G\x00S\x00_\x00k\x00w\x00\x83\x00\x8f\x00\x9f\x00\xa3\x00\xb3\x00\x00\x01\x15\x14+\x01\"=\x014;\x0127\x15\x14+\x01\"=\x014;\x012'\x15\x14+\x01\"=\x014;\x012\x01\x15\x14#!\"=\x0143!2%\x15\x14+\x01\"=\x014;\x012'\x15\x14+\x01\"=\x014;\x012\x01\x15\x14+\x01\"=\x014;\x012'\x15\x14+\x01\"=\x014;\x012\x01\x15\x14+\x01\"=\x014;\x012\x01\x15\x14+\x01\"=\x014;\x012\x01\x15\x14+\x01\"=\x014;\x012\x05\x15\x14+\x01\"=\x014;\x012\x05\x11\x14+\x01\"=\x014;\x0154;\x012\x13\x11!\x11\x01\x11\x14\x06#!\"&5\x11463!2\x16\x01\x80\x10`\x10\x10`\x10\x80\x10\xe0\x10\x10\xe0\x10\x80\x10`\x10\x10`\x10\x04\x00\x10\xfc\xa0\x10\x10\x03`\x10\xfd\x80\x10`\x10\x10`\x10\x80\x10`\x10\x10`\x10\x01\x80\x10`\x10\x10`\x10\x80\x10`\x10\x10`\x10\x01\x80\x10`\x10\x10`\x10\x01\x80\x10`\x10\x10`\x10\xfe\x00\x10`\x10\x10`\x10\x01\x00\x10`\x10\x10`\x10\x01\x00\x10\xe0\x10\x10p\x10`\x10\x80\xf9\x80\a\x00K5\xf9\x805KK5\x06\x805K\x01p`\x10\x10`\x10\xf0`\x10\x10`\x10\xf0`\x10\x10`\x10\xfd\xf0`\x10\x10`\x10\xf0`\x10\x10`\x10\xf0`\x10\x10`\x10\xfe\xf0`\x10\x10`\x10\xf0`\x10\x10`\x10\xfe\xf0`\x10\x10`\x10\xfe\xf0`\x10\x10`\x10\x01\xf0`\x10\x10`\x10\x10`\x10\x10`\x10\x10\xfe\xa0\x10\x10`\x10\xf0\x10\xfd\x00\x03\x80\xfc\x80\x03\x80\xfc\x805KK5\x03\x805KK\x00\x00\x00\x00\x03\x00@\xff\x80\a\x00\x05\x80\x00\x16\x00*\x00V\x00\x00\x01\x11\x06#\"'.\x01#\"\a\x11632\x1e\x02\x1f\x01\x1632\x01\x14\x06\a\x11\x14\x06+\x01\"&5\x11.\x015462\x16\x05\x11\x14\a\x06\a\x06#\"/\x01.\x02#\"\x04\a\x06#\"'&5\x1147>\x0332\x16\x17\x16327676\x17\x16\x06\x80\xa9\x89R?d\xa8^\xad\xe6\xf5\xbc7ac77\x1c,9x\xfbm#\x1d\x12\x0e@\x0e\x12\x1d#KjK\x05\xc0#\n\aڗXF\x1c@Fp:f\xfe\xf5_\x0f\x12\x10\x10 \x1f#W\x8d\xa4Ip\xc2p&3z\xbc\x16\t\x1f\x1f\x1f\x01\xeb\x02h[ 17\u007f\xfd\xa9q\x0f%\x19\x1b\x0e\x16\x03q#:\x11\xfb\x0e\x0e\x12\x12\x0e\x04\xf2\x11:#5KKu\xfd\x05'\x12\x05\x04t#\x0e!\x1e\x1cX:\t\b\x13%\x02\xe6#\x14\x15+=&>7\x13p\f\x05\x10\x12\x14\x00\x00\x06\x00@\xff\x80\a\x00\x05\x80\x00\x05\x00\v\x00*\x002\x00F\x00r\x00\x00\x015\x06\a\x156\x135\x06\a\x156\x015\x06'5&'.\t#\"\a\x1532\x16\x17\x16\x17\x15\x1632\x135\x06#\"'\x15\x16\x01\x14\x06\a\x11\x14\x06+\x01\"&5\x11.\x015462\x16\x05\x11\x14\a\x06\a\x06#\"/\x01.\x02#\"\x04\a\x06#\"'&5\x1147>\x0332\x16\x17\x16327676\x17\x16\x03@\xb5\xcbͳ\xac\xd4\xd7\x03\xe9\xeb\x95\x14\x13\x058\r2\x13.\x1a,#,\x16\x17\x1a\x13f\xb5k\x13\x14*1x\xad\xa9\x89-!\x94\xfb\xac#\x1d\x12\x0e@\x0e\x12\x1d#KjK\x05\xc0#\n\aڗXF\x1c@Fp:f\xfe\xf5_\x0f\x12\x10\x10 \x1f#W\x8d\xa4Ip\xc2p&3z\xbc\x16\t\x1f\x1f\x1f\x02\x18\xc0\x10e\xb9`\x01\xb0\xc5\bv\xbdo\xfe8\xb8t-\xe0\x06\t\x03\x1c\x06\x18\a\x13\x06\v\x04\x04\x03\xde:5\t\x06\xbc\x11\x02\a\xbd[\b\xc4*\x01\xee#:\x11\xfb\x0e\x0e\x12\x12\x0e\x04\xf2\x11:#5KKu\xfd\x05'\x12\x05\x04t#\x0e!\x1e\x1cX:\t\b\x13%\x02\xe6#\x14\x15+=&>7\x13p\f\x05\x10\x12\x14\x00\x02\x00\r\x00\x00\x06\x80\x043\x00\x14\x00$\x00\x00\t\x01\x06\"/\x01&47\t\x01&4?\x0162\x17\x01\x16\x14\x01\x15\x14\x06#!\"&=\x01463!2\x16\x02I\xfe.\n\x1a\n2\n\n\x01\x89\xfew\n\n2\n\x1a\n\x01\xd2\n\x04-\x12\x0e\xfc@\x0e\x12\x12\x0e\x03\xc0\x0e\x12\x02)\xfe.\n\n2\n\x1a\n\x01\x89\x01\x89\n\x1a\n2\n\n\xfe.\n\x1a\xfe-@\x0e\x12\x12\x0e@\x0e\x12\x12\x00\x00\x00\x00\x03\x00-\xff\x93\aS\x04\xed\x00\x14\x00$\x009\x00\x00%\a\x06\"'\x01&47\x0162\x1f\x01\x16\x14\a\t\x01\x16\x14\t\x01\x0e\x01/\x01.\x017\x01>\x01\x1f\x01\x1e\x01\t\x01\x06\"/\x01&47\t\x01&4?\x0162\x17\x01\x16\x14\x02i2\n\x1a\n\xfe.\n\n\x01\xd2\n\x1a\n2\n\n\xfew\x01\x89\n\x02E\xfe\x8b\x04\x17\f>\r\r\x04\x01u\x04\x17\f>\r\r\x02\x8d\xfe.\n\x1a\n2\n\n\x01\x89\xfew\n\n2\n\x1a\n\x01\xd2\n\x892\n\n\x01\xd2\n\x1a\n\x01\xd2\n\n2\n\x1a\n\xfew\xfew\n\x1a\x04!\xfa\xf5\r\r\x04\x11\x04\x17\r\x05\v\r\r\x04\x11\x04\x17\xfdh\xfe.\n\n2\n\x1a\n\x01\x89\x01\x89\n\x1a\n2\n\n\xfe.\n\x1a\x00\x00\x02\x00\x00\xff\x80\a\x00\x05\xbb\x00\x15\x00;\x00\x00\x01\x15\x14\a\x06#\"'\x01&47\x016\x17\x16\x1d\x01\x01\x06\x14\x17\x01\x14\x0e\x03\a\x06#\"'&7\x12'.\x01'\x15\x14\a\x06#\"'\x01&47\x016\x17\x16\x15\x11\x04\x17\x16\x02\x80'\r\f\x1b\x12\xfe\x00\x13\x13\x02\x00\x1d)'\xfes\x13\x13\x06\r\"+5\x1c\x06\b\x14\x06\x03\x19\x02+\x95@ա'\r\f\x1b\x12\xfe\x00\x13\x13\x02\x00\x1d)'\x01\x9b\xbc\xa9\x01\xc6F*\x11\x05\x13\x02\x00\x134\x13\x02\x00\x1f\x11\x11*E\xfer\x134\x13\xfeM:\x97}}8\f\x11\x01\b\x1a\x01\x90\xa5GO\r\xfb*\x11\x05\x13\x02\x00\x134\x13\x02\x00\x1f\x11\x11*\xfe\xfa\x1c\xc1\xad\x00\x00\x00\x00\x02\x00\x02\xff\xad\x06~\x05\xe0\x00\n\x00(\x00\x00\x01-\x01/\x01\x03\x11\x17\x05\x03'\t\x01\x13\x16\x06#\"'%\x05\x06#\"&7\x13\x01&67%\x13632\x17\x13\x05\x1e\x01\x04\xa2\x01\x01\xfe\x9cB\x1e\x9f;\x01><\f\x01\xf5\xfe\x95V\x05\x16\x17\x11\x17\xfe?\xfe?\x17\x11\x17\x16\x05V\xfe\x94 \x12-\x01\xf6\xe1\x14\x1d\x1c\x15\xe1\x01\xf6-\x12\x02C\xfa4\n<\x01B\xfc=\x1f\xa8\x01cB\x015\xfe\x9e\xfe\f!%\f\xec\xec\f%!\x01\xf4\x01b 7\aI\x01\xc7))\xfe9I\a7\x00\x00\x00\x01\x00\x02\xff\x80\x05\x80\x05\x00\x00\x16\x00\x00\t\x01\x06#\"'.\x015\x11!\".\x0167\x01632\x17\x1e\x01\x05y\xfd\x80\x11(\x05\n\x16\x1b\xfd\xc0\x16#\n\x12\x14\x05\x00\r\x10\x1b\x12\x0f\a\x04\xa3\xfb\x00#\x02\x05#\x16\x02@\x1b,(\n\x02\x80\a\x13\x0e)\x00\x00\x03\x00\x00\xff\x00\x06\x80\x05\x80\x00\x02\x00\x05\x008\x00\x00\x01!\x11\t\x01!\x01\x15\x14\x06+\x01\x15\x14\x06+\x01\"&=\x01!\"&5\x11#\"&=\x0146;\x01546;\x012\x16\x1d\x01!762\x17\x16\x14\x0f\x01\x1132\x16\x02-\x02S\xfd\x80\x02S\xfd\xad\x04\x80\x12\x0e\xe0\x12\x0e\xc0\x0e\x12\xfc\xa0\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\x12\x0e\xc0\x0e\x12\x03S\xf6\n\x1a\n\t\t\xf7\xe0\x0e\x12\x01\x00\x02S\xfd\xda\x02S\xfd`\xc0\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\x12\x0e\x03`\x12\x0e\xc0\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\xf7\t\t\n\x1a\n\xf6\xfc\xad\x12\x00\x00\x00\x04\x00\x00\xff\x80\x04\x00\x05\x80\x00\a\x00\x0f\x00\x17\x00K\x00\x00$4&\"\x06\x14\x162\x124&\"\x06\x14\x162\x044&\"\x06\x14\x1627\x14\x06\a\x02\a\x06\a\x0e\x01\x1d\x01\x1e\x01\x15\x14\x06\"&5467\x11.\x015462\x16\x15\x14\x06\a\x1167>\x055.\x015462\x16\x01 8P88P88P88P\x02\xb88P88P\x984,\x02\xe0C\x88\x80S,4p\xa0p4,,4p\xa0p4,6d7AL*'\x11,4p\xa0p\x18P88P8\x04\xb8P88P8HP88P8`4Y\x19\xfe\xe1\u007f&+(>E\x1a\x19Y4PppP4Y\x19\x034\x19Y4PppP4Y\x19\xfe\x0f\x1a\x1f\x11\x19%*\x0154&#\"\a\x06\a\x06#\"/\x01.\x017\x12!2\x1e\x02\x02\xc0\x18\x10\xf0\x10\x18\x18\x10\xf0\x10\x18\x01<\x1f'G,')7\x18\x10\xf0\x0f\x15\x82N;2]=A+#H\r\x12\f\r\xa4\r\x05\b\xa0\x010P\xa2\x82R\x01\x18\xf0\x10\x18\x18\x10\xf0\x10\x18\x18\x02H6^;<\x1b\x16\x17T\x19\x11\x1f%\x13-S\x93#\x1b:/*@\x1d\x19Z\x10\b}\n\x1e\r\x01\n>h\x97\x00\x00\x00\x02\x00\x00\x00\x00\x02\x80\x05\x80\x00\x1e\x00.\x00\x00%\x15\x14\x06#!\"&=\x0146;\x01\x11#\"&=\x01463!2\x16\x15\x1132\x16\x03\x15\x14\x06#!\"&=\x01463!2\x16\x02\x80&\x1a\xfe\x00\x1a&&\x1a@@\x1a&&\x1a\x01\x80\x1a&@\x1a&\x80&\x1a\xff\x00\x1a&&\x1a\x01\x00\x1a&\xc0\x80\x1a&&\x1a\x80\x1a&\x01\x80&\x1a\x80\x1a&&\x1a\xfd\xc0&\x04f\xc0\x1a&&\x1a\xc0\x1a&&\x00\x00\x02\x00b\x00\x00\x02\x1e\x05\x80\x00\x0f\x00\x1f\x00\x00\x01\x15\x14\x06#!\"&=\x01463!2\x16\x13\x03\x0e\x01#!\"&'\x03&63!2\x16\x02\x00&\x1a\xff\x00\x1a&&\x1a\x01\x00\x1a&\x1e\x1c\x01'\x1a\xff\x00\x1a'\x01\x1c\x01%\x1a\x01@\x1a%\x01 \xe0\x1a&&\x1a\xe0\x1a&&\x04\x06\xfd\x00\x1a&&\x1a\x03\x00\x1a&&\x00\x02\x00\x05\x00\x00\x05\xfe\x05k\x00%\x00J\x00\x00%\x15#/\x01&'#\x0e\x02\a\x06\x0f\x01!53\x13\x03#5!\x17\x16\x17\x16\x1736?\x02!\x15#\x03\x13\x01\x15!'&54>\x0454&#\"\a\x06\a'67632\x16\x15\x14\x0e\x04\a35\x03\x81\xf8\x9f\x18\b\x03\x03\x01\x03\x04\x01\n\x0f\x9b\xfe\xfe\x80Ź\x89\x01\x14\x8b\x02\x15\b\x03\x03\x03\b\x19\x8c\x01\x01}\xb8\xcc\x02\xea\xfd\xfe\x03\x044NZN4;)3.\x0e\x16i\x1a%Sin\x881KXL7\x03觧\xfc*\t\f\x03\a\t\x02\x14\x18\xfa\xa7\x01#\x01\x10\xa8\xe4\x04&\t\f\t\f*\xe4\xa8\xfe\xf5\xfe\xd8\x02\xa7\xce\x1b\x1c\x12@jC?.>!&1'\v\x1b\\%\x1dAwc8^;:+\x0454&#\"\a\x06\a'67632\x16\x15\x14\x0e\x03\a35\x03\x81\xf8\x9f\x18\b\x03\x03\x01\x03\x04\x01\n\x0f\x9b\xfe\xfe\x80Ź\x89\x01\x14\x8b\x02\x15\b\x03\x03\x03\b\x19\x8c\x01\x01}\xb8\xcc\x02\xec\xfd\xfe\x04\x034NZN4;)3.\x0e\x16i\x1a%Pln\x88EcdJ\x04觧\xfc*\t\f\x03\a\t\x02\x14\x18\xfa\xa7\x01#\x01\x10\xa8\xe4\x04&\t\f\t\f*\xe4\xa8\xfe\xf5\xfe\xd8\xd9\xce\x1b-\x01@jC?.>!&1'\v\x1b\\%\x1dAwcBiC:D'P\x00\x00\x00\x02\x00\x01\x00\x00\a\u007f\x05\x00\x00\x03\x00\x17\x00\x00%\x01!\t\x01\x16\x06\a\x01\x06#!\"&'&67\x0163!2\x16\x03\x80\x01P\xfd\x00\xfe\xb0\x06\xf5\x0f\v\x19\xfc\x80&:\xfd\x00&?\x10\x0f\v\x19\x03\x80&:\x03\x00&?\x80\x01\x80\xfe\x80\x045\"K\x1c\xfc\x00,)\"\"K\x1c\x04\x00,)\x00\x00\x01\x00\x00\xff\xdc\x06\x80\x06\x00\x00h\x00\x00\x01\x14\x06#\".\x02#\"\x15\x14\x16\a\x15\"\a\x0e\x02#\"&54>\x0254&#\"\x06\x15\x14\x1e\x02\x15\x14\a\x06#\"'.\x01/\x01\"'\"5\x11\x1e\x02\x17\x16327654.\x0254632\x16\x15\x14\x0e\x02\x15\x14\x163267\x15\x0e\x02\a\x06\x15\x14\x17\x1632>\x0232\x16\x06\x80YO)I-D%n \x01\x16\v\"\u007fh.=T#)#lQTv\x1e%\x1e.%P_\x96\t%\t\r\x01\x02\x02\x02\x1f%\x03\x96_P%.\x1e%\x1evUPl#)#T=@\xe8/\x01\x05\x05\x01\x18#,-\x1691P+R[\x01\xb6Ql#)#|'\x98'\x05\x01\x03\x11\n59%D-I)OY[R+P19\x16-,#\x18\x02\x04\x02\x02\x01\x01\x04\x00\x01\x05\x05\x01\x18#,-\x1691P+R[YO)I-D%95\x1e\x02\x02\x02\x1f%\x03\x96_P%.\x1e%\x1ev\x00\x00\x02\x00\x00\xff\x80\x04\x80\x06\x00\x00'\x003\x00\x00\x01\x15\x14\x00\a\x15!2\x16\x14\x06#!\"&463!5&\x00=\x01462\x16\x1d\x01\x14\x00 \x00=\x01462\x16\x01\x11\x14\x06 &5\x1146 \x16\x04\x80\xfe\xd9\xd9\x01\x00\x1a&&\x1a\xfd\x80\x1a&&\x1a\x01\x00\xd9\xfe\xd9&4&\x01\a\x01r\x01\a&4&\xff\x00\xbc\xfe\xf8\xbc\xbc\x01\b\xbc\x03@\x80\xdd\xfe\xb9\x18\x84&4&&4&\x84\x18\x01G݀\x1a&&\x1a\x80\xb9\xfe\xf9\x01\a\xb9\x80\x1a&&\x01f\xfe\x00\x84\xbc\xbc\x84\x02\x00\x84\xbc\xbc\x00\x03\x00\r\xff\x80\x05s\x06\x00\x00\v\x00C\x00K\x00\x00\x01\a&=\x01462\x16\x1d\x01\x14\t\x01\x15\x14\x06#\"'\a\x1632\x00=\x01462\x16\x1d\x01\x14\x00\a\x15!2\x16\x14\x06#!\"&463!5&'\a\x06\"/\x01&47\x0162\x1f\x01\x16\x14%\x01\x114632\x16\x01\x0fe*&4&\x04i\xfe\x97\xbc\x8476`al\xb9\x01\a&4&\xfe\xd9\xd9\x01\x00\x1a&&\x1a\xfd\x80\x1a&&\x1a\x01\x00}n\xfe\n\x1a\nR\n\n\x04\xd2\n\x1a\nR\n\xfez\xfd\x93\xbc\x84f\xa5\x02Oego\x80\x1a&&\x1a\x805\x02\x1e\xfe\x97\x80\x84\xbc\x13`3\x01\a\xb9\x80\x1a&&\x1a\x80\xdd\xfe\xb9\x18\x84&4&&4&\x84\rD\xfe\n\nR\n\x1a\n\x04\xd2\n\nR\n\x1az\xfd\x93\x02\x00\x84\xbcv\x00\x00\x00\x02\x00\x00\xff\x80\x05\x00\x05\x80\x00\x06\x00\"\x00\x00\x01\x11!\x11676\x13\x11\x14\x0e\x05\a\x06\"'.\x065\x11463!2\x16\x04@\xfe@w^\xeb\xc0Cc\x89t~5\x10\f\x1c\f\x105~t\x89cC&\x1a\x04\x80\x1a&\x02@\x02\x80\xfb\x8f?J\xb8\x03\xb0\xfd\x00V\xa9\x83|RI\x1a\a\x06\x06\a\x1aIR|\x83\xa9V\x03\x00\x1a&&\x00\x00\x00\x00\x04\x00\x00\xff\x00\x06\x80\x06\x00\x00\x03\x00\x13\x00#\x00G\x00\x00\x17!\x11!%\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126%\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126%\x11\x14\x06#!\"&5\x1146;\x01546;\x012\x16\x1d\x01!546;\x012\x16\x1d\x0132\x16\x80\x05\x80\xfa\x80\x01\x80\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x03\x00\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x01\x80L4\xfa\x804LL4\x80^B@B^\x01\x80^B@B^\x804L\x80\x04\x00\xc0\x01 \x0e\x12\x12\x0e\xfe\xe0\x0e\x12\x12\x0e\x01 \x0e\x12\x12\x0e\xfe\xe0\x0e\x12\x12N\xfb\x004LL4\x05\x004L`B^^B``B^^B`L\x00\x00\x00\x02\x00\x03\xff\x80\x05\x80\x05\xe0\x00\a\x00L\x00\x00\x004&\"\x06\x14\x162%\x11\x14\a\x06#\"'%.\x015!\x15\x1e\x01\x15\x11\x14\x06#!\"&5\x114675#\"\x0e\x03\a\x06#\"'.\x017>\x047&5462\x16\x15\x14\a!467%632\x17\x16\x02\x00&4&&4\x03\xa6\f\b\f\x04\x03\xfe@\v\x0e\xff\x00o\x91&\x1a\xfe\x00\x1a&}c ;pG=\x14\x04\x11(\x10\r\x17\x11\f\x05\x138Ai8\x19^\x84^\x0e\x01.\x0e\v\x01\xc0\x03\x04\f\b\f\x05&4&&4&`\xfe\xc0\x10\t\a\x01`\x02\x12\vf\x17\xb0s\xfc\xe0\x1a&&\x1a\x03 j\xa9\x1eo/;J!\b#\a\f2\x18\n KAE\x12*,B^^B!\x1f\v\x12\x02`\x01\a\t\x00\x00\x02\x00$\xff \x06\x80\x05\x80\x00\a\x00-\x00\x00\x004&\"\x06\x14\x162\x01\x14\x02\a\x06\a\x03\x06\a\x05\x06#\"/\x01&7\x13\x01\x05\x06#\"/\x01&7\x1367%676$!2\x16\x05\xa08P88P\x01\x18\x97\xb2Qr\x14\x02\x0e\xfe\x80\a\t\f\v@\r\x05U\xfe\xe7\xfe\xec\x03\x06\x0e\t@\x11\f\xe0\n\x10\x01{`P\xbc\x01T\x01\x05\x0e\x14\x04\x18P88P8\x01\x80\xf9\xfe\x95\xb3P`\xfe\x85\x10\n\xe0\x04\t@\x0e\x12\x01\x14\x01\x19U\x01\t@\x13\x14\x01\x80\x0e\x02\x14rQ\xbb\x8e\x13\x00\x00\x00\x01\x00\x00\x00\x00\x06\xd1\x05\x00\x00\x16\x00\x00\x01\x03!\x136'&+\x01\x03!\x13!\x03!\x13\x03!2\x16\x17\x1e\x01\x06Ѥ\xfe\xb2\xb2\r\x1c\x1b8\xa9\xcc\xfe\xb2\xcc\xfe\xe2\xcc\xfe\xb2̙\x04\xfce\xb1;<*\x02\xfb\xfd\x05\x03@8 !\xfcG\x03\xb9\xfcG\x03\xb9\x01GQII\xbf\x00\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x14\x00 \x00\x00%764'\t\x0164/\x01&\"\a\x01\x06\x14\x17\x01\x162\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x03\x8df\x13\x13\xfe\xcd\x013\x13\x13f\x134\x13\xfe:\x13\x13\x01\xc6\x134\x02\x86\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x8df\x134\x13\x013\x013\x134\x13f\x13\x13\xfe:\x134\x13\xfe:\x13\x02\xd7\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x14\x00 \x00\x00%\x0164'\x01&\"\x0f\x01\x06\x14\x17\t\x01\x06\x14\x1f\x01\x162\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x02\xcd\x01\xc6\x13\x13\xfe:\x134\x13f\x13\x13\x013\xfe\xcd\x13\x13f\x134\x03F\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x8d\x01\xc6\x134\x13\x01\xc6\x13\x13f\x134\x13\xfe\xcd\xfe\xcd\x134\x13f\x13\x02\xd7\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x14\x00 \x00\x00\x01764'\x01&\"\a\x01\x06\x14\x1f\x01\x1627\t\x01\x162\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04\x8df\x13\x13\xfe:\x134\x13\xfe:\x13\x13f\x134\x13\x013\x013\x134\x01\x86\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01\x8df\x134\x13\x01\xc6\x13\x13\xfe:\x134\x13f\x13\x13\x013\xfe\xcd\x13\x01\xd7\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x14\x00 \x00\x00%\x0164/\x01&\"\a\t\x01&\"\x0f\x01\x06\x14\x17\x01\x162\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x03-\x01\xc6\x13\x13f\x134\x13\xfe\xcd\xfe\xcd\x134\x13f\x13\x13\x01\xc6\x134\x02\xe6\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xed\x01\xc6\x134\x13f\x13\x13\xfe\xcd\x013\x13\x13f\x134\x13\xfe:\x13\x02w\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x02\x00\x00\xff@\x05\x80\x05\x80\x00\x11\x00\x16\x00\x00\x017!\x13!\x0f\x01/\x01#\x13\x0535%\x13!'\x01!\x03\x05%\x04j\x10\xfc\x8c/\x02d\x16\xc5\xc4\r\xaf\x16\x01j\x04\x01g2\xfd|\x0f\xfe8\x05\x80\x80\xfd\xbe\xfd\xc2\x03\xab\xaf\xfd\xea\xe455\x8c\xfe\xead\x01c\x02 \xb5\x01\xd5\xfab\xa2\xa2\x00\x00\x00\x01\x00\f\xff@\x06\xf4\x05\x80\x00\x0f\x00\x00\x01!\t\x02\x13!\a\x05%\x13!\x13!7!\x01\x13\x05\xe1\xfe\xf6\xfc\xdc\xfdFG\x01)\x1d\x01\xa6\x01\xe6D\xfbH:\x04\xb9&\xfbH\x05\x80\xfa\xcb\xfe\xf5\x01\v\x01d\x93\xa1\xa1\x01S\x01)\xbf\x00\x00\x00\x02\x00\x00\xff\x10\a\x00\x06\x00\x00\a\x00U\x00\x00\x004&\"\x06\x14\x162\x01\x11\x14\a\x06#\"/\x01\x06\x04 $'\a\x06#\"'&5\x11463!2\x17\x16\x0f\x01\x1e\x01\x17\x11#\"&=\x0146;\x015.\x015462\x16\x15\x14\x06\a\x1532\x16\x1d\x01\x14\x06+\x01\x11>\x017'&763!2\x16\x03\xc0&4&&4\x03f\x14\b\x04\f\v]w\xfeq\xfe4\xfeqw]\t\x0e\x04\b\x14\x12\x0e\x01`\x16\b\b\x0fdC\xf5\x95\xc0\x1a&&\x1a\xc0:F\x96ԖF:\xc0\x1a&&\x1a\xc0\x95\xf5Cd\x0f\b\b\x16\x01`\x0e\x12\x04\xe64&&4&\xfc\xa0\xfe\xa0\x16\b\x02\t]\x8f\xa7\xa7\x8f]\t\x02\b\x16\x01`\x0e\x12\x14\x13\x10d[}\x14\x02\x87&\x1a\x80\x1a&\xa3\"uFj\x96\x96jFu\"\xa3&\x1a\x80\x1a&\xfdy\x14}[d\x10\x13\x14\x12\x00\x01\x00\x00\x00\x00\x04\x80\x06\x00\x00#\x00\x00\x012\x16\x15\x11\x14\x06#!\"&5\x1146;\x01\x114\x00 \x00\x15\x14\x06+\x01\"&54&\"\x06\x15\x11\x04 (88(\xfc@(88( \x01\a\x01r\x01\a&\x1a@\x1a&\x96Ԗ\x03\x008(\xfd\xc0(88(\x02@(8\x01@\xb9\x01\a\xfe\xf9\xb9\x1a&&\x1aj\x96\x96j\xfe\xc0\x00\x00\x00\x00\x05\x00\x00\xff\x80\x06\x00\x05\x80\x00\a\x00\x0f\x00\x17\x00'\x003\x00\x00\x00\x14\x06\"&462\x00\x10& \x06\x10\x16 \x00\x10\x00 \x00\x10\x00 \x00\x10.\x02 \x0e\x02\x10\x1e\x02 >\x01\x12\x10\x02\x04 $\x02\x10\x12$ \x04\x04\x00\x96Ԗ\x96\xd4\x01\x16\xe1\xfe\xc2\xe1\xe1\x01>\x01a\xfe\xd4\xfeX\xfe\xd4\x01,\x01\xa8\x01\xacf\xab\xed\xfe\xfc\xed\xabff\xab\xed\x01\x04\xed\xab\xe6\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02\xeaԖ\x96Ԗ\xfea\x01>\xe1\xe1\xfe\xc2\xe1\x02T\xfeX\xfe\xd4\x01,\x01\xa8\x01,\xfd~\x01\x04\xed\xabff\xab\xed\xfe\xfc\xed\xabff\xab\x02@\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x00\x03\x00\x00\x02\x00\x05\x80\x03\x80\x00\x0f\x00\x1f\x00/\x00\x00\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x05\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x05\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x808(\xc0(88(\xc0(8\x02\x008(\xc0(88(\xc0(8\x02\x008(\xc0(88(\xc0(8\x03 \xc0(88(\xc0(88(\xc0(88(\xc0(88(\xc0(88(\xc0(88\x00\x00\x00\x00\x03\x00\x00\x00\x00\x01\x80\x05\x80\x00\x0f\x00\x1f\x00/\x00\x00\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x11\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x11\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x808(\xc0(88(\xc0(88(\xc0(88(\xc0(88(\xc0(88(\xc0(8\x01 \xc0(88(\xc0(88\x01\xd8\xc0(88(\xc0(88\x01\xd8\xc0(88(\xc0(88\x00\x00\x04\x00\x00\xff\x80\x06\x00\x05\x80\x00\a\x00\x1b\x005\x00E\x00\x00$4&\"\x06\x14\x162%&\x00'&\x06\x1d\x01\x14\x16\x17\x1e\x01\x17\x1e\x01;\x0126%&\x02.\x01$'&\a\x06\x1d\x01\x14\x16\x17\x16\x04\x12\x17\x1e\x01;\x01276\x01\x11\x14\x06#!\"&5\x11463!2\x16\x02\x00KjKKj\x01\xaa\r\xfe\xb9\xe9\x0e\x14\x11\r\x9a\xdc\v\x01\x12\r\x80\r\x14\x01\u007f\x05f\xb1\xe9\xfe\xe1\x9a\x0e\t\n\x12\r\xcc\x01\\\xd1\a\x01\x12\r\x80\r\n\v\x01\x1f\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\xcbjKKjK\"\xe9\x01G\r\x01\x14\r\x80\r\x12\x01\vܚ\r\x11\x14\r\x9a\x01\x1f\xe9\xb1f\x05\x01\n\n\r\x80\r\x12\x01\a\xd1\xfe\xa4\xcc\r\x12\n\t\x03\xcd\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\v\x00\x1b\x00\x00\x00 \x04\x12\x10\x02\x04 $\x02\x10\x12\x0164'\x01&\a\x06\x15\x11\x14\x17\x16327\x02/\x01\xa2\x01a\xce\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x03\xb2 \xfd\xe0\x1f! \x10\x10\x11\x0f\x05\x80\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xfd\x97\x12J\x12\x01@\x13\x12\x13%\xfd\x80%\x13\b\t\x00\x03\x006\xff5\x06\xcb\x05\xca\x00\x03\x00\x13\x00/\x00\x00\t\x0564'\x01&\"\a\x01\x06\x14\x17\x01\x162\t\x01\x06\"/\x0164&\"\a'&47\x0162\x1f\x01\x06\x14\x1627\x17\x16\x14\x04\x00\x01<\xfd\xc4\xfe\xc4\x01i\x02j\x13\x13\xfe\x96\x126\x12\xfd\x96\x13\x13\x01j\x126\x03\x8b\xfcu%k%~8p\xa08}%%\x03\x8b%k%}8p\xa08~%\x04<\xfe\xc4\xfd\xc4\x01<\xfei\x02j\x134\x13\x01j\x12\x12\xfd\x96\x134\x13\xfe\x96\x12\x02\x8f\xfct%%~8\xa0p8~%k%\x03\x8a%%}8\xa0p8}%k\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x1f\x00\x00\x0154&#!\"\x06\x1d\x01\x14\x163!26\x01\x11\x14\x06#!\"&5\x11463!2\x16\x05\x00&\x1a\xfc\x80\x1a&&\x1a\x03\x80\x1a&\x01\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x02@\x80\x1a&&\x1a\x80\x1a&&\x02:\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x03\x00\x00\x00\x00\x05\x80\x05\x80\x00\x0f\x00\x1f\x00/\x00\x00\x01\x15\x14\x06#!\"&=\x01463!2\x16\x13\x114&#!\"\x06\x15\x11\x14\x163!26\x13\x11\x14\x06#!\"&5\x11463!2\x16\x04\x80\x12\x0e\xfc\xc0\x0e\x12\x12\x0e\x03@\x0e\x12\x80^B\xfc\xc0B^^B\x03@B^\x80\xa9w\xfc\xc0w\xa9\xa9w\x03@w\xa9\x02\xe0@\x0e\x12\x12\x0e@\x0e\x12\x12\xfe2\x03@B^^B\xfc\xc0B^^\x03\x82\xfc\xc0w\xa9\xa9w\x03@w\xa9\xa9\x00\x00\x01\x00\x03\x00\x00\x03\xfa\x05\u007f\x00\x1c\x00\x00\x01\x06+\x01\x11\x14\x06#!\"'&?\x0163!\x11#\"'&7\x0162\x17\x01\x16\x03\xfa\x12(\xc0\x12\x0e\xfd@\x15\b\b\f\xa0\t\x10\x01@\xc0(\x12\x11\x1a\x01@\x12>\x12\x01@\x1b\x03\xa5%\xfc\xa0\x0e\x12\x12\x14\x0f\xc0\v\x02\x80%%\x1f\x01\x80\x16\x16\xfe\x80 \x00\x00\x00\x01\x00\x03\xff\x80\x03\xfa\x05\x00\x00\x1b\x00\x00\x13!2\x16\x15\x1132\x16\a\x01\x06\"'\x01&76;\x01\x11!\"/\x01&76 \x02\xc0\r\x13\xc0($\x1b\xfe\xc0\x12>\x12\xfe\xc0\x1a\x11\x12(\xc0\xfe\xc0\x0e\v\xa0\r\t\t\x05\x00\x13\x0e\xfc\xa1J \xfe\x80\x16\x16\x01\x80\x1f&%\x02\x80\v\xc0\x0e\x14\x13\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x14\x00$\x00\x00%\x0164/\x01&\"\a\x01'&\"\x0f\x01\x06\x14\x17\x01\x162\x01\x11\x14\x06#!\"&5\x11463!2\x16\x02\xad\x02f\x13\x13f\x134\x13\xfe-\xd3\x134\x13f\x13\x13\x01f\x134\x03f\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\xed\x02f\x134\x13f\x13\x13\xfe-\xd3\x13\x13f\x134\x13\xfe\x9a\x13\x03\x86\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x05\x00\x00\xff\x80\x06\x00\x05\x80\x00\x06\x00\x10\x00\x15\x00\x1f\x00/\x00\x00\x01\x17\a#5#5\x01\x16\a\x01\x06'&7\x016\t\x03\x11\x01764/\x01&\"\x0f\x01%\x11\x14\x06#!\"&5\x11463!2\x16\x01\x94\x9848`\x01\xd2\x0e\x11\xfe\xdd\x11\r\x0e\x11\x01#\x11\xfe\xfb\x02 \xfe\xe0\xfd\xe0\x03\x80\\\x1c\x1c\x98\x1cP\x1c\\\x02\xa0\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x01\xac\x984`8\x01\xba\r\x11\xfe\xdd\x11\x0e\r\x11\x01#\x11\xfd@\x02 \x01 \xfd\xe0\xfe\xe0\x02`\\\x1cP\x1c\x98\x1c\x1c\\`\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x19\x00)\x00\x00\x01\x114&#!\"\a\x06\x1f\x01\x01\x06\x14\x1f\x01\x1627\x01\x17\x163276\x01\x11\x14\x06#!\"&5\x11463!2\x16\x05\x00&\x1a\xfe *\x11\x11\x1f\x90\xfd\xea\x13\x13f\x134\x13\x02\x16\x90\x12\x1b\f\r'\x01\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x02`\x01\xe0\x1a&')\x1d\x90\xfd\xea\x134\x13f\x13\x13\x02\x16\x90\x13\x05\x11\x02*\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00%\x005\x00\x00\t\x0164'\x01&\a\x06\x1d\x01\"\x0e\x05\x15\x14\x17\x163276'\x027>\x013\x15\x14\x17\x1632\x01\x11\x14\x06#!\"&5\x11463!2\x16\x03\xed\x01`\x13\x13\xfe\xa0\x1e'(w\u0083a8!\n\xa7\v\x0e\a\x06\x16\x03,j.\xa8\x8c(\f\f\x1a\x02&\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x01\xb3\x01`\x134\x13\x01`\x1f\x11\x11*\xa0'?_`ze<\xb5\xdf\f\x03\t\x18\x01bw4/\xa0*\x11\x05\x02\xc0\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x04\x00\x00\xff\x80\x06\x00\x05\x80\x00\x02\x00\x06\x00\x12\x00\x1e\x00\x00\x01-\x01\x01\x11\x01\x11\x00\x10.\x01 \x0e\x01\x10\x1e\x01 6\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x02\x80\x01\x00\xff\x00\x01\x80\xfe\x00\x03 \x92\xfa\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\x01r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01\xc0\x80\x80\x01O\xfd\xe2\xff\x00\x02\x1e\xfe\xdd\x01(\xfa\x92\x92\xfa\xfe\xd8\xfa\x92\x92\x02_\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\r\x00\x1d\x00-\x00\x00\x01\x16\a\x01\x06\"'\x01&763!2\x13\x114&#!\"\x06\x15\x11\x14\x163!26\x01\x11\x14\x06#!\"&5\x11463!2\x16\x04y\x12\x17\xfe\xc0\x13B\x13\xfe\xc0\x17\x12\x11(\x02\x80(\x98\x13\r\xfc@\r\x13\x13\r\x03\xc0\r\x13\x01\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x03]#\x1f\xfe@\x1b\x1b\x01\xc0\x1f##\xfd \x03\xc0\r\x13\x13\r\xfc@\r\x13\x13\x03\xcd\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\r\x00\x1d\x00-\x00\x00\x01\x06#!\"'&7\x0162\x17\x01\x16\x13\x114&#!\"\x06\x15\x11\x14\x163!26\x01\x11\x14\x06#!\"&5\x11463!2\x16\x04y\x11(\xfd\x80(\x11\x12\x17\x01@\x13B\x13\x01@\x17u\x13\r\xfc@\r\x13\x13\r\x03\xc0\r\x13\x01\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x01\xa3###\x1f\x01\xc0\x1b\x1b\xfe@\x1f\xfe\xda\x03\xc0\r\x13\x13\r\xfc@\r\x13\x13\x03\xcd\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\r\x00\x1d\x00-\x00\x00\x00\x14\a\x01\x06'&5\x11476\x17\x01\x13\x114&#!\"\x06\x15\x11\x14\x163!26\x01\x11\x14\x06#!\"&5\x11463!2\x16\x04@\x1b\xfe@\x1f####\x1f\x01\xc0\xdb\x12\x0e\xfc@\x0e\x12\x12\x0e\x03\xc0\x0e\x12\x01\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x02\xa1B\x13\xfe\xc0\x17\x12\x11(\x02\x80(\x11\x12\x17\xfe\xc0\xfd\xec\x03\xc0\x0e\x12\x12\x0e\xfc@\x0e\x12\x12\x03\xce\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x01\x00\x00\x00\x00\x03\xf3\x05\x80\x00`\x00\x00%\x17\x16\x06\x0f\x01\x0e\a#\"\x00'#\"&=\x0146;\x01&7#\"&=\x0146;\x016\x0032\x17\x16\x17\x16\x0f\x01\x0e\x01/\x01.\x05#\"\x06\a!2\x17\x16\x0f\x01\x06#!\x06\x17!2\x17\x16\x0f\x01\x0e\x01#!\x1e\x0132>\x04?\x016\x17\x16\x03\xd0#\x03\f\v\x05\x04\r\x13\x18\x1b!\"'\x13\xea\xfe\xa2?_\r\x13\x13\rB\x02\x03C\x0e\x12\x12\x0ebC\x01a\xe0f\\\v\t\x06\x03+\x03\x16\r\x04\x04\x0f\x14\x19\x1b\x1f\x0e~\xc82\x01\xd4\x10\t\n\x03\x18\x05\x1b\xfe\x18\x03\x03\x01\xcb\x0f\n\t\x03\x18\x02\x12\v\xfe}0\xcb\u007f\x12$\x1f\x1c\x15\x10\x04\x05\r\r\f\xe5\x9f\f\x15\x04\x01\x02\x03\x06\x05\x05\x05\x04\x02\x01\x05\xdd\x13\rq\r\x1390\x12\x0er\x0e\x12\xd2\x01\x00\x17\x03\f\v\r\x9f\r\r\x04\x01\x01\x03\x04\x03\x03\x02\x80p\f\f\x0er\x1a%D\f\f\x0fp\v\x0fu\x89\x03\x04\x05\x05\x04\x01\x02\x05\a\a\x00\x00\x01\x00\x00\x00\x00\x03\xfc\x05\x80\x00?\x00\x00\x01\x11\x14\x06#!\"&=\x0146;\x01\x11#\"&=\x0146;\x0154632\x17\x1e\x01\x0f\x01\x06\a\x06'.\x02#\"\x06\x1d\x01!2\x16\x1d\x01\x14\x06#!\x11!546;\x012\x16\x03\xfc\x12\x0e\xfcD\x0e\x12\x13\ra_\x0e\x12\x12\x0e_\xf7\xbf\xb9\x96\t\x02\bg\t\r\r\n\x05*`-Uh\x011\r\x13\x13\r\xfe\xcf\x01\x9e\x12\x0e\xa2\x0e\x12\x01\x8f\xfe\x91\x0e\x12\x12\x0e\x96\r\x13\x01\u007f\x13\r\x83\x0e\x12߫\xde}\b\x19\n\u007f\v\x01\x02\t\x05\x1c$^L\xd7\x12\x0e\x83\r\x13\xfe\x85\xb5\r\x13\x13\x00\x00\x00\x01\x004\xff\x00\x03\xd2\x06\x00\x00b\x00\x00\x01\x14\x06\a\x15\x14\x06+\x01\"&=\x01.\x04'&?\x01676\x170\x17\x16\x17\x1632654.\x03'.\b5467546;\x012\x16\x1d\x01\x1e\x04\x17\x16\x0f\x01\x06\a\x06'.\x04#\"\x06\x15\x14\x1e\x04\x17\x1e\x06\x03\xd2ǟ\x12\x0e\x87\r\x13B{PD\x19\x05\x11\x0fg\a\x10\x0f\t\x02q\x82%%Q{\x1e%P46'-N/B).\x19\x11ĝ\x13\r\x87\x0e\x129kC<\x12\x06\x11\fQ\b\x0f\x0e\r\x03\x177>W*_x\x11*%K./58`7E%\x1a\x01_\x99\xdd\x1a\xaf\x0e\x12\x13\r\xaf\t,-3\x18\x06\x15\x14\x87\n\x02\x02\v\x02c\x1a\bVO\x1c2\")\x17\x15\x10\x12#\x1b,)9;J)\x8a\xd0\x1e\xb4\r\x13\x12\x0e\xb0\x06\"!*\x10\x06\x12\x14\x92\x0f\x01\x03\n\x03\x12#\x1d\x17VD\x1a,'\x1b#\x13\x12\x14\x17/&>AX\x00\x01\x00\x00\x00\x00\x03\x82\x05\x80\x00>\x00\x00\x01\x15\x14\x06+\x01\x0e\x01\a\x16\x01\x16\a\x06+\x01\"'\x00'&=\x0146;\x01267!\"&=\x01463!&+\x01\"&=\x01463!2\x16\x1d\x01\x14\x06+\x01\x16\x1732\x16\x03\x82\x12\x0e\xa8\x17Ԫ\xa7\x01$\x0e\n\b\x15\xc3\x10\t\xfe\xce\xc0\t\x13\rp\x84\xa1\x16\xfeU\x0e\x12\x12\x0e\x01\x9d9ӑ\r\x13\x12\x0e\x03@\x0e\x12\x12\x0e\xe9/\x11\xab\x0e\x12\x04*f\x0e\x12\x90\xb4\x14\xb2\xfe\x9a\x10\x12\x12\f\x01o\xcc\t\r\u007f\r\x13VR\x12\x0ef\x0e\x12q\x13\r\x85\x0e\x12\x12\x0ef\x0e\x12=S\x12\x00\x01\x00\x04\x00\x00\x03\xff\x05\x80\x00E\x00\x00!#\"&5\x11!\"&=\x01463!5!\"&=\x0146;\x01\x01&76;\x012\x17\x13\x16\x17>\x017\x136;\x012\x17\x16\a\x0132\x16\x1d\x01\x14\x06#!\x15!2\x16\x1d\x01\x14\x06#!\x11\x14\x06\x02[\xac\r\x13\xfe\xe0\r\x13\x13\r\x01 \xfe\xe0\r\x13\x13\r\xd6\xfe\xbf\b\b\n\x12\xc2\x13\n\xd7\x13%\n)\a\xbf\b\x15\xbf\x11\n\t\b\xfe\xc7\xd7\r\x13\x13\r\xfe\xde\x01\"\r\x13\x13\r\xfe\xde\x13\x12\x0e\x01J\x12\x0eg\r\x13U\x12\x0eh\r\x13\x02B\x10\x10\x10\x12\xfeW&W\x18X\x11\x01\xa4\x13\x10\x0e\x11\xfd\xbd\x13\rh\x0e\x12U\x13\rg\x0e\x12\xfe\xb6\r\x13\x00\x02\x00\x00\x00\x00\x05\x00\x05\x80\x00\a\x008\x00\x00\x004&#!\x11!2\x00\x10\x06#!\x15!2\x16\x1d\x01\x14\x06#!\x15\x14\x06+\x01\"&=\x01#\"&=\x0146;\x015#\"&=\x0146;\x01\x11463!2\x04\x13\x82j\xfe\xc0\x01@j\x01o\xfd\xc8\xfe\xac\x01\xf9\x0e\x12\x12\x0e\xfe\a\x13\r\xa7\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\xe0\x0e\x12\x12\x0e\xe0\x12\x0e\x02\x1b\xc8\x03g\xc8|\xfe@\x01\xa1\xfe~\xf4v\x12\x0e\x80\x0e\x12\xc0\x0e\x12\x12\x0e\xc0\x12\x0e\x80\x0e\x12v\x12\x0e\x95\r\x13\x02u\x0e\x12\x00\x06\x00\x00\x00\x00\a\x00\x05\x80\x00\b\x00\f\x00\x10\x00\x19\x00\x1d\x00n\x00\x00\x01\x13#\x13\x16\x14\x1746\x137!\x17!3'#\x01\x13#\x13\x14\x16\x1746\x137!\x17\x05\x15\x14\x06+\x01\x03\x06+\x01\"'\x03#\x03\x06+\x01\"&'\x03#\"&=\x0146;\x01'#\"&=\x0146;\x01\x03&76;\x012\x17\x13!\x136;\x012\x17\x13!\x136;\x012\x17\x16\a\x0332\x16\x1d\x01\x14\x06+\x01\a32\x16\x02\x02Q\x9fK\x01\x01\x01t#\xfe\xdc \x01\xa1\x8b#F\x01\x9fN\xa2Q\x01\x01\x01o!\xfe\xd7\"\x02\x80\x12\x0eդ\a\x18\x9f\x18\a\xa6ѧ\a\x18\x9f\v\x11\x02\xa0\xd0\x0e\x12\x12\x0e\xaf!\x8e\x0e\x12\x12\x0emY\x05\n\n\x10\x89\x1a\x05Z\x01ga\a\x18~\x18\ab\x01m]\x05\x1a\x89\x10\n\n\x05[o\x0e\x12\x12\x0e\x91\"\xb3\x0e\x12\x01U\x01+\xfe\xd4\x01\x04\x01\x01\x05\x01\xac\x80\x80\x80\xfd\xd4\x01,\xfe\xd5\x01\x05\x01\x01\x04\x01\xad\x80\x80 @\x0e\x12\xfd\x98\x18\x18\x02h\xfd\x98\x18\x0e\n\x02h\x12\x0e@\x0e\x12\x80\x12\x0e@\x0e\x12\x01X\x0f\r\f\x18\xfe\x98\x01h\x18\x18\xfe\x98\x01h\x18\f\r\x0f\xfe\xa8\x12\x0e@\x0e\x12\x80\x12\x00\x00\x03\x008\xff\x00\x04\xe8\x05\x80\x003\x00H\x00\\\x00\x00\x01\x16\a\x1e\x01\a\x0e\x04\a\x15#5\"'\x15#\x11\"&+\x017327\x113&#\x11&+\x015\x172753\x156353\x15\x1e\x03\x034.\x04\"\x06#\x112\x162>\x06\x034.\x04\x0e\x01#\x112\x16>\x06\x04\x8f\x12\x95ut\r\a3Nt\u007fR\x9aP*\x9a\x12H\x13\xc8\x1fo2\b\x10\x06\n\rLo\xd4@!\x9aR(\x9aOzh=\xd1\x1e,GID2F\xfd\x9e\n\xfe\xc1\n\r\f\v\xfe\xc0\x0f\b\b\x16\xc0\x12\x0e\xc0\x0e\x12\xc0\x0e\x12\x02\xee\x1a8PuE>.\x18\x12'\x0f\x10%&Te\x10\x02\x15Q,j\x86\x90m{\xa4\x1e\xfe+\xa7\x01\x02\a\b\x12>R\xc0{\xdf?jJrL6V\f\f\xfe\xc1\t\t\x01@\x10\x13\x14\x05`\x0e\x12\x12\x0e\xfa\xa0\x127>wmR1\x10\b\aq\a\x04\ruW\x17\x1c\x8fei\x92\xbd\x02/rr\x01\xb0\a\x18\x05\x10\f\r\x12:V\xb9\xfdr\x00\x00\x00\x00\x04\x00\"\xff\x00\x05\xce\x06\x00\x00\n\x00$\x007\x00V\x00\x00\x014&#\"\x06\x14\x16326\x01\x14\a\x01\x06#\"'\x01&76;\x01\x1146;\x012\x16\x15\x1132\x16\x05\x15!53\x1146=\x01#\a\x06\x0f\x01'73\x11\x13\x14\x0e\x03#\"'&'7\x16\x17\x163267#\x0e\x01#\"&54632\x16\x05BX;4>ID2F\xfd\x9e\n\xfe\xc1\n\r\f\v\xfe\xc0\x0f\b\b\x16\xc0\x12\x0e\xc0\x0e\x12\xc0\x0e\x12\x02\xd0\xfe+\xa7\x01\x02\a\b\x12>R\xc0{\xc3\x1a8PuE>.\x18\x12'\x0f\x10%&Te\x10\x02\x15Q,j\x86\x90m{\xa4\x04\xdf?jJrL6\xfb\xaa\f\f\xfe\xc1\t\t\x01@\x10\x13\x14\x05`\x0e\x12\x12\x0e\xfa\xa0\x12\xfcrr\x01\xb0\a\x18\x05\x10\f\r\x12:V\xb9\xfdr\x053>wmR1\x10\b\aq\a\x04\ruW\x17\x1c\x8fei\x92\xbd\x00\x00\x03\x00\x00\xff\x80\x06@\x05\x80\x00\v\x00\x1b\x00\\\x00\x00%4&#\"\x06\x15\x14\x16326\x13\x11\x14\x06#!\"&5\x11463!2\x16\x05\x14\a\x16\x15\x16\a\x16\a\x06\a\x16\a\x06\a+\x02\".\x01'&'.\x015\x11467>\x01767>\x027>\x027632\x1e\x05\x15\x14\x0e\x01\a\x0e\x02\a!2\x16\x01\x00&\x1a\x1b%%\x1b\x1a&\xa0&\x1a\xfe\xe0\x1a&&\x1a\x01 \x1a&\x04\xa07\x0f\x03.\x11\x11\x0f'\t:@\x85$L\x11B\x9cWM{#\x1a&$\x19\x18h1D!\x12\x1a\t\t\a\v\x1c\x14\x13\x1a.I/!\x0f\t\x01\x13\x13\x12\x03\x0e\b\x04\x01\x15Nr\xc0\x1a&&\x1a\x1b%%\x02\x1b\xfd\x80\x1a&&\x1a\x02\x80\x1a&&\x1aV?, L=8=9%pEL\x02\x1f\x1b\x1a+\x01\x01%\x1a\x02\x81\x19%\x02\x02r@W!\x12<%*',<\x14\x13\x15\x1f2(<\x1e\x18&L,\"\x06\x18\x14\x0er\x00\x00\x00\x00\x03\x00\x00\xff\x00\x06@\x05\x00\x00\v\x00\x1b\x00\\\x00\x00\x01\x14\x06#\"&54632\x16\x13\x114&#!\"\x06\x15\x11\x14\x163!26%\x16\x15\x0e\x01#!\x1e\x02\x17\x1e\x02\x15\x14\x0e\x05#\"'.\x02'.\x02'&'.\x01'.\x015\x1146767>\x02;\x03\x16\x17\x16\a\x16\x17\x16\a\x16\a\x14\x01\x00&\x1a\x1b%%\x1b\x1a&\xa0&\x1a\xfe\xe0\x1a&&\x1a\x01 \x1a&\x04i7\x01qN\xfe\xeb\x04\b\x0e\x03\x12\x12\x14\x01\t\x0f!/I.\x1a\x13\x14\x1c\v\a\t\t\x1a\x12!D1h\x18\x19$&\x1a#{MW\x9cB\x11L$\x85@:\t'\x0f\x11\x11.\x03\x03\xc0\x1a&&\x1a\x1b%%\xfd\xe5\x02\x80\x1a&&\x1a\xfd\x80\x1a&&\xaf=XNr\x0e\x14\x18\x06%(M&\x18\x1e<(2\x1f\x15\x13\x14<,'*%<\x12!W@r\x02\x02%\x19\x02\x81\x1a%\x01\x01+\x1a\x1b\x1f\x02LEp%9=8=L \x00\x00\f\x00\x00\xff\x80\x06\x00\x05\x80\x00\t\x00\x0f\x00\x17\x00+\x00=\x00\\\x00d\x00\u007f\x00\x8c\x00\x9e\x00\xb2\x00\xc2\x00\x00%54#\"\a\x15\x16327354\"\x15%\x15#\x11#\x11#5\x05\x11#5\x06#\"'&5\x113\x11\x14\x17\x16327\x11\x05\x15\x14\a\x06#\"'\x15#\x113\x15632\x17\x16\x17\x15\x14\a\x06\a\x06#\"'&=\x014762\x17\x16\x1d\x01#\x15\x143274645\x01\x15\x14\"=\x0142\x014'.\x01'&! \a\x0e\x01\a\x06\x15\x14\x17\x1e\x01\x17\x16 7>\x0176\x01\x13#\a'#\x1e\x01\x17\x16\x17\x153%54'&#\"\a\x06\x1d\x01\x14\x17\x163276\x173\x11#\x11\x06#\"'&5\x11#\x11\x14\x17\x16327\x01\x11\x14\x06#!\"&5\x11463!2\x16\x03\x97\x1d\x11\x10\x10\x11\x1d\xb8BB\xfd\xc5PJN\x01\xb1C'%!\t\x06B\x01\x01\x0e\x14\x16\x01?\a\f)#!CC $)\f\a\xfb\x02\x03\f\x1b54\x1d\x15\x14\x1df\x1b\x15\x85\"\x18\x06\x01\xfe\x81@@\x02\x15\x13\nB+\x88\xfe\xec\xfe\xed\x88,A\n\x14\x14\nA+\x89\x02&\x89+A\n\x14\xfd\rZK35N\a \b#\vJ\x01!\x15\x1d13\x1b\x15\x15\x1b31\x1d\x15\xb5CC\x16\x14\x0f\x01\x01C\x06\v $)\x01\xf7\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\xe9\x9d2\x10\xe0\x10\xab\"33\xe8F\xfeY\x01\xa7F~\xfe\x91(-\x1c\x11%\x01\"\xfe\xf2\x18\x02\x0f\x1f\x01\x18o\x924\x15*)$\x01\xed\xa1(*\x15\xb6\t\x1d\x0e\x16\x12(&\x1b;\x81;\x1b&&\x1d9LA3\x1a\x01\f\x15\v\x038\x9c33\x9c4\xfd\x03\xb1S,;\x05\x0f\x0f\x05;,W\xad\xb0T+<\x05\x0f\x0f\x05<+T\x03;\x01(\xc3\xc3\x17\\\x17g7\xc9x\x82:\x1d&&\x1d:\x82:\x1d&&\x1b<\x01r\xfe\xe5\x1f\x10\x02\x18\x01\x10\xfe\xdb%\x12\x1b-\x01\b\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\v\x00\x1b\xff\x00\x05\xe5\x06\x00\x00\t\x00\x0f\x00\x17\x00+\x00=\x00[\x00c\x00}\x00\x89\x00\x9b\x00\xaf\x00\x00\x01\x15\x14#\"'\x11632\x05\x15#542%35!\x153\x113!3\x11#\x11\x06#\"'&5\x11#\x11\x14\x17\x16327%54'&#\"\a5#\x1135\x163276%5#\x14\a\x06#\"=\x01354'&#\"\a\x06\x1d\x01\x14\x17\x16327676\x0154\"\x1d\x01\x142\x01\x14\a\x0e\x01\a\x06 '.\x01'&547>\x0176 \x17\x1e\x01\x17\x16\x013\x03\x11#\x11&'&'3\x13\x05\x15\x14\a\x06#\"'&=\x0147632\x17\x16%\x11#5\x06#\"'&5\x113\x11\x14\x17\x16327\x11\x03\xcb'\x17\x16\x16\x17'\x01RZZ\xfc:k\xfe\xc8id\x01 YY\x1e\x1b\x12\x03\x01Y\b\f.06\x01\xad\t\x1162+YY-06\x11\t\x01R[\x02\a!.\xb3\x1b'CD'\x1c\x1d'EH$\x12\x03\x02\xfd\xa0VV\x02\xcf\x1a\x0eX:\xb8\xfd\x1a\xb8:Y\r\x1a\x1a\x0eX;\xb7\x02\xe6\xb8:Y\r\x1a\xfc\x1afyd\x0e/%\x1cjG\x01\xb6\x1c&DC&\x1c\x1c&CD&\x1c\x01O[52.\r\b[\x01\x03\x12\x1b\x1e\x01$\xd3C\x16\x01-\x16D..D\x96^^\xfd\xc7\x01\xee\xfe\x86*\x15\x03 \x01l\xfey1\x18%=^\xc5I\x1a86\xd9\xfdi077\x1bS\r3\n$EWgO%33%O\xadO%35\x1b\x1b\t\x03\xc2\xd2EE\xd2F\xfdW\xeat;P\x06\x15\x15\x06P;p\xee\xeat;P\a\x14\x14\aP;p\x04\x0e\xfeq\xfe\xf1\x01\x0fJ\x8agT\xfe\xf9F\xafQ%33&P\xafP%33%R\xfe\r7>%\x183\x01\x8a\xfe\x91!\x02\x16+\x01}\x00\x00\x02\x00\x05\xff\x80\x05{\x05\xf6\x00\x13\x00'\x00\x00\x01\x06\x03\x06+\x01\"&7\x132'\x03&76;\x012\x17\x01\x16\a\x01\x15\x01\x16\a\x06+\x01\"'\x016\x016;\x012\x02U\n\xf7\x1b&\xef\x15\x14\n\xfd\x01\x01\xa1\f\v\t\x17\xef(\x1a\x03\xca\v\v\xfd\xf0\x01P\v\n\n\x16\xef*\x18\xfe\xad\x12\x02\x01\x19'\xf1\x16\x03e\x12\xfeJ.\"\x13\x01\xc0\x01\x01\x17\x16\x0f\x0f-\x01d\x10\x15\xfcZ\x01\xfd\x99\x14\x11\x0f-\x02n \x03\x8e-\x00\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x13\x00'\x007\x00\x00\x014'&+\x01\"\a\x06\x1f\x01\x15\x03\x06\x17\x16;\x0127\x01&+\x01\"\a\x01\x16\x01\x16;\x01276'\x015\x016\x17\x11\x14\x06#!\"&5\x11463!2\x16\x02\xad~\x15\x1f\xb8\x12\b\a\b}\xc4\t\t\b\x10\xb9\x1f\x13\x037\a\x11\xbb\x1e\x13\xfee\x01\x01\x05\x14 \xb8\x12\a\b\t\xfe\xfc\x01\x99\b۩w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x03\x03\x01\xdd\"\v\f\x11\xd8\x01\xfe\xa6\x0e\x0e\r$\x03Q\f#\xfd'\x02\xfe!#\f\r\x0f\x01\xdc\x01\x02\xd3\x10\x88\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x00\x02\x00\x00\x00\n\a\x00\x04\xf6\x00\x02\x00I\x00\x00\x01-\x01\x132\x04\x1f\x012\x1e\x05\x17\x1e\x02\x17\x1e\x01\x17\x1d\x01\x16\a\x0e\x01\x0f\x01\x0e\x06#\x06!&$/\x02.\x02'.\x02'.\x01'=\x01&7>\x01?\x01>\x0636\x02\xc7\x01\xe4\xfe\x1c\xb9\xa8\x019II\x01 \x0e!\x18 \x1e\x0e\x06\x13'\a\b\t\x01\x01\x13\a$\x0e\x0e\x0e\x1e \x18!\x0f\x1f\x01\xfb\xfe\x88\xcf\xfe\xcf01$$%A\x18\x06\x13'\a\b\t\x01\x01\x13\a$\x0e\x0e\x0e\x1e \x18!\x0e \x01\xfb\x01\x98\xfa\xfd\x01g\t\x05\x04\x03\x03\x06\n\x10\x17\x0f\x06\x19\\7@\x91)(\x88\x91\x917Y\x11\x11\x0f\x17\x0f\n\x06\x03\x03\x13\x02\t\x03\x04\x04\x05\n \x19\x06\x19\\7@\x91)(\x88\x91\x917Y\x11\x11\x0f\x17\x10\n\x06\x03\x03\x12\x00\x00\x05\x00@\xff\x80\x06\xc0\x05\x8a\x00\x03\x00\x13\x00\x17\x00\x1b\x00\x1f\x00\x00\t\x04\x15\x01\x15'\a5\x015\x17\x015\x177\x15\t\f\x01\x92\x01\xee\xfe\xaa\xfe\x16\x05,\xfe\x16\x01\x01\xfe\x17\x93\x01V\x01\x01\x01W\xfdQ\x01V\xfe\x12\xfe\xae\x05.\x01R\xfe\x17\xfe\xa9\x01W\x01\xe9\xfe\xae\xfe\x12\x03=\xfe\xcf\xfe\xe3\x01?\xfe\xe4l\xfe\xdb\x01\x01\x01\x01\x01%l`\x01\x1c\x02\x01\x01\x02\xfe\xe4\x04\xd8\xfe\xe3\xfe\xd0\x01\x0e\xfe\xf2\xfe\xf1\xfe\xc1\x01\x1d\x03~\xfe\xc1\xfe\xf2\x010\x00\x06\x00\v\xff\x00\x05\xf5\x06\x00\x00\a\x00\v\x00\x0f\x00\x13\x00\x17\x00\x1b\x00\x00\x05!\x11#\x11!\x11#%7\x05\a\x017\x01\a\x017\x01\a\x03\x01\a\t\x015!\x15\x05\t\xfb\xa2\xa0\x05\x9e\xa0\xfcR!\x03\x0f!\xfdXC\x02\xd5C\xfd\xf4f\x02ff\xd9\x01݀\xfe#\xfd\xb2\x03 `\x01\xe0\xfd\x80\x02\x80,\x9d\xa5\x9c\x02\x1a\x92\xfe\xad\x91\x02\xb6{\xfd\xff{\x03{\xfd\u007f`\x02\x81\xfa\xa1\x9f\x9f\x00\x00\x00\x05\x00\x00\xff\x80\x06\x00\x05\x80\x00\a\x00\x0f\x00\x17\x00O\x00g\x00\x00\x004&\"\x06\x14\x162\x00\x10\x06 &\x106 $\x14\x06\"&462$\"&\x0e\x02\a\x0e\x01\a\x0e\x03\x16\x14\x06\x1e\x02\x17\x1e\x01\x17\x1e\x0362\x16>\x027>\x017>\x03&46.\x02'.\x01'.\x03\x00\x10\a\x0e\x01\a\x06 '.\x01'&\x107>\x0176 \x17\x1e\x01\x17\x04\x00\x96Ԗ\x96\xd4\x01 \xe6\xfe\xb8\xe6\xe6\x01H\x01R6L66L\xfeG\x0e\x8bHyU\x1d2L\x14\v\x0f\x05\x01\x01\x01\x01\x05\x0f\v\x14L2\x1dUyH\x8b\x0e\x8bHyU\x1d2L\x14\v\x0f\x05\x01\x01\x01\x01\x05\x0f\v\x14L2\x1dUyH\x02n\x05\n\xe4\xd0X\xfe6X\xd0\xe4\n\x05\x05\n\xe4\xd0X\x01\xcaX\xd0\xe4\n\x02\x16Ԗ\x96Ԗ\x01\xa4\xfe\xb8\xe6\xe6\x01H\xe66L66L6\x80\x01\x01\x05\x0f\v\x14L2\x1dUyH\x8b\x0e\x8bHyU\x1d2L\x14\v\x0f\x05\x01\x01\x01\x01\x05\x0f\v\x14L2\x1dUyH\x8b\x0e\x8bHyU\x1d2L\x14\v\x0f\x05\x01\xfen\xfe6X\xd0\xe4\n\x05\x05\n\xe4\xd0X\x01\xcaX\xd0\xe4\n\x05\x05\n\xe4\xd0\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x17\x00\x1f\x00\x00\x012\x16\x15\x11\x14\x06#!\"&5\x11463\x004&\"\x06\x14\x162$4&\"\x06\x14\x162\x04\xe0w\xa9\xa9w\xfc@w\xa9\xa9w\x01\x9a|\xb0||\xb0\x02\xb0|\xb0||\xb0\x05\x80\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\xfc\xa8\xb0||\xb0||\xb0||\xb0|\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x02\x00\t\x00\x15\x00\x00\x01\x13!\x053\t\x0137!\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x03\x00\xc9\xfen\x026^\xfe5\xfe5^h\x02\n\x01\xfb\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x03\x92\xfe\xce\xe0\x02\xb3\xfdM\xa0\x011\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x05\x00\x00\xffP\x05\x81\x05\xa3\x00\n\x00\x16\x00*\x00C\x00g\x00\x00\x01\x16\x06'.\x01676\x1e\x01\x17.\x01\a\x0e\x01\x17\x1e\x017>\x01\x13.\x02'$\x05\x0e\x02\a\x1e\x02\x17\x167>\x02\x13\x0e\x03\a\x0e\x01&'.\x03'&'?\x01\x16 7\x1e\x01\x06\x13\x06\x03\x0e\x02\a\x06%&'.\x04'.\x03'>\x04767$\x05\x16\x17\x1e\x01\x03/\bu5'\x1d\x1c&$I7o\x0e\xc6b?K\x03\x04\x93\\[z\xe4\x14H,1\xfe\xdd\xfe\xed+.@\x12\x1e\\7<\xe4\xdc?5\\V\b\x0f\r,$V\xcf\xc5g.GR@\x14\x19 \x06\x12\xdf\x027\xe0\x15\x06\x10\xb5\x1aU\x05,+!\xfc\xfe\x9a\xf8\x92\x0f\x15\r\x05\a\x02\t#\x15\x1a\t\x03\x1d\"8$\x1e}\xbc\x01{\x01)\x9b<\x10\x01\x02\xa5?L \x11RR\x11\x12\f;\x11kr,\x1cyE[\x80\b\b\x98\x02z\x1b#\t\b/1\a\n\"\x1a\x1c#\t\a\x1d\x1c\b\b#\xfc\x12\x1aeCI\x140/\x03\x11\b\x14\"5#`\xc4\x10\t\x94\x94\x06\"8\x03\xb8\xa7\xfe\x18\x1e4\x1c\x11~&\x1bp\f\x1d)\x1b4\t2\xc8{\xacH\x1a-\x1e\x1e\x0f\v.\x12%W.L\x14>\x00\x06\x00\x00\xff\x80\x06\x00\x05\x80\x00\b\x00\x13\x00'\x00:\x00Y\x00i\x00\x00\x014&\a\x06\x16\x17\x1667\x16\x0e\x01&'&676\x16\x13\x0e\x02\a\x06'.\x02'>\x0276\x17\x1e\x02\x1346&'\x06 '\x0f\x01\x16\x17\x16\x17\x167>\x02\x136'&'&\x05\x06\a\x0e\x02\a\x1e\x02\x17\x1e\x03\x17\x16\x17\x047>\x027\x12\x01\x11\x14\x06#!\"&5\x11463!2\x16\x03PR$+\x01+'TJ\bX\x84j\x03\x027-F\x8f\xb6\x14C',\x9b\xa9,&C\x15\r.\"\x1e\xc6\xd2!$28\v\x05\x0f\xa1\xfeh\xa2\f\x05\x1a\x0f/\x9d\xf9\xb3\"\x1e\x0f\x87\t\x11+p\xd8\xfe\xf1\x84^&+3\x04\b\x16$\x06\x01\b\x06\x12\ri\xb3\x01\x03\xb5\x18\x1f\x1f\x040\x01(\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x02\x9a+.\x16\x14i\x12\x176=Bn\f\\C1X\x14\x1fR\x01:\x15\x1a\x06\x05\x14\x14\x06\a\x19\x14\x13\x18\a\x05#\"\x05\a\x19\xfd\x03\a'\x19\x04jj\x06\f\x9a8Q\x1b.c\x13Aj\x02\xc75\x167!?\x1b\f\"\x0f\x140\x1eD\x8c\xca$\x054\x14\"\vP\x14\x1c[\r\x14&\x15\x01\v\x012\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x00\x01\x00D\xff\x80\x04\x00\x06\x00\x00\"\x00\x00%\x17\x0e\x01\a\x06.\x035\x11#5>\x047>\x01;\x01\x11!\x15!\x11\x14\x1e\x0276\x03\xb0P\x17\xb0Yh\xadpN!\xa8HrD0\x14\x05\x01\a\x04\xf4\x01M\xfe\xb2\r C0N\xcf\xed#>\x01\x028\\xx:\x02 \xd7\x1aW]oW-\x05\a\xfeX\xfc\xfd\xfa\x1e45\x1e\x01\x02\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x1f\x00/\x00\x00%'\x06#\x06.\x025\x11!5!\x11#\"\a\x0e\x03\a\x153\x11\x14\x1e\x027>\x01\x01\x11\x14\x06#!\"&5\x11463!2\x16\x04p>,;$4\x19\n\x01\x01\xff\x00\xbc\b\x01\x05\x195eD\x82+W\x9bcE\x87\x01\xa2\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9K\xb7\x16\x01\x17()\x17\x01\x8e\xc2\x01F\n,VhV\x19\xa5\xfe^9tjA\x02\x010\x04/\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x01\x00\x03\xff@\x02\xfd\x06\x00\x00\x17\x00\x00\x00\x16\a\x01\x06#\"'\x01&76;\x01\x1146;\x012\x16\x15\x113\x02\xf5\x10\r\xfe\xa2\n\r\x0e\n\xfe\x9d\r\b\t\x14\xe0\x12\x0e\xc0\x0e\x12\xe0\x01\x00&\x10\xfe\x80\n\n\x01\x80\x10\x13\x13\x04\xe0\x0e\x12\x12\x0e\xfb \x00\x00\x00\x01\x00\x03\xff\x00\x02\xfd\x05\xc0\x00\x17\x00\x00\x01\x06+\x01\x11\x14\x06+\x01\"&5\x11#\"&7\x01632\x17\x01\x16\x02\xfd\t\x14\xe0\x12\x0e\xc0\x0e\x12\xe0\x15\x10\r\x01^\n\r\x0e\n\x01c\r\x04\x13\x13\xfb \x0e\x12\x12\x0e\x04\xe0&\x10\x01\x80\n\n\xfe\x80\x10\x00\x00\x00\x00\x01\x00@\x01\x03\a\x00\x03\xfd\x00\x17\x00\x00\x01\x15\x14\x06#!\x15\x14\x06'\x01&547\x016\x17\x16\x1d\x01!2\x16\a\x00\x12\x0e\xfb &\x10\xfe\x80\n\n\x01\x80\x10\x13\x13\x04\xe0\x0e\x12\x02\xe0\xc0\x0e\x12\xe0\x15\x10\r\x01^\n\r\x0e\n\x01b\x0e\b\t\x14\xe0\x12\x00\x00\x00\x01\x00\x00\x01\x03\x06\xc0\x03\xfd\x00\x17\x00\x00\x01\x14\a\x01\x06'&=\x01!\"&=\x01463!546\x17\x01\x16\x06\xc0\n\xfe\x80\x10\x13\x13\xfb \x0e\x12\x12\x0e\x04\xe0&\x10\x01\x80\n\x02\x83\x0e\n\xfe\x9e\x0e\b\t\x14\xe0\x12\x0e\xc0\x0e\x12\xe0\x15\x10\r\xfe\xa2\n\x00\x00\x00\x02\x00\x00\xff\x80\x05q\x06\x00\x00&\x008\x00\x00\x01\x06\a\x06#\"'&#\"\a\x06#\"\x03\x02547632\x17\x16327632\x17\x16\x17\x06\a\x06\x15\x14\x16\x01\x14\a\x06\a\x06\a\x06\a6767\x1e\x01\x17\x14\x16\x05q'T\x81\x801[VA=QQ3\x98\x95\x93qq\xabHih\"-bfGw^44O#A\x8a\xfe\xe1\x1d\x1e?66%C\x03KJ\xb0\x01\x03\x01\x01\x01A}}\xc4 !\"\x01\x03\x01\x05\xf2䒐\x1e\x1e\"\"A$@C3^q|\xc6\x04z=KK?6\x12\v\x06\x95lk)\x03\x10\x03\x04\f\x00\x00\x04\x00\x00\xff\x00\x06\x80\x05\x80\x00\x03\x00\a\x00\v\x00\x0f\x00\x00\x01\x11%\x11\x01\x11!\x11\x01\x11%\x11\x01\x11!\x11\x02\xaa\xfdV\x02\xaa\xfdV\x06\x80\xfcu\x03\x8b\xfcu\x02\x12\xfdu^\x02-\x02\xe7\xfdm\x025\xfdw\xfc\xee}\x02\x95\x03n\xfc\xe6\x02\x9d\x00\x00\x00\x06\x00\x00\xff\x00\x05\x80\x05~\x00\a\x00\x0f\x00\x1c\x007\x00M\x00[\x00\x00\x00264&\"\x06\x14\x04264&\"\x06\x14\x052\x16\x15\x11\x14\x06\"&5\x1146\x05\x11\x14\x06+\x01\x15\x14\x06\"&=\x01#\x15\x14\x06#\"&5'#\"&5\x11\x01\x1e\x01\x15!467'&76\x1f\x0162\x1776\x17\x16\a\x01\x11\x14\x06#\"&5\x114632\x16\x01\xdd \x17\x17 \x16\x01\xbc \x16\x16 \x17\xfc\xfb*<;V<<\x04O@-K\x03<\x01&\x014'>\x03&4.\x02'.\x01'\x16\x17\x16\a\x06\a\x06.\x01'.\x04'.\x03'&6&'.\x01'.\x01676\x16\a\x06\x167645.\x03'\x06\x17\x14#.\x01\x06'6&'&\x06\a\x06\x1e\x017676\a\"&'&6\x172\x16\x06\a\x06\a\x0e\x01\a\x0e\x01\x17\x1e\x03\x17\x167>\x0376\x17\x1e\x01\x06\a\x0e\x01\a\x06\a\x06'&\x17\x16\x17\x167>\x05\x16\x17\x14\x0e\x05\a\x0e\x02'&'&\a\x06\x15\x14\x0e\x02\x17\x0e\x01\a\x06\x16\a\x06'&'&76\a\x06\a\x06\x17\x1e\x01\x17\x1e\x01\x17\x1e\x01\x06\a\x1e\x02\x156'.\x027>\x01\x17\x167676\x17\x16\a\x06\a\x06\x16\x17>\x0176&6763>\x01\x16\x016&'&\x15\x16\x172\a\x0632\x05.\x02'.\x04\a\x06\x16\x17\x166'4.\x01\a\"\x06\x16\x17\x16\x17\x147674.\x01'&#\x0e\x01\x16\a\x0e\x02\x17\x16>\x017626\x01\x1e\x02\x0e\x05\a\x0e\x01\a\x0e\x01'.\x03'&#\"\x06\a\x0e\x03'.\x01'.\x04'&676.\x0167>\x017>\x015\x16\a\x06'&\a\x06\x17\x1e\x03\a\x14\x06\x17\x16\x17\x1e\x01\x17\x1e\x027>\x02.\x01'&'&\a\x06'&7>\x027>\x03767&'&67636\x16\x17\x1e\x01\a\x06\x17\x16\x17\x1e\x01\x17\x16\x0e\x01\a\x0e\x03'.\x04'&\x0e\x01\x17\x16\a\x06\x1667>\x017>\x01.\x01'.\x0167\x1e\x05\x02\x97\v\t\x04\x05\x13\x05\\\x04\x0f\n\x18\b\x03\xfe\x9b\x04\x04\x05\x03\x03\a\n\t\x04\x11\x04\x01\x02\x02\x01\x02\x03U7\x04\a\x03\x03\x02\a\x01\t\x01\nJ#\x18!W!\v'\x1f\x0f\x01\v\t\x15\x12\r\r\x01\x0e\"\x19\x16\x04\x04\x14\v'\x0f;\x06\b\x06\x16\x19%\x1c\n\v\x12\x15\r\x05\x11\x19\x16\x10k\x12\x01\t)\x19\x03\x01\"\x1c\x1b\x1d\x02\x01\t\x11\a\n\x06\x04\v\a\x11\x01\x01\x14\x18\x11\x14\x01\x01\x16\t\b'\x01\r\x05\n\x0e\x16\n\x1b\x16/7\x02*\x1b \x05\t\v\x05\x03\t\f\x14I\t,\x1a\x196\n\x01\x01\x10\x19*\x11&\"!\x1b\x16\r\x02\x02\x06\x06\v\a\r\x03\x1cO6\x16\x15*\x16\x03\x01\x1e\x1d\r\x12\x17O\b\x02\x01\x06\b\x15 \x04\x02\x06\x04\x05\x02\x02$.\x05(\x04\x14\xa8\t\x10\x03\x1f\x1e\b*\x0e.'\x04\r\x06\x01\x03\x14\n.x\x85,\x17\v\f\x02\x01\x16\t\x06\x15\x03\x17\x02\x02\x11\x02\x16\x0f$\x01CN\xfd\xa1\x03\v\x06\t\x02\x03\n\x03\x03\v\x03\x01\xa3\x02\t\x11\x06\x05\t\x05\x06\x02\x03\x0e*\x12\t\v\xb4\n\f\x03\x06\x04\x04\x03\x0e\x04\b\x026\x05\r\x03\x0f\t\t\x05\x03\x02\x01\n\x02\x04\x04\b\x0e\b\x01\x10\x0e\x027\x14\x16\x02\a\x18\x17%\x1a&\b&_\x1c\x11f&\x12\x17\n\"\x1e,V\x13L\x14,G$3\x1c\x1d\xa4@\x13@$+\x18\x05\n\"\x01\x01\n\n\x01\n\x0eV\x11\x1e\x18\x155 3\"\t\r\x12\x02\f\x05\x04\x01\"\x03\x03\"\x14\x81#\x18dA\x17++\x03\x12\x14\ny0D-\v\x04\x03\x01\x01\x12\x1e\a\b%\x16&\x14n\x0e\f\x04\x024P'A5j$9E\x05\x05#\"c7Y\x0f\b\x06\x12\v\n\x1b\x1b6\"\x12\x1b\x12\t\x0e\x02\x16&\x12\x10\x14\x13\n8Z(;=I50\v' !!\x03\x0e\x01\x0e\x0f\x1a\x10\x1b\x04e\x01\x13\x01\x06\f\x03\x0e\x01\x0f\x03\v\r\x06\xfeR\x01\b\x11\x05\x05\b\v\x01\x01\x10\n\x03\b\x04\x05\x03\x03\x02\xfe\x9a\x12\x18\x0f\x19\x1b\x10\x1d\n\"\a+\x050n\x14\x14?\xa2t(\x02\x04-z.'<\x1f\x12\f\x01>R\x1e$\x16\x15A\"\b\x03\x1e\x01\x0124\x01\x03B\x19\x13\x0f\a\x04@\x05\x1e(\x15\t\x03\b~\x0f\t\x03\x04\a9B\x01\x019\x1f\x0f,\x1f\x02\x03\v\t\x01\x1d\x13\x16\x1e\x01*$\x04\x0f\x0e\f\x17\x01\x0e\x1a\x05\b\x17\x0f\v\x01\x02\x11\x01\f\t\x11\t\x0e\x06\x03\v\r\x03\x06\x1f\x04\x13\x04\x05\a\x02\x04\x04\x0f\x17\x01\x01\f\x10\x13\x0f\t\x04\t\x02\x05\x05\x04\x06\x03\a\x01\x0e<\x1a\f\v>\x1f\t\x03\a\x19?0D\x1d\x06\xa89\x12f\b\x18\x15\x1f?\x1c\x1c\x13\x01\x01\x04Ae\f \x04\x17\x87\t\x0f.(\x03\x0f;1.\x18D\b\x10\b\x02\x05\t\a4\x10\x0fH&\b\x06.\x19C\x17\x1d\x01\x13t \x15iY\x1a\x12% \v\x03*\x11\x1a\x02\x02\t\x05\x01\x0f\x14\xc2\b\a\x03\x04\x03\n\x06\a\x01\x02\x107\x04\x01\x12\xe0\v\x11\b\x01\x04\x04\x01\x04\x1b\x03\x05\x02\xea\x02\x06\b\x02\x0f\x01\r\r\x06\x04\r\x05\x06\x03\x06\f\x03\x01\x04\xfa\xc8\f\x19\x17\x16\x16\x11\x14\r\x12\x04\x13J\x1b\x10\a\x12\t\x1d\x16\x11\x01\x01\x03\x01\x01\x1c \x19\x01\x01<\r\x04\v\a\f\x11\v\x17W\v\x100%$\t\f\x04\n\x12\"\"I!\x14\x05\x03\r\x0f*\x06\x18\f\x16\v\x0fD\x0e\x11\t\x06\x19\b\x06 \x0e\x03\x06,4A'\x11\xbe4J\"\t\x18\x10\x16\x1d.0\x12\x15f6D\x14\x8f4p\xc6Z{+\x15\x01\x1d\x1b*\x9fD_wqi;\xd0W1G(\x02\x02\"%\x1e\x01\x01\b\x13\f\x1d\x05%\x0eT7F}AG\x05!1#\x19\x12% \x19\v\vJG\f\x1f3\x1e\x1b\v\x0f\x00\b\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0e\x00 \x00'\x00.\x002\x00>\x00V\x00b\x00\x00%&\x03#\a\x0e\x04\a'\x1632\x03&'\x04!\x06\x15\x14\x16\x17>\x03?\x01>\x01'&'\x0e\x01\a \x05&\a\x16\x17>\x01\x01\"\a6\x05&#\"\a\x16\x17>\x04\x13&'\a\x0e\x04\a\x16\x17\x1e\x01\x17>\x012\x1e\x04\x176\x10\x02\x04 $\x02\x10\x12$ \x04\x04\x00*b\x02\x02\x106\x94~\x88#\x0f\xb8\xea\x84=\x15 \xfe\xc9\xfe\x96\x01XP2\x93\x8a{&%\x04\x12gx|\x8a\xc0 \x01.\x03\xdc\xd2\xc7W)o\x94\xfc\xf1\x01\x01\x01\x02O\xb9\xf8LO\x83sEzG<\x0f\xe4\x03\x92\x01\t\x14CK}E\x19\x13\x02\t\x03$MFD<5+\x1e\nz\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a$\xf1\x01\x01\x01\x06\x15MW\x8eM\v\x96\x02\x931>]\a\x0e|\xe1YY\x9b^D\x0e\r\x01\x05\xd6եA\xf2\x97\xef<\x1f\xef\xe6K\xe5\x03m\x01\x01\x91\xa4\x13\xaa\xd4\x1aE6<\x15\xfe\"\xe8\xb2\x01\f\x19@9I\x1c5*\x05\x18\x05\x05\x04\x03\x05\x06\a\x05\x02\xc8\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00>\x00^\x00\x00\x014.\x03/\x01.\x045432\x1e\x0332654.\x01#\"\x0e\x02\x15\x14\x1e\x02\x1f\x01\x16\x17\x16\x15\x14\x06#\".\x03#\"\x06\x15\x14\x1632>\x02\x05\x14\x06#\"'\x06#\"$&\x02547&54632\x17632\x04\x16\x12\x15\x14\a\x16\x04\x95':XM1h\x1e\x1c*\x12\x0f\x90+D($,\x1a/9p\xac`D\x80oC&JV<\x92Z\x16 PA3Q1*2\x1d23\xf4\xa9I\x86oB\x01kែhMI\x8f\xfe\xfb\xbdo\x10PែhMI\x8f\x01\x05\xbdo\x10P\x01\xd92S6,\x18\v\x18\a\a\x10\x10\x1a\x11M\x18!\"\x18@-7Y.\x1f?oI=[<%\x0e$\x16\x0e\x14('3 -- <-\\\x83%Fu\x90\x9f\xe1P\x10o\xbd\x01\x05\x8fIMh\x82\x9f\xe1P\x10o\xbd\xfe\xfb\x8fIMh\x00\x00\x00\x03\x00,\xff\x80\x04\xcb\x06\x00\x00#\x00?\x00D\x00\x00\x0176&#!\"\x06\x15\x11\x147\x01>\x01;\x01267676&#!\"&=\x01463!267\x06\n\x01\a\x0e\x04#!\"\a\x06\x01\x0e\x01'&5\x11463!2\x16\a\x036\x1a\x01\x03\xe8%\x05\x1c\x15\xfd8\x17\x1f\x06\x01#\x17\x1e!\xef\x16\x1e\x03\x18\r\x04\x1f\x15\xfe\xda\x1d&&\x1d\x01Z\x12\"\xe6\x0fM>\x04\x06\x06\x16\x1b2!\xfe\xf1\r\t\b\xfe^\x16I\f7LR\x03x_@\x16\x9e\x04>M\x04N\xc2\x17\"\"\x14\xfb\xb3\a\x06\x01`\x1a\x0f\x1d\x0f\x82=\x15&&\x1d*\x1d%\x1b\xeeI\xfe}\xfe\xc7\x11\x16\x15,\x16\x14\n\t\xfe\x1b\x19\a\t\x16L\x05\x827_jj\xfc\xea\x11\x019\x01\x83\x00\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00\x00%\x114&#!\"\x06\x15\x11\x14\x163!26\x01\x114&#!\"\x06\x15\x11\x14\x163!26\x13\x11\x14\x06#!\"&5\x11463!2\x16\x02\xc0\x12\x0e\xfe \x0e\x12\x12\x0e\x01\xe0\x0e\x12\x02\xa0\x12\x0e\xfe \x0e\x12\x12\x0e\x01\xe0\x0e\x12\xa0&\x1a\xfa\x80\x1a&&\x1a\x05\x80\x1a&\xc0\x04\x00\x0e\x12\x12\x0e\xfc\x00\x0e\x12\x12\x01\x8e\x02\x80\x0e\x12\x12\x0e\xfd\x80\x0e\x12\x12\x03\x0e\xfa\x80\x1a&&\x1a\x05\x80\x1a&&\x00\x00\x00\x00\x02\x00\x00\xff\x00\x05\x00\x05\xe0\x001\x009\x00\x00\x01\x14\x06#\"'\x03#\x15\x13\x16\x15\x14\x06+\x01\x11\x14\x06+\x01\"&5\x11#\"&547\x135#\x03\x06#\"&547\x0163!2\x17\x01\x16\x00\x14\x06\"&462\x05\x008(3\x1d\xe3-\xf7\t&\x1a\xc0B.\xa0.B\xc0\x1a&\t\xf7-\xe3\x1d3(8\x10\x01\x00Ig\x01\x80gI\x01\x00\x10\xfe`\x83\xba\x83\x83\xba\x01\xe0(8+\x01U\x84\xfee\x0f\x12\x1a&\xfe\xf0.BB.\x01\x10&\x1a\x12\x0f\x01\x9b\x84\xfe\xab+8(\x1d\x18\x01\x80kk\xfe\x80\x18\x03`\xba\x83\x83\xba\x83\x00\x02\x00\x00\xff\x00\x04\x00\x05\xe0\x00%\x00-\x00\x00\x01\x11\x14\x06\"&5\x11#\x11\x14\x06\"&5\x11#\x11\x14\x06\"&5\x11#\x11\x14\x06\"&5\x11463!2\x16\x00\x14\x06\"&462\x04\x008P8@B\\B@B\\B@8P8pP\x02\x80Pp\xfe\xe0\x83\xba\x83\x83\xba\x03@\xfe`(88(\x01`\xfcp.BB.\x01\xd0\xfe0.BB.\x03\x90\xfe\xa0(88(\x01\xa0Ppp\x01ͺ\x83\x83\xba\x83\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x15\x00!\x00\x00%\x01>\x01&'&\x0e\x01\a\x06#\"'.\x02\a\x0e\x01\x16\x17$\x10\x02\x04 $\x02\x10\x12$ \x04\x03\x05\x01^\x10\x11\x1d/(V=\x18$<;$\x18=V).\x1d\x11\x10\x04X\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xea\x01\xd9\x16J`\x1f\x1a\x01\"\x1c((\x1c\"\x01\x1a\x1f`J\x16\x8e\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x02\x00,\xff\x00\x06\xd4\x05\xff\x00\x0f\x00I\x00\x00\x004.\x02\"\x0e\x02\x14\x1e\x022>\x01%\x06\a\x05\x11\x14\a\x06'%\a\x06\"/\x01\x05\x06'&5\x11%&'&?\x01'&767%\x11476\x17\x05762\x1f\x01%6\x17\x16\x15\x11\x05\x16\x17\x16\x0f\x01\x17\x16\x05\xc0[\x9b\xd5\xea՛[[\x9b\xd5\xea՛\x01o\x04\x10\xfe\xdc\r\x0f\x0e\xfeܴ\n \n\xb4\xfe\xdc\x0e\x0f\r\xfe\xdc\x10\x04\x05\t\xb4\xb4\t\x05\x04\x10\x01$\r\x0f\x0e\x01$\xb4\t\"\t\xb4\x01$\x0e\x0f\r\x01$\x10\x04\x05\t\xb4\xb4\t\x02\v\xea՛[[\x9b\xd5\xea՛[[\x9b5\x0f\x05`\xfe\xce\x10\n\n\x06^\xf8\r\r\xf8^\x06\n\n\x10\x012`\x05\x0f\x11\f\xf8\xf8\r\x10\x0f\x05`\x012\x10\n\n\x06^\xf8\f\f\xf8^\x06\n\n\x10\xfe\xce`\x05\x0f\x10\r\xf8\xf8\f\x00\x02\x00\x00\xff\x80\x05\xbe\x05\u007f\x00\x12\x001\x00\x00%\x06#\"$\x02547\x06\x02\x15\x14\x1e\x0232$%\x06\x04#\"$&\x0254\x126$76\x17\x16\a\x0e\x01\x15\x14\x1e\x013276\x17\x1e\x01\x04\xee68\xb6\xfeʴh\xc9\xfff\xab킐\x01\x03\x01&^\xfe\x85\xe0\x9c\xfe\xe4\xcezs\xc5\x01\x12\x99,\x11\x12!V[\x92\xfa\x94vn)\x1f\x0e\a\xe9\t\xb4\x016\xb6\xc0\xa5<\xfe\xaeׂ\xed\xabf{\xc3\xcb\xf3z\xce\x01\x1c\x9c\x99\x01\x17\xcc}\x06\x02))\x1fN\xcfs\x94\xfa\x923\x12\x1f\x0e(\x00\x03\x00@\xff\x80\x06\xc0\x05\x80\x00\v\x00\x1b\x00+\x00\x00\x004&#!\"\x06\x14\x163!2\x01\x11\x14\x06#!\"&5\x11463!2\x16\x13\x11\x14\x06#!\"&5\x11463!2\x16\x04@&\x1a\xff\x00\x1a&&\x1a\x01\x00\x1a\x02f&\x1a\xfa\x80\x1a&&\x1a\x05\x80\x1a&@&\x1a\xfa\x00\x1a&&\x1a\x06\x00\x1a&\x02\xa64&&4&\x01\x00\xfc@\x1a&&\x1a\x03\xc0\x1a&&\x01\xa6\xff\x00\x1a&&\x1a\x01\x00\x1a&&\x00\x00\x02\x00 \xff\xa0\x06`\x05\xc0\x00B\x00H\x00\x00\x00\x14\x06+\x01\x14\a\x17\x16\x14\a\x06\"/\x01\x0e\x04#\x11#\x11\".\x02/\x01\a\x06#\"'.\x01?\x01&5#\"&46;\x01\x11'&462\x1f\x01!762\x16\x14\x0f\x01\x1132\x01!46 \x16\x06`&\x1a\xe0C\xd0\x13\x13\x126\x12\xc6\x05\x14@Bb0\x803eI;\x0e\x0f\xb7\x14\x1c\x18\x13\x13\x03\x11\xca:\xe0\x1a&&\x1a\xe0\xad\x13&4\x13\xad\x03L\xad\x134&\x13\xad\xe0\x1a\xfeF\xfd\x80\xbb\x01\n\xbb\x02Z4&\xabw\xd1\x134\x13\x13\x13\xc5\x05\x10) \x1a\x03\x80\xfc\x80\x1b''\r\x0e\xcf\x15\x10\x125\x14\xe3r\xa0&4&\x01&\xad\x134&\x13\xad\xad\x13&4\x13\xad\xfe\xda\x02\x00\x85\xbb\xbb\x00\x00\x01\xff\xff\x00\x01\a}\x04G\x00\x85\x00\x00\x01\x16\a\x06\a\x0e\x02\x1e\x02\x17\x16\x17\x16\x17\x1e\x02\x0e\x01#\x05\x06&/\x01.\x03\a\x0e\x04\x17\x14\x06\x0f\x01\x06\a#\x06.\x02/\x01.\x03\x02'&4?\x0163%\x1e\x01\x1f\x01\x16\x17\x1e\x01\x1f\x01\x1e\x0327>\x04'.\x01/\x01&'&7676\x17\x16\x17\x1e\x03\x14\x0e\x01\x15\x14\x06\x1e\x02\x17\x1e\x01>\x02767>\x01?\x01>\x02\x17%6\x16\x17\a}\x17\xad\x18)(\x1e\x1f\a\x13.\"\x04\x01\x8d2\x03\a\a\b*&\xff\x00\x18@\x14\x14\x1eP9A\x18\x03\n\x18\x13\x0f\x01\a\x04\x04\x12#sG\x96q]\x18\x19\n#lh\x8d<\x06\x03\x04\x0f*\x01\x12\f\x16\x05\x05\x10\b\x144\x0f\x10\x1d6+(\x1c\r\x02\x06\x12\t\n\x05\x02\x0e\a\x06\x19<\r\x12\x10\x165\xbaR5\x14\x1b\x0e\a\x02\x03\x02\x01\x06\x11\x0e\b\x12\"*>%\"/\x1f\t\x02\x04\x1a+[>hy\n\x0f\x03\x03\x01\x03\x03\x01\x02\x05\x0f\t\x00\a\x00\x00\xff\xaa\x06\xf7\x05K\x00\n\x00\x15\x00!\x00/\x00U\x00i\x00\u007f\x00\x00%6&'&\x06\a\x06\x1e\x01676&'&\x06\a\x06\x17\x166\x17\x0e\x01'.\x017>\x01\x17\x1e\x01%.\x01$\a\x06\x04\x17\x1e\x01\x0476$%\x14\x0e\x02\x04 $.\x0154\x1276$\x17\x16\a\x06\x1e\x016?\x0162\x17\x16\a\x0e\x01\x1e\x01\x17\x1e\x02\x02\x1e\x01\a\x0e\x01'.\x0176&\a\x06&'&676%\x1e\x01\a\x0e\x01.\x0176&'.\x01\a\x06.\x01676\x16\x02\xa3\x15\x14#\"N\x15\x16\x12DQt\b\t\r\x0e\x1d\a\x11\x1e\x0e\x1e\xb5-\xe2okQ//\xd1jo_\x01\v\t\xa0\xfe\xff\x92\xdf\xfe\xdb\x0e\t\xa0\x01\x01\x92\xdf\x01%\x01&J\x90\xc1\xfe\xfd\xfe\xe6\xfe\xf4Ղ\x8b\x80\xa9\x01YJA-\x04\x06\x0e\x0f\x06\x06\x8b\xd6.--\x02\x05\x0e\n\f9\\DtT\x19\x13\b+\x17\x17\x16\a\x14X?\x18*\x04\x05\x1a\x18<\x01UW3'\t26\x1a\b\x1c$>>\xacW\x1c0\f\x1f\x1c{\xf2\xfc\"F\x0f\x0e\x1a!\"E \x1b\x9b\r\x1b\x05\x05\v\r\x1f\x0e\x05\v^f`$\"\xb9_]\\\x1b\x1d\xb5<`\x94F\x0e\x17\xed\x92`\x94F\x0e\x17\xed\x8eD\x8f\x83h>Cw\xb7ls\x01\x04\x80\xa9\x86J@\x91\x0e\f\x02\x03\x02\x02;=?s\r\x0e\v\x04\x04\x12:i\x02_^{8\x17\x16\a\b+\x17?`\r\x05\x1a\x18\x18)\x05\rO`\xfds\x1b\x1a\x122\x1bR\xb4DE5\x12\x06\x1f8/\x06\x1aK\x00\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05r\x00\t\x00\x13\x00\x1d\x00\x00\x05\x06#\"'>\x017\x1e\x01\x01\x11\x14\x02\a&\x114\x12$\x01\x10\a&\x025\x11\x16\x04\x12\x04m\xab\xc5ī\x8a\xc3\"#\xc3\xfe\x9b\xfd̵\xa7\x01$\x045\xb5\xcc\xfd\xb3\x01$\xa7\"^^W\xf8\x90\x90\xf8\x05=\xfe\x1b\xfc\xfeac\xd7\x01\x18\xbb\x01E\xd6\xfd*\xfe\xe8\xd7c\x01\x9f\xfc\x01\xe5\x1e\xd6\xfe\xbb\x00\x00\x00\x01\x00\x00\xff\x00\x05z\x06\x00\x00k\x00\x00\x01\x0e\x03.\x03/\x01\x06\x00\a\"&4636$7\x0e\x02.\x03'>\x01\x1e\x02\x1767\x0e\x02.\x05'>\x01\x1e\x05\x1f\x0165.\x0567\x1e\x04\x0e\x02\x0f\x01\x16\x14\a>\x05\x16\x17\x0e\x06&/\x01\x06\a>\x05\x16\x05z X^hc^O<\x10\x11q\xfe\x9f\xd0\x13\x1a\x1a\x13\xad\x01+f$H^XbVS!rȇr?\x195\x1a\a\x16GD_RV@-\x06F\u007fbV=3!\x16\x05\x04\f\b\x1bG84\x0e&3Im<$\x05\x06\x14\x12\b\a\x01\x01\x03\x0e/6X_\x81D\x02'=NUTL;\x11\x11\x172\x06\x18KPwt\x8e\x01\xb1Pt= \x03\x0e\x1e\x19\n\n\xe4\xfe\xf9\x01\x1a&\x19\x01ռ\x0e\x12\b\r,J~S/\x14#NL,\x83\xa0\x01\x03\x02\x03\x11\x1d8JsF\x1c\x11\x13);??1\x0f\x10zI\x06\x14EJpq\x8dD\x19IPZXSF6\x0f\x0f\x04\\\x1a\a\x17?5:\x1f\x02\x17N\u007fR=\x1e\x12\x01\x03\x03\x03\x93\x88\a\x17;.&\x021\x00\x04\x00\x15\xff\x00\x04\xeb\x05\x00\x00\f\x00\x10\x00\x14\x00\x1e\x00\x00\x01\x15\x14\x06+\x01\x01\x11!\"&=\x01\x01\x15!\x11\x01\x15!\x11%\x15!5463!2\x16\x04\xebsQ9\xfe\xfc\xfd\xefQs\x04\xd6\xfb*\x04\xd6\xfb*\x04\xd6\xfb*sQ\x03NQs\x01\x1bBUw\xfe\xf3\x01\rwUB\x01F\xff\x00\xff\x01H\xff\x00\xff\x8cCCTww\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x19\x00%\x001\x00\x00\x00\x14\a\x01\x06#\"&=\x01!\"&=\x01463!54632\x17\x01\x16\x10.\x01 \x0e\x01\x10\x1e\x01 6\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04\x80\t\xfe\xc0\t\x0e\r\x13\xfe\xa0\r\x13\x13\r\x01`\x12\x0e\f\f\x01?\xa9\x92\xfa\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\x01r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02\x8e\x1c\t\xfe\xc0\t\x13\r\xc0\x13\r\xc0\r\x13\xc0\x0e\x12\n\xfe\xc1\xab\x01(\xfa\x92\x92\xfa\xfe\xd8\xfa\x92\x92\x02_\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x19\x00%\x001\x00\x00\x01\x15\x14\x06#!\x15\x14\x06#\"'\x01&47\x01632\x16\x1d\x01!2\x16\x12\x10.\x01 \x0e\x01\x10\x1e\x01 6\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04\x80\x13\r\xfe\xa0\x12\x0e\f\f\xfe\xc1\t\t\x01@\t\x0e\r\x13\x01`\r\x13\xa0\x92\xfa\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\x01r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02\xe0\xc0\r\x13\xc0\x0e\x12\n\x01?\t\x1c\t\x01@\t\x13\r\xc0\x13\xfe\xff\x01(\xfa\x92\x92\xfa\xfe\xd8\xfa\x92\x92\x02_\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00\x00\x01\x11\x14\x06#\"'\x01&47\x01632\x16\x01\x114&#!\"\x06\x15\x11\x14\x163!26\x01\x11\x14\x06#!\"&5\x11463!2\x16\x04\x00&\x1a\x14\x11\xfe@\x1b\x1b\x01\xc0\x11\x14\x1a&\x01\x00\x13\r\xfc@\r\x13\x13\r\x03\xc0\r\x13\x01\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x03\xc0\xfd\x80\x1a&\f\x01@\x13B\x13\x01@\f&\xfc\xc6\x03\xc0\r\x13\x13\r\xfc@\r\x13\x13\x03\xcd\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\a\x00\x13\x00\x1f\x00\x00\x00\x14\x06\"&462\x12 \x0e\x01\x10\x1e\x01 >\x01\x10&\x04\x10\x02\x04 $\x02\x10\x12$ \x04\x04\x00\x96Ԗ\x96\xd4*\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\x92\x92\x01r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02\xeaԖ\x96Ԗ\x01 \x92\xfa\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\xbd\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x00\x02\x00\x00\xff\x00\x06]\x05\xe0\x00\x15\x006\x00\x00\x01\x17\x06\x04#\"$\x0254\x127\x17\x0e\x01\x15\x14\x0032>\x01%\x17\x05\x06#\"'\x03!\"&'\x03&7>\x0132\x16\x15\x14\x06'\x13!\x15!\x17!2\x17\x13\x03\xfff:\xfeл\x9c\xfe\xf7\x9bѪ\x11z\x92\x01\a\xb9~\xd5u\x02\x1b:\xff\x00\r\x10(\x11\xef\xfe(\x18%\x03`\x02\b\x0eV6B^hD%\x01\xa7\xfei\x10\x01\xc7(\x11\xe4\x01]̳ޛ\x01\t\x9c\xb5\x01*>\x836߅\xb9\xfe\xf9\x82\xdd\x1ar\x80\a#\x01\xdd!\x18\x03\v\x11\x193?^BEa\a\xfe߀\x80#\xfe9\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00#\x003\x00\x00\x016'&\x03632\a\x0e\x01#\"'&'&\a\x06\a\x0e\x01\a\x17632\x17\x1e\x01\x17\x1632\x13\x12\x13\x11\x14\x06#!\"&5\x11463!2\x16\x05\f\n\xab\xe7Q,&U\v\x04\x8c#+'\r \x1e\x82;i\x1bl\x1b4L\v92\x0f<\x0fD`\x9d\xe2\xdc\xfa\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x03\x82\xd8\x06\b\xfe\xf3\x13`9ܩ6ɽ\f\a]\x18`\x18C4\xb37\xdb7\xb3\x01&\x01\x1b\x01\u007f\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x01\x00\x00\x00\x00\x04\x80\x05\x80\x00D\x00\x00\x01\x14\x02\x04+\x01\"&5\x11\a\x06#\"'&=\x014?\x015\a\x06#\"'&=\x014?\x01546;\x012\x16\x1d\x01%6\x16\x1d\x01\x14\a\x05\x15%6\x16\x1d\x01\x14\a\x05\x116\x00546;\x012\x16\x04\x80\xbd\xfe\xbc\xbf\xa0\x0e\x12\xd7\x03\x06\n\t\r\x17\xe9\xd7\x03\x06\n\t\r\x17\xe9\x12\x0e\xa0\x0e\x12\x01w\x0f\x1a\x17\xfew\x01w\x0f\x1a\x17\xfew\xbc\x01\x04\x12\x0e\xa0\x0e\x12\x02\xc0\xbf\xfe\xbc\xbd\x12\x0e\x02cB\x01\x06\n\x10\x80\x17\bG]B\x01\x06\n\x10\x80\x17\bG\xfa\x0e\x12\x12\x0e\xb5t\x05\x14\x10\x80\x17\by]t\x05\x14\x10\x80\x17\by\xfe\x19\r\x01\x14\xbe\x0e\x12\x12\x00\x03\x00\x00\x00\x00\x05\x80\x05\x80\x00#\x003\x00C\x00\x00\x01\x15\x14\x06#!\x11\x14\x06+\x01\"&5\x11!\"&=\x01463!\x1146;\x012\x16\x15\x11!2\x16\x13\x114&#!\"\x06\x15\x11\x14\x163!26\x13\x11\x14\x06#!\"&5\x11463!2\x16\x04\x80\x12\x0e\xfe\xa0\x12\x0e@\x0e\x12\xfe\xa0\x0e\x12\x12\x0e\x01`\x12\x0e@\x0e\x12\x01`\x0e\x12\x80^B\xfc\xc0B^^B\x03@B^\x80\xa9w\xfc\xc0w\xa9\xa9w\x03@w\xa9\x02\xe0@\x0e\x12\xfe\xa0\x0e\x12\x12\x0e\x01`\x12\x0e@\x0e\x12\x01`\x0e\x12\x12\x0e\xfe\xa0\x12\xfe2\x03@B^^B\xfc\xc0B^^\x03\x82\xfc\xc0w\xa9\xa9w\x03@w\xa9\xa9\x00\x00\x00\x00\x04\x00\x00\xff\x80\b\x80\x05\x00\x00'\x00/\x00?\x00P\x00\x00\x01\x06+\x015#\"&547.\x01467&546;\x01532\x17!\x1e\x01\x17\x1e\x02\x14\x0e\x01\a\x0e\x01\a7\x16\x14\a\x1764'\x01!\x06\a\"\x06\x0f\x01\x01\x0e\x01+\x01\x0332\x03#\x1332\x16\x17\x01\x1e\x043\x05!&\x02ln\x9e\x80@\r\x13\a:MM:\a\x13\r@\x80\x9en\x04Y*\x81\x10Yz--zY\x10\x81*\x0655QDD\xfbU\x03\xf7\xd9\xef9p\x1b\x1c\xfe\xe0\x1aY-`]\x1d\x9d\x9d\x1d]`.X\x1a\x01 \x04\x0e/2I$\x01\xc8\xfc\tt\x01\xa0@@/!\x18\x19\x02\x11\x18\x11\x02\x19\x18!/@@\a\x16\x03\x0f3,$,3\x0f\x03\x16\a\xfc$p$\x1e0\x940\xfe\xd6&*0\x18\x18\xfe\xe0\x1a&\x01\xd0\x01\xe0\x01\xd0&\x1a\xfe\xe0\x04\r!\x19\x15P@\x00\x02\x00\x00\xff\x80\x06\x80\x06\x00\x00R\x00V\x00\x00\x012\x16\x15\x14\x0f\x01\x17\x16\x15\x14\x06#\"&/\x01\x05\x17\x16\x15\x14\x06#\"&/\x01\a\x06#\"&546?\x01\x03\a\x06#\"&546?\x01'&54632\x16\x1f\x01%'&54632\x16\x1f\x017632\x16\x15\x14\x06\x0f\x01\x1376\x01%\x03\x05\x05\xef>S]\xac8\aT;/M\x0f7\xfe\xca7\bT\x057%>\x01\x04\xe0w\xa9\xa9w\xfc@w\xa9\xa9w\x03\xe0\x1f!\"\xc55bBBb/\xbe/\f*\n8(\x03@(87)\xfc\xc0(8=%/\xb5'\x03\x1c\x0e\x1c\x13\x18\x15\x14\x15\x18\x13\x1c\x0e\x1c\x03\x01\v#?\x05\x80\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\xfb\xe0\x01\xb4#\x14\x16~$EE y \b&\b\xfeL(88\x02e):8(%O\x19 r\x1a\x02\x13\t\x11\t\n\x05\x05\n\t\x11\t\x13\x02\xae\x17O\x00\x00\x00\x00\x06\x00\x00\xff\x00\a\x00\x06\x00\x00\x05\x00?\x00G\x00Q\x00a\x00q\x00\x00\x1347\x01&\x02\x01\x14\x0e\x03\a\x03\x0167>\x01&\x0f\x01&'&\x0e\x01\x1e\x01\x1f\x01\x13\x03\x0167>\x01&\x0f\x01\"$32\x04\x17#\"\x06\x15\x14\x1e\x06\x17\x16\x05\x13\x16\x17\x06#\"'\x01\x16\x15\x14\x02\a\x13654\x00 \x04\x16\x12\x10\x02\x06\x04 $&\x02\x10\x126\x00 $6\x12\x10\x02&$ \x04\x06\x02\x10\x12\x16\u007fC\x01o\xc4\xee\x05\b\x05\x0f\b\x1b\x04L\xfe\xea.*\x13\x0e\x13\x13\xcdK\u007f\f\x11\x06\x03\x0f\fPx\xa8\xfe\xe8.*\x13\x0e\x13\x13\xcd\a \ni\x01SƓ\x01\vi\n7J\x04\x04\f\x06\x12\a\x16\x03?\xfe\x06\xed\x01\x04~\x81pi\x03{_Я\xeb;\xfc\xa2\x01l\x01L\xf0\x8e\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01U\x01Z\x01=刈\xe5\xfe\xc3\xfe\xa6\xfe\xc3刈\xe5\x02\x80\xa3\x96\xfc\x13_\x01t\x01\b\x13'<\x1cZ\r\xff\x00\x03:\x03\x05\x02!\x1d\x01\n\x01\t\x01\f\x12\x13\x0e\x01\b\xfe\xb8\xfe\b\x03@\x03\x05\x02!\x1d\x01\n\x01\xa0\xbbj`Q7\f\x18\x13\x1b\x0f\x1e\f$\x05k\xd3\xfdy\x06\x05, \x04R\xae\xc3\xd1\xfe\x9ff\x02\xa6\xa9k*\x024\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\xf9\xb7\x88\xe5\x01=\x01Z\x01=刈\xe5\xfe\xc3\xfe\xa6\xfe\xc3\xe5\x00\x00\x00\x02\x00\x00\xff\x80\a\x00\x06\x00\x00\x12\x00\x1b\x00\x00\x01\x11\x05&$&546$7\x15\x06\x04\x15\x14\x04\x17\x11\x01\x13%7&'5\x04\x17\x04>\xfe\xf0\xe4\xfe\x8c\xd6\xc9\x01]\xd9\xd9\xfe\xe9\x015\xea\x03\xad%\xfd\xf3\x93w\xa1\x01\x15\xcc\x06\x00\xfa\x00\x80\x14\xa4\xfd\x92\x8c\xf7\xa4\x1a\xac&\xe0\x8f\x98\xe6\x1e\x05P\xfe?\xfezrSF\x1d\xac!|\x00\x00\x00\x03\x00\x00\xff\x00\a\x80\x06\x00\x00\f\x00&\x000\x00\x00\t\x01\x15#\x14\x06#!\"&5#5\x01!\x113\x11!\x113\x11!\x113\x11!\x1132\x16\x1d\x01!546;\x01\x052\x16\x1d\x01!5463\x03\xc0\x03\xc0\x80)\x1c\xfa\n\x1c)\x80\x01\x00\x01\x00\x80\x01\x00\x80\x01\x00\x80\x01\x00;\x1c)\xf9\x80)\x1c;\x06;\x1c)\xf8\x80)\x1c\x06\x00\xfe\x80\x80\x1a&&\x1a\x80\xff\x00\xfd\x00\x03\x00\xfd\x00\x03\x00\xfd\x00\x03\x00\xfd\x00&\x1a@@\x1a&\xc0&\x1a\x80\x80\x1a&\x00\x00\x02\x00\x00\xff\x80\t\x00\x05\x80\x00\r\x006\x00\x00\x01\x13\x16\x06\x04 $&7\x13\x05\x1627\x00\x14\a\x01\x06\"'%\x0e\x01\a\x16\x15\x14\a\x13\x16\a\x06+\x01\"'&7\x13&54767%&47\x0162\x17\x01\x06\xee\x12\x04\xac\xfe\xd6\xfe\xa4\xfe֬\x04\x12\x02>\x164\x16\x04P\x16\xfb\xa0\x04\f\x04\xfdt+8\x06?::\x02\n\t\x0f\xc0\x0f\t\n\x02::A\vW\xfe\xb3\x16\x16\x04`\x04\f\x04\x04`\x02\xbc\xfe\xc4EvEEvE\x01<\xb5\a\a\x02\x10.\b\xfe\xa0\x01\x01\xce\"\x9be$IE&\xfeO\x0e\v\v\v\v\x0e\x01\xb1&EI&\xcf{h\b.\b\x01`\x01\x01\xfe\xa0\x00\x01\x00m\xff\x80\x05\x93\x06\x00\x00\"\x00\x00\x01\x13&#\"\a\x13&\x00\x02'\x16327\x1e\x01\x12\x17>\x037\x163271\x0e\x03\a\x06\x03[\r>+)@\r(\xfe\xff\xb0]:2,C?\x8d\xc1*%\x91Zx/658:\x1c@#N\n\x92\x02C\xfd=\v\v\x02\xc3E\x01\xc5\x01(\x8b\x0f\x0fo\xed\xfe\xc4E=\xe9\x93\xcdW\x0e\x0e'c:\x86\x11\xf8\x00\x00\x01\x00\x00\xff\x80\x05\xe1\x05\x80\x00#\x00\x00\x01!\x16\x15\x14\x02\x04#\"$&\x02\x10\x126$3 \x17\a&#\"\x0e\x01\x10\x1e\x0132>\x037!\x03\x00\x02\xd5\f\xb6\xfe\xafڝ\xfe\xe4\xceyy\xce\x01\x1c\x9d\x01,\xd7\xd1{\xb7\x81ۀ\x80ہW\x92^F!\x06\xfeL\x02\xeeC=\xd9\xfe\xab\xc0y\xce\x01\x1c\x01:\x01\x1c\xcey\xc9\xc9w\x82\xdf\xfe\xf8߂0H\\R%\x00\x00\x05\x00\x00\xff\x00\a\x00\x06\x00\x00\x10\x00\x19\x00\"\x00N\x00^\x00\x00\x01\x16\a\x06 '&762\x17\x1632762$\x14\x06\"&5462\x05\x14\x06\"&462\x1674&\"\a&'\x13\x17\x14\x16264&#\"\a'&\a\x03\x06\a&#\"\x06\x15\x14\x16\x17\x06\x15\x14\x0432$54'>\x01$\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x04G\x10\x10>\xfe\xee>\x10\x10\x06\x12\x060yx1\x06\x12\xfe\xd34J55J\x01\xbf5J44J5\xfbFd$\x82\xb5?\xc84J55%6\x1a\xdd\x13\x06E\xb4\x81#42F%\x1f\x06\x01\x18\xc5\xc6\x01\x18\a\x1e$\x01f\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x01q\x10\x0f>>\x0f\x10\x06\x0611\x06\xd4J44%&4Z%44J54R1F$Z\x06\x01\x1b-%45J521\x05\x15\xfe\xc8\aZ%F1#:\x0f\x1b\x1d\x8e\xcaʎ \x19\x0f9\xbb\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x8e\xf0\x00\x00\x00\x00\x05\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x19\x00#\x00Q\x00a\x00\x00\x01\x16\a\x06\"'&762\x17\x162762%\x14\x06\"&5462\x16\x05\x14\x06\"&5462\x1674&#\"\a&'7\x17\x1e\x013264&#\"\a'&\a\x03\x06\a&#\"\x06\x15\x14\x16\x17\x06\x15\x14\x1632654'>\x01\x01\x11\x14\x06#!\"&5\x11463!2\x16\x03\xab\r\r5\xec5\r\r\x05\x10\x05*\xce*\x05\x10\xfe\xfe.>.-@-\x01R.>.-@-\xd7<+*\x1fq\x9a6\xab\x01-\x1f -- 0\x15\xbd\x11\x04<\x9ao\x1e,+< \x1a\x05\xf0\xa9\xaa\xf0\x06\x19\x1f\x013\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x01\x97\r\r55\r\r\x06\x06**\x06\x96\x1f..\x1f -- \x1f..\x1f --G*<\x1fN\x04\xf3' ,-@-+*\x05\x12\xfe\xf4\x06M <*\x1e2\r\x19\x17z\xad\xadz\x19\x18\r1\x01\xe4\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x1e\x000\x00<\x00\x00\x01754&\"\x06\x15\x11\x14\x06\"&=\x01#\x15\x14\x163265\x114632\x16\x1d\x01\x055#\x15\x14\x06#\"&=\x01\a'\x15\x14\x1626\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x03bZt\xa0t\x1c&\x1b\x97sRQs\x1b\x14\x13\x1b\x01\x89\x96\x1b\x14\x13\x1bZOpoO\xfe\xe5\x14\x1b\x1b\x14xzRrqP\x01\x18\x13\x1c\x1c\x136\xdfz~\x14\x1b\x1c\x13{\x1a\x1c{Prr\x01\xad\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x02\x00\x00\xff\xa3\a\x80\x05]\x00\x1e\x000\x00\x00\x0154&\"\x06\x15\x11\x14\x06#\"&5\x11!\x11\x14\x16265\x114632\x16\x1d\x01\a\x05!\x11\x14\x06#\"&5\x11\x177\x11\x14\x16265\x04&\x02'&\a\x0e\x01#\".\x01'&'\x04#\"&5467%&4>\x037>\x0132\x16\x17632\x16\x15\x14\x06\x0f\x02\x06\x1632654.\x02547'654'632\x1e\x05\x177\x0e\x03\x177.\a'.\x02*\x01#\"\a>\x057\x1e\x02?\x01\x15\x1767>\b?\x01\x06\a\x0e\x01\a\x0e\x02\a\x1e\x01\x15\x14\x03>\x0132\x1e\x03\x17\x06#\"'\x017\x17\a\x01\x16\x15\x14\x0e\x03\a'>\x023\x01\a'>\x0132\x133\x17\a\x015\x15\x0f\x01?\x02\x04\xc6K\x89cgA+![,7*\x14\x15\n\x18\f2\x03(-#\x01=\x05\x11\a\x0e\x06\n\a\t\x04\a\x0f\x1a\x12/\x0e~[\x10(D?\x1dG\b\f \x16\f\x16\xf7|\x1c,)\x19\"\x0e#\v+\b\a\x02)O\xfc\xb4\x0e8,\x11\x03+\xf7'\xb96\t\x1b\x1d\x17\x19\x02y{=@\xfe\xf90mI\x01\xa1\x03#938\x04\a\x15OA\x1c\xfeE`\x06\n-\f\x13\xd3\x1f\n)\x03y\x01\x02\x01\x02\x01\x02_\x03/FwaH8j7=\x1e7?\x10%\x9c\xad\xbc\x95a\x02\x04\x05\t\x05%\a\x1d\f\x1e\x19%\x16!\x1a?)L\x0f\x01\x15\n\x10\x1fJ\x16\r9=\x15\x02\x1a5]~\x99\x14\x04\x1ap\x16\x10\x0f\x17\x03j\x0e\x16\r\n\x04\x05\x02\x01\r \x11%\x16\x11\x0f\x16\x03(\x10\x1a\xb7\xa01$\"\x03\x14\x18\x10\x12\x13,I\x1a \x10\x03\x0e\r$\x1f@\x1c\x19((\x02\v\x0f\xd6\x05\x15\b\x0f\x06\n\x05\x05\x02\x03\x04\x01+\x1e!\x1a.\x1bS\t\t-\x1c\x01\x01L\x01__\x15$'\x17-\x119\x13L\x0f\t5V\xa5\xc6+\x03\t\n\t\x136\a\v\xfcT\x1a+\x1f6.8\x05-\v\x03$\f\xb10\xfe\xd0\x0f\x01\a\x0f\v\b\a\x01+\x02\r\a\x02t\x14\x11\x01\f\xfd|S\f\x061\x01\x01\x05\x02\x03\x04\x01\x00\x00\x04\x00\x00\xff\x12\x06\x00\x05\xee\x00\x17\x006\x00]\x00\x83\x00\x00\x05&\a\x0e\x01#\"'&#\"\a\x0e\x01\x17\x1e\x0167>\x0276'&'&#\"\a\x06\a\x06\x17\x1667>\a32\x1e\x01\x17\x1e\x0176\x014.\x02#\"\x0e\x01#\x06.\x03\a\x0e\x01\a\x06\x17\x1e\x0132>\x02\x17\x1e\x03\x17\x1667>\x017\x14\x02\x06\x04 $&\x0254>\x057>\x037>\x017\x16\x17\x1e\x01\x17\x1e\x06\x04\x8f\x05\x13\x1erJ\x81@\x05\b\v\x0f\a\x01\b\"kb2)W+\a\f,\x13\x14\x175/\x18\x1d1\x1a\x0e\t\x11\x17\x03\x0f\x06\x0e\t\x10\x0e\x13\v\x1b#\v\b\n\x05\n\x17\x01Z\n\x17-\x1e!\x80\x82$\x1bIOXp7s\xa4\x02\x02L\x1dCF9\x96vz \x1aNAG\x14#/ \x1c\x1d5|\xd0\xfe\xeb\xfe\xd0\xfe\xe6Հ';RKR/\x13\x0eJ#=\x1e$,\b\x819,\xac+\x15$UCS7'2\x13\x0e\x16\"1\x04\f\x06\x14\n \x1c\x03\x03\x04!\x1b\a\f\x84/\x0e\x0f\n\f,\x18\x14\b\a\x14\x02\r\x04\n\x04\x06\x03\x02\x0f\x0e\x0f\x11\x06\x04\f\x01/\x16--\x1cST\x01(::(\x01\x01\x9bep4\x14\x11AM@\x01\x01=I>\x01\x03\".)xΤ\xfe\xe7\xbfls\xc7\x01\x1c\xa0Y\xa7|qK@\x1d\n\b%\x14(\x18\x1cYQ\x9b&\x1dN\x1b\r\x18EHv~\xab\x00\x00\x00\x04\x00\x00\xff\x80\x06\x00\x05\x80\x00\x1e\x00<\x00Z\x00x\x00\x00\x01\x0f\x02\x0e\x01'\x0e\x01#\"&5467&6?\x01\x17\a\x06\x14\x17\x162?\x03\x03\x17\a'&\"\x06\x14\x1f\x03\a/\x02.\x017.\x0154632\x16\x176\x16\x01\x14\x06#\"&'\x06&/\x017\x17\x16264/\x037\x1f\x02\x1e\x01\a\x1e\x01\x03\x14\x06\a\x16\x06\x0f\x01'764&\"\x0f\x03'?\x02>\x01\x17>\x0132\x16\x04.\xa0\x97\x1eA\xadU\x10pIUxYE\x16.A\f\x97\v%%%h%\x1e\x97\xa1\xbe\f\x98\f%hJ%\x1d\x98\xa0\x97\xa1\x97\x1eD,\x1bFZxULs\fT\xab\x03gxUJr\x0eV\xbbD\v\x97\f%hJ%\x1e\x98\xa0\x98\xa0\x98\x1d@/\x15Le\x02fL\x1a.C\f\x97\f%Jh%\x1e\x98\xa0\x98\xa1\x98\x1dC\xb8V\vsNUx\x01Ϡ\x98\x1e@.\x15FZyUHp\x10V\xaeA\f\x98\v%h&%%\x1e\x98\xa0\x02\x12\f\x98\f%Ji%\x1d\x98\xa0\x98\xa0\x98\x1eC\xb9W\x0fpIUybJ\x14/\xfb\x95Uy^G\x1c,D\f\x98\f%Jh%\x1e\x98\xa0\x98\xa0\x98\x1e@\xadU\vs\x04\x17Mt\vU\xb7C\f\x98\f%hJ%\x1e\x98\xa0\x98\xa0\x98\x1eC-\x1aKfy\x00\x00\b\x00\x00\xff\x00\x06\x00\x06\x00\x00E\x00X\x00[\x00_\x00g\x00j\x00\x89\x00\xa3\x00\x00\x01\x06&/\x01&'.\x01'\x06\a\x06\a\x0e\x01'67>\x017>\x017&\a\x0e\x02\a\x06\x14\a\x06\a\x06'&'&'>\x0176763>\x017>\x02\x17\x16\a\x14\x0e\x01\a\x06\a\x17\x1e\x01\x17\x1e\x01\x03\x16\a\x06\a\x06#&'&'7\x1e\x0167672\x05\x17'\x01%\x11\x05\x01\x17\x03'\x03\x177\x17\x01\x05\x11\x01\x17\a'\x06\a\x06+\x01\"&'&54632\x1e\x01\x17\x1e\x013267>\x027\x01\x11%\x06\x04#\"'4'\x11676767\x11\x052,\x0132\x15\x11\x02\x8e\x01\x17\x14\x14,+\aD\x04CCQ\x18\x04\x1f\x03\x06L\x15\x81\x0e\x11D\x02\bf\b'\x1e\x02\x02\x01\x05\x1a\x17\x18\x12\n\x04\x01\x06%\v:/d\x02\nB\v\t\x19\x04\x04\x02\x03\x19\x1c\x03\x194@\f}\x05\x04\r\xcf\x03\a\f&\x1e\x1e\x1a\x17\x0e\x04\x01\x03!\x140$\x13\x11\x02\xbe?\x8b\xfb\xf8\x02\xb6\xfdJ\x04\xd9f\xb5d\xd8f-\xd3\xfe.\x02=\xfe\xfa\x9e6(\x82\x92:!TO\xf1?\b\n\b\x04\x1c!\x04I\xadG_\x90U\x0f\x1f%\n\x01\x95\xfc\xfa\x0e\xfd.\a\r\x05\x01\x03\x01\x05\x0fk*\x02.\x02\x01=\x01;\x04\x14\x01\xca\x03\a\b\t\x14\x1d\x055\x02gN_\x0f\x02\x04\x02\x04X\x18\xb6\x1b\x1e\x89\t\x01\"\x02\v\b\x01\x02\x11\x01\n\x05\a\a\x04\x11\x06\x11\x02\x06\x03\x10\x10#\x02#\x04\x03\n\x01\x01\f\x15\x0229\x052Q\x1c\x064\x02\x011\x01\xe0\x0f\r\x17\x0f\f\x03\x17\x0f\x1a\x03\x03\x04\x04\x0e\f\x02\x92\xe3*\xfd\x99\xe8\x04\b\xe9\xfd6\x1f\x02\x91\x1f\xfd\xe8\x1fnA\x03;\xb8\x01|\xfa\x11\r\xa0BS\x19\fN.\a\t\b\v\x0f\x12\x02%1\x1d$\a\x11\x15\x06\x04\x80\xfb\xc9\xf6\x06\xf3\r\x01\x02\x046\t\x01\x06\x05$\x0e\x01\x80\xc6nk\x15\xfe^\x00\f\x00\x00\xff\x00\a\x00\x06\x00\x00\x0f\x00'\x007\x00G\x00W\x00g\x00w\x00\x87\x00\x97\x00\xa7\x00\xb7\x00\xc0\x00\x00\x012\x16\x15\x11\x14\x06+\x01\"&5\x11463\x05\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x1f\x01\x1e\x01\x15\x0154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x0154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x0154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x13\x11#\"&=\x01!\x11\x01 B^^B\x80B^^B\x05\xe0:F\x96j\xfc\xa0B^8(\x02\xa0(`\x1c\x98\x1c(\xfd \x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x01\x00\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x01\x00\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12`\xa0(8\xfd\x80\x04\x80^B\xfb\xc0B^^B\x04@B^\xa3\"vE\xfd\x00j\x96^B\x06\x00(8(\x1c\x98\x1c`(\xfb\x80\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x01\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x01\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\xfe\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x01\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x01\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\xfe\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x01\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x01\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x01\x8e\x01\x008(\xa0\xfe\x00\x00\x14\x00\x00\xff\x00\x05\x80\x06\x00\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00o\x00\u007f\x00\x8f\x00\x9f\x00\xaf\x00\xbf\x00\xcf\x00\xdf\x00\xef\x00\xff\x01\x0f\x01\x1f\x01/\x01?\x00\x00\x012\x16\x15\x11\x14\x06#!\"&5\x11463\x01\x15\x14\x16;\x0126=\x014&+\x01\"\x06\x11\x15\x14\x16;\x0126=\x014&+\x01\"\x06\x11\x15\x14\x16;\x0126=\x014&+\x01\"\x06\x11\x15\x14\x16;\x0126=\x014&+\x01\"\x06\x0354&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x0154&#!\"\x06\x1d\x01\x14\x163!26\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x0154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x05@\x1a&&\x1a\xfb\x00\x1a&&\x1a\x01\xc0\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x80\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x02\x00\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x01\x00\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x06\x00&\x1a\xf9\x80\x1a&&\x1a\x06\x80\x1a&\xfe\xe0@\x0e\x12\x12\x0e@\x0e\x12\x12\xfe\xf2@\x0e\x12\x12\x0e@\x0e\x12\x12\xfe\xf2@\x0e\x12\x12\x0e@\x0e\x12\x12\xfe\xf2@\x0e\x12\x12\x0e@\x0e\x12\x12\xfe\xb2@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\xfb\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x02\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\xfc\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x00\x00\x00\x02\x00@\xff\x10\x04\xc0\x05`\x00\x1f\x00'\x00\x00\t\x01\x11\x14\x06\"&5\x11#\x11\x14\x06\"&5\x11\x01&4762\x1f\x01!762\x17\x16\x14$\x14\x06\"&462\x04\xa4\xfe\xdcB\\B@B\\B\xfe\xdc\x1c\x1c\x1dO\x1c\xe4\x01p\xe4\x1cP\x1c\x1c\xfe\xa0\x83\xba\x83\x83\xba\x03\xdc\xfe\xdc\xfc\xc8.BB.\x01\x80\xfe\x80.BB.\x038\x01$\x1cP\x1c\x1c\x1c\xe4\xe4\x1c\x1c\x1dO広\x83\xba\x83\x00\x05\x00\x00\xff\x80\x06\x80\x05\x80\x00\x0f\x00\x1d\x003\x00C\x00Q\x00\x00\x01\x14\x0e\x01#\".\x0154>\x0132\x1e\x01\x01\x14\x06#\".\x0154632\x1e\x01\x052\x04\x12\x15\x14\x0e\x02#\"&#\"\x06#\"54>\x02%\".\x0154>\x0132\x1e\x01\x15\x14\x0e\x01%2\x16\x15\x14\x0e\x01#\"&54>\x01\x03\f&X=L|<&X=M{<\xfe\xaaTML\x83FTML\x83F\x01\x8av\x01\x12\xb8\"?B+D\xef?B\xfdJ\xb7p\xa7\xd0\x01H=X&<{M=X&<|\x01dMTF\x83LMTF\x83\x04(\x012\x1e\x01\x02\xc0r_-\x02$\x1a\xc0\x1a$\x02-_rU\x96\xaa\x96U\x03\xf0\x91\xc5%\xfc\xcb\x1a&&\x1a\x035%ő\x80\xf3\x9d\x9d\xf3\x00\x00\x00\x00\x03\x00\x00\xff\x00\x06\x80\x05\x80\x00\x03\x00\a\x00\x1f\x00\x00\x05\x01\x11\x05'-\x01\r\x01\x11\x14\x06\a\x01\x06\"'\x01.\x015\x11467\x0162\x17\x01\x1e\x01\x03\x80\x02\x80\xfd\x80@\x02\xba\xfdF\xfdF\x05\xfa$\x1f\xfd@\x1cB\x1c\xfd@\x1f$.&\x02\xc0\x16,\x16\x02\xc0&.]\x01]\x02|\xe9q\xfe\xfe\xfe\x02\xfd\x00#<\x11\xfe\x80\x10\x10\x01\x80\x11<#\x03\x00(B\x0e\x01\x00\b\b\xff\x00\x0eB\x00\x00\x00\x00\a\x00\x00\xff\x00\b\x80\x06\x00\x00\x03\x00\a\x00\v\x00\x0f\x00\x13\x00\x17\x00B\x00\x00\x05%\x11\x05'-\x01\x05\x01%\x11\x05'-\x01\x05'%\x11\x05'-\x01\x05\x01\x11\x14\x06\a\x05\x06\"'%&'\x06\a\x05\x06\"'%.\x015\x11467%\x11467%62\x17\x05\x1e\x01\x15\x11\x05\x1e\x01\x02\x80\x01\x80\xfe\x80@\x01\x94\xfel\xfel\x05\xd4\x01\x80\xfe\x80@\x01\x94\xfel\xfel,\x01\x80\xfe\x80@\x01\xb9\xfeG\xfeG\x05\xf9&!\xfe@\x19@\x19\xfe@\x04\x03\x02\x05\xfe@\x19@\x19\xfe@!&+#\x01\xb2+#\x01\xc0\x176\x17\x01\xc0#+\x01\xb2$*`\xc0\x01:\xa4p\xad\xad\xad\xfd\x8d\xc0\x01:\xa4p\xad\xad\xadx\xa5\x01\n\xa4p\xbd\xbd\xbd\xfd=\xfe`$>\x10\xe0\x0e\x0e\xe0\x02\x02\x02\x02\xe0\x0e\x0e\xe0\x10>$\x01\xa0&@\x10\xba\x01\x90&@\x10\xc0\n\n\xc0\x10@&\xfep\xba\x10@\x00\x00\x06\x00\x00\xff\xfe\b\x00\x05\x02\x00\x03\x00\t\x00\x1f\x00&\x00.\x00A\x00\x00\x01!\x15!\x03\"\x06\a!&\x032673\x02!\"\x0254\x0032\x1e\x01\x15\x14\a!\x14\x16%!254#!5!2654#!%!2\x1e\x02\x15\x14\a\x1e\x01\x15\x14\x0e\x03#!\a8\xfe\x01\x01\xff\xfcZp\x06\x01\x98\x12\xa6?v\x11\xddd\xfe\xb9\xd6\xfd\x01\x05Ί\xcde\x02\xfdns\xfb6\x01(\xcd\xc7\xfe\xd2\x01\x19N[\xbe\xfe\xfc\xfe\xeb\x02RW\x88u?\xacrt1Sr\x80F\xfd\x9d\x04\xad|\xfe\xd2iZ\xc3\xfd\xb7@7\xfe\xcd\x01\b\xd7\xd0\x01\x13\x88މ\x11\x1eoy2\xa7\xb4\xbeIM\x90\xd7\x1cC~[\xb5R \xa6yK{T:\x1a\x00\x00\x00\a\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x1e\x00%\x00,\x00A\x00G\x00K\x00\x00\x012\x16\x15\x11\x14\x06#!\"&5\x11463\x13!\x11!2654'654.\x02\x03#532\x15\x14\x03#532\x15\x14\x05\"&5!654&#\"\x06\x15\x14\x16327#\x0e\x01\x032\x17#>\x01\x03!\x15!\x04\xe0w\xa9\xa9w\xfc@w\xa9\xa9w\xd3\xfe\x8d\x01~u\xa0\x8fk'JTM\xb0\xa3wa\xb9\xbd|\x02\nDH\x01\x9b\x01\x95\x81\x80\xa4\x9e\x86\xcd>\x8a\vI1q\v\xfe\x04Fj\x01?\xfe\xc1\x05\x80\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\xfe\x91\xfc\xedsq\x9e*4p9O*\x11\xfe¸Z^\xfe\xb1\xd9qh LE\n\x14\x84\xb1\xac\x82\x87\xa4\xbf\"(\x01nz8B\x01\nM\x00\x00\x00\x04\x00\x00\xff\x80\a\x00\x05\x80\x00\a\x00\x1b\x00'\x00?\x00\x00\x00\x14\x06\"&462\x004&#\"\a\x17\x1e\x01\a\x0e\x01'.\x01'\x1e\x0132\x014&#\"\x06\x15\x14\x163267\x14\x00#\x01\x0e\x01#\"&/\x01\x11\x05632\x17\x016\x0032\x00\x06.\x8fʏ\x8f\xca\xfd\x8d\x92h\x1b\x1bhMA\x1f\x1f\x98L\x15R\x14 vGh\x03г~\u007f\xb3\xb3\u007f~\xb3\x96\xfe\xf5\xbc\xfeK\f\u0084y\xba\x19\xe6\x01\x85O^\r\x16\x01\x1c\x02\x01\v\xbb\xbc\x01\v\x04\x1fʏ\x8fʏ\xfb\xbeВ\x06*\x1f\x97LM@\x1f\b!\b\xfeשw\x03\xc0w\xa9\xf7\x8eȍ\x8dde\x8d\x03)\xa0qrOPq\xfeȦs:0\x14\x14\x183=\x027\x16\x1b\x01'\x0e\x03\x0f\x01\x03.\x01?\x0167'\x01\x03\x0e\x01\x0f\x01\x06\a\x17\x03\x13\x17\x1667\x01\x06\x03%'\x13>\x01\x17\x1e\x05\x01\x13\x16\x06\a\x0e\x05\a&\x03%'7\x03%7.\x03/\x01\x056\x16\x1f\x01\x16\x03D\x0f\x02\xfe\\$>\x10\v\a\x0f\t\"\x02N,\xb4\x93?a0\x1f\x03\x04\xbe\x11\x02\a\b#O\x8c\x06\x80\xbc\f1\x13\x12G\x94\b\xe6\xd3\a\xaa\xe29\xfd'/\xda\xfe\xc3\x13\xe1\x14P(\x181#0\x180\x02\x97\xd4\x12\v\x16\r($=!F\v\"\xe7\x019|\x8e\xdc\xfe]\x97\"RE<\x11\x11\x01\x95\x1f6\f\v'\x01o\xfe\x90\x16\x1d\x039%\x1b8J$\\\a\f\x02:\xfe\x85\\H\x91iT\x15\x15\x01e\x1a<\x11\x12?}V\xfd\xea\xfe\x99\x1d#\x03\x04\a\x05\xa4\x01o\x01j\xad\x10\x16\x16\x03\xb2?\xfe\x8c\xbb\f\x01d\x1f\x1c\x04\x02\x14\x16,\x196\xfe\xc5\xfe\x95%N#\x14\"\x16\x16\n\x12\x03H\x01l\xc3\xedS\xfe\x8b\x14VY\x9a]C\r\r\x01\x03\x1b\x0f\x0f=\x00\x00\x04\x00\x00\xff@\b\x00\x05\x80\x00\a\x00\x11\x00\x19\x00C\x00\x00\x004&\"\x06\x14\x162\x13!\x03.\x01#!\"\x06\a\x004&\"\x06\x14\x162\x13\x11\x14\x06+\x01\x15\x14\x06\"&=\x01!\x15\x14\x06\"&=\x01#\"&5\x1146;\x01\x13>\x013!2\x16\x17\x1332\x16\x01\xe0^\x84^^\x84\x82\x03\xf8Y\x02\x18\t\xfd\x00\t\x18\x02\x05\x03^\x84^^\x84\xfe\x12\x0e`p\xa0p\xfc\x00p\xa0p`\x0e\x12\x83]\x1ci\x17\xa2b\x03\x00b\xa2\x17i\x1c]\x83\x01~\x84^^\x84^\x01\xe0\x01e\b\x13\x13\b\xfd\x19\x84^^\x84^\x01\x00\xfe\x80\x0e\x12\x80PppP\x80\x80PppP\x80\x12\x0e\x01\x80]\x83\x01\xa3^\u007f\u007f^\xfe]\x83\x00\x04\x00\x00\xff\x00\b\x00\x06\x00\x003\x00;\x00E\x00M\x00\x00\x012\x16\x15\x11\x14\x06+\x01\x15\x14\x06\"&=\x01!\x15\x14\x06\"&=\x01#\"&5\x1146;\x01\x13>\x01;\x015463!2\x16\x1d\x0132\x16\x17\x13\x00264&\"\x06\x14\x01!\x03.\x01#!\"\x06\a\x00264&\"\x06\x14\a ]\x83\x12\x0e`p\xa0p\xfc\x00p\xa0p`\x0e\x12\x83]\x1ci\x17\xa2b\x80\x12\x0e\x01\xc0\x0e\x12\x80b\xa2\x17i\xf9\xfa\x84^^\x84^\x01d\x03\xf8Y\x02\x18\t\xfd\x00\t\x18\x02\x04!\x84^^\x84^\x02\x80\x83]\xfe\x80\x0e\x12@PppP@@PppP@\x12\x0e\x01\x80]\x83\x01\xa3^\u007f\xe0\x0e\x12\x12\x0e\xe0\u007f^\xfe]\xfe ^\x84^^\x84\x01\x82\x01e\b\x13\x13\b\xfc\xbb^\x84^^\x84\x00\x01\x00 \xff\x00\x05\xe0\x06\x00\x003\x00\x00$\x14\x06#!\x1e\x01\x15\x14\x06#!\"&5467!\"&47\x01#\"&47\x01#\"&47\x0162\x17\x01\x16\x14\x06+\x01\x01\x16\x14\x06+\x01\x01\x05\xe0&\x1a\xfe2\x01\n$\x19\xfe\xc0\x19$\n\x01\xfe2\x1a&\x13\x01\x92\xe5\x1a&\x13\x01\x92\xc5\x1a&\x13\x01\x80\x134\x13\x01\x80\x13&\x1a\xc5\x01\x92\x13&\x1a\xe5\x01\x92Z4&\x11\x8d&\x19##\x19&\x8d\x11&4\x13\x01\x93&4\x13\x01\x93&4\x13\x01\x80\x13\x13\xfe\x80\x134&\xfem\x134&\xfem\x00\x04\x00\x00\xff\x80\x06\x00\x05\x80\x00\x15\x00+\x00D\x00P\x00\x00\x014'&#\"\a\x06\x15\x14\x16327632\x17\x1632674'&!\"\a\x06\x15\x14\x1632763 \x17\x16326\x134'&$#\"\a\x0e\x01\x15\x14\x16327632\x04\x17\x1632>\x01\x10\x02\x04 $\x02\x10\x12$ \x04\x04g\x1e\xc1\xfe\x85\x9a*\x1b\x16\x05 \x84o\xe2\xab\x13\x0e\x13\x1c`#\xed\xfeə\x960#\x19\a\x1ez\x81\x01\x17\xd1\x18\x0e\x19#l(~\xfe\xb2\xb0̠\x17\x1f)\x1f\v\x1d\x85\xae\x9f\x01-g\x15\x13\x1d+\xcd\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01F \x13s\"\t+\x14\x1d\b\x1bg\v\x1b\xec(\x15\x8d*\r3\x19#\b!|\r#\x01\x11/\x17IK/\a%\x1e\x1f*\b%D=\f)[\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x01\x00\x00\xff\x80\x04\x00\x06\x00\x00\x13\x00\x00\t\x01\x17!\x11!\a\x03\a!\x11\x01'!\x11!7\x137!\x04\x00\xfe\xd1\x18\x01\x17\xfe\x05,\x8e\x1e\xfe\xd3\x01/\x18\xfe\xe9\x01\xfb,\x8e\x1e\x01-\x04\xd1\xfd\xba\x1f\xfea\x1e\xfe\xef\x1e\x01/\x02G\x1e\x01\x9f\x1e\x01\x11\x1e\x00\x00\x00\x11\x00\x00\x00\x8c\t\x00\x04t\x00\x0e\x00%\x00/\x00;\x00<\x00H\x00T\x00b\x00c\x00q\x00\u007f\x00\x8d\x00\x90\x00\x9e\x00\xac\x00\xc0\x00\xd4\x00\x00%7\x03.\x01#\"\x06\x15\x03\x17\x1e\x0132%7\x034'&\"\a\x06\x15\a\x03\x14\x17\x15\x14\x17\x1632765\x01\x17\a\x06\"/\x017627\x17\a\x06#\"5'7432\x01\x03\x17\a\x14#\"/\x017632\x1f\x01\a\x06#\"5'7432\x1f\x01\a\x06#\"&5'74632\t\x01\x13\a\x14\x06#\"/\x01\x13632\x167\x13\a\x14\x06#\"/\x01\x13632\x167\x13\a\x06#\"/\x01\x134632\x16\x019\x01\x03\x13\a\x14\x06\"&/\x01\x13462\x16\x17\x13\a\x14\x06\"&/\x01\x13>\x012\x16\x13\a1\x14\x06\"&/\x02\x13567632\x17\x16\x17\x01\x14\x06#!.\x015\x1147632\x00\x17632\x16\x03\x10\x10\x10\x01\r\n\t\x0e\x0e\x0e\x01\r\t\x16\x01*\v\f\r\b\x10\b\r\x01\n\v\x06\t\x0e\v\t\t\xfb\xec\x14\x14\x02\x0e\x02\x11\x11\x02\x0eX\x1a\x1a\x02\b\t\x17\x17\t\b\x01\x1a\xbc\x19\x19\v\n\x02\x15\x15\x02\n\v^\x17\x17\x02\f\r\x15\x15\r\f`\x15\x15\x02\x0e\x06\t\x14\x14\t\x06\x0e\x01\x81\xfe\xdf\x15\x15\n\a\x10\x02\x12\x12\x02\x10\a\n^\x13\x13\v\b\x12\x02\x10\x10\x02\x12\b\vb\x12\x12\x02\x14\x13\x02\x10\x10\r\b\t\f\x01\x89\xc6\x0f\x0f\x0f\x14\x0e\x01\x0e\x0e\x0f\x14\x0fc\x0e\x0e\x10\x16\x10\x01\f\f\x01\x10\x16\x0f\xd5\x0e\x12\x1a\x12\x01\x06\x06\f\x02\n\t\v\b\a\x0e\x02\x04f\xa6u\xfc\xee\r\x12\x1cU`\xc3\x01\x1e\x1159u\xa6\xa4\xf1\x02\v\n\x0e\x0e\n\xfd\xf5\xf1\n\r4\xd3\x02J\x10\b\x05\x05\b\x10\x06\xfd\xbd\x01\xeb\x01\n\a\v\t\a\r\x01l\x80~\t\t~\x80\tF\xcf\xcb\t\n\xca\xcf\t\xfe2\x01\xeb\xf5\xed\v\v\xed\xf5\f\x05\xfc\xf4\r\r\xf4\xfc\r\x1f\xea\xf6\x10\t\a\xf6\xea\x06\t\xfe\x16\x02m\xfe\x84\xf6\a\v\x12\xf6\x01|\x12\vO\xfe,\xf4\b\v\x13\xf4\x01\xd4\x13\v \xfe\x06\xf2\x15\x15\xf2\x01\xfa\t\r\r\xfd\x11\x02\xea\xfe\x02\xef\n\x0f\x0e\v\xef\x01\xfe\v\x0e\x0e\x1e\xfe\x14\xec\v\x10\x10\v\xec\x01\xec\f\x10\x10\xfe\b\xe7\r\x12\x12\rru\x02|\x03\x0f\t\a\x05\b\x12\xfd\x94u\xa5\x02\x12\r\x03\x83\x17\n\"\xfe\xf9\xc0\x16\xa6\x00\x00\x00\x04\x00\x00\xff\x00\x06\x00\x06\x00\x00\r\x00\x1b\x00)\x009\x00\x00\x00 $7\x15\x14\x06\x04 $&=\x01\x16\x00 $7\x15\x14\x06\x04 $&=\x01\x16\x00 $7\x15\x14\x06\x04 $&=\x01\x16\x00 \x04\x16\x1d\x01\x14\x06\x04 $&=\x0146\x02\x13\x01\xda\x01\x9cw\xce\xfe\x9e\xfe`\xfe\x9e\xcew\x01\x9c\x01\xda\x01\x9cw\xce\xfe\x9e\xfe`\xfe\x9e\xcew\x01\x9c\x01\xda\x01\x9cw\xce\xfe\x9e\xfe`\xfe\x9e\xcew\x01\xb9\x01\xa0\x01b\xce\xce\xfe\x9e\xfe`\xfe\x9e\xce\xce\x03\x00VT\xaaEvEEvE\xaaT\xfc\xaaVT\xaaEvEEvE\xaaT\x01*VT\xaaEvEEvE\xaaT\x04*EvE\x80EvEEvE\x80Ev\x00\b\x00\x00\xff\x00\x06\x00\x06\x00\x00\x13\x00\x1a\x00#\x00^\x00c\x00t\x00\u007f\x00\x87\x00\x00\x01\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x17\a\x11!&'\x01&\x01\x11!\"&5\x11!\x11\x01\x16\x17632\x17\x16\a\x14\x06\a\x15\x06#\"&'\x06\a\x02#\"/\x01&'&7>\x0176\x17\x16\x156767.\x0176;\x022\x17\x16\a\x06\a\x16\x1d\x01\x06\a\x16\x0167\x0e\x01\x01\x06\x17674767&5&5&'\x14\a\x0367.\x01'&'\x06\a\x06\x05&#\x163274\x05\xbc\x1c(8(\xfa\xc0(88(\x03\x80(`\x1c\x84\x01x\n\f\xfe\xc7\f\x01c\xfe`(8\xfd\x00\x02\xfe!3;:\x93\x1e\x10\x0e\x02\x01\x06A0\x86?ݫ\x99Y\x0f\r\x18\x01\x05\n\x04\t^U\x0e\t\x0247D$\x18\r\r\v\x1f\x15\x01\x17\f\x12\t\x02\x02\x01\x02\f7\xfe\x1b4U3I\x01\x81\x0f\r\x01\x06\a\x01\x03\x01\x01\x01\f\x01|\x87\x95\x02\x16\x05L3\x1b8\x1e\x02w\x18tL0\x0e\x04\x04\x84\x1c`(\xfb\x80(88(\x06@(8(\x1cD\xfe\x88\x1d\f\x019\f\xfa\x12\x04\x008(\x01\xa0\xfa\x00\x02Q\x1a\x1e\a1\x16\x1e\x01\x02\x01\x01&(!\x18;\xfe\xfa\a\f\x01\x04\n\x1a(g-\t\x0f\x02\x02Up\x88~R\x9b2(\x0f\x15/\x06\x02\x03\x05\x1e{E\xa4\xfe\x1b\x18\x86(X\x03z*Z\a%\x03(\x04\x04\x01\x01\x02\x01\x16\x0e\x01\x01\xfdi6\x1b\x01\x11\x05CmVo8\v\x18\x1c\x01\x01\x00\x00\x00\x00\x04\x00\x00\xff\x00\x06\x00\x06\x00\x00\x13\x00\x1a\x00#\x00T\x00\x00\x01\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x17\a\x11!&'\x01&\x01\x11!\"&5\x11!\x11\x13\x153\x133\x1367653\x17\x1e\x01\x17\x133\x1335!\x153\x03\x06\x0f\x01#4.\x015.\x01'\x03#\x03\x0e\x01\x0f\x01#'&'\x0335\x05\xbc\x1c(8(\xfa\xc0(88(\x03\x80(`\x1c\x84\x01x\n\f\xfe\xc7\f\x01c\xfe`(8\xfd\x00iF\xa4\x9f\x80\a\x03\x02\x04\x03\x01\x05\x03\x80\x9f\xa4F\xfe\xd4Zc\x05\x02\x02\x04\x01\x02\x01\x06\x02\x90r\x90\x02\x05\x01\x04\x04\x02\x02\x05cZ\x04\x84\x1c`(\xfb\x80(88(\x06@(8(\x1cD\xfe\x88\x1d\f\x019\f\xfa\x12\x04\x008(\x01\xa0\xfa\x00\x03\x80k\xfdk\x01\xe5\x14\x1a\x10\b\x18\x03\"\t\xfe\x1b\x02\x95kk\xfeJ\x14\x1a\x15\x03\a\t\x02\x05 \t\x02!\xfd\xdf\t\x1f\x06\x15\x15\x1a\x14\x01\xb6k\x00\x00\x04\x00\x00\xff\x00\x06\x00\x06\x00\x00\x13\x00\x1a\x00#\x00S\x00\x00\x01\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x17\a\x11!&'\x01&\x01\x11!\"&5\x11!\x11%\x15!5#7>\x02;\x01\x16\x17\x1e\x02\x1f\x01#\x15!5#\x03\x1335!\x153\a\x0e\x01\x0f\x01#&'&/\x0135!\x153\x13\x03\x05\xbc\x1c(8(\xfa\xc0(88(\x03\x80(`\x1c\x84\x01x\n\f\xfe\xc7\f\x01c\xfe`(8\xfd\x00\x01-\x01\x19Kg\x05\n\x05\x01\x02\x01\x04\x02\x05\a\x03kL\x01#D\xc0\xc3C\xfe\xe9Jg\x04\f\x03\x02\x02\x01\x04\x06\vjL\xfe\xdeD\xbd\xc2\x04\x84\x1c`(\xfb\x80(88(\x06@(8(\x1cD\xfe\x88\x1d\f\x019\f\xfa\x12\x04\x008(\x01\xa0\xfa\x00\xeajj\xa1\a\x13\b\x04\x06\x04\a\t\x04\xa1jj\x01\x11\x01\x1akk\x9f\a\x13\x04\x03\x04\x06\v\f\x9fkk\xfe\xf0\xfe\xe5\x00\x00\x00\x00\x05\x00\x00\xff\x00\x06\x00\x06\x00\x00\x13\x00\x1a\x00#\x008\x00C\x00\x00\x01\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x17\a\x11!&'\x01&\x01\x11!\"&5\x11!\x11%\x15!5#5327>\x0154&'&#!\x153\x11\x01#\x1132\x17\x16\x15\x14\a\x06\x05\xbc\x1c(8(\xfa\xc0(88(\x03\x80(`\x1c\x84\x01x\n\f\xfe\xc7\f\x01c\xfe`(8\xfd\x00\x01 \x01G]\x89L*COJ?0R\xfe\x90\\\x01\x05wx4\x1f8>\x1f\x04\x84\x1c`(\xfb\x80(88(\x06@(8(\x1cD\xfe\x88\x1d\f\x019\f\xfa\x12\x04\x008(\x01\xa0\xfa\x00\xeajj\xa7\x0f\x17\x80RQx\x1b\x13k\xfd\xd5\x01\x18\x01\f\x12!RY\x1f\x0f\x00\x00\x00\x00\x05\x00\x00\xff\x00\x06\x00\x06\x00\x00\x13\x00\x1a\x00#\x00*\x002\x00\x00\x01\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x17\a\x11!&'\x01&\x01\x11!\"&5\x11!\x11\x01\x11!57\x17\x01\x04\"&462\x16\x14\x05\xbc\x1c(8(\xfa\xc0(88(\x03\x80(`\x1c\x84\x01x\n\f\xfe\xc7\f\x01c\xfe`(8\xfd\x00\x04\x80\xfc\x00\xc0\x80\x01\x80\xfeP\xa0pp\xa0p\x04\x84\x1c`(\xfb\x80(88(\x06@(8(\x1cD\xfe\x88\x1d\f\x019\f\xfa\x12\x04\x008(\x01\xa0\xfa\x00\x01\xc0\xfe\xc0\xc0\xc0\x80\x01\x80\x80p\xa0pp\xa0\x00\x00\t\x00\x00\xff\x00\x06\x00\x06\x00\x00\x03\x00\a\x00\v\x00\x0f\x00#\x00*\x007\x00J\x00R\x00\x00\x015#\x15\x055#\x1d\x015#\x15\x055#\x15\x01\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x17\a\x11!&'\x01&\x01\x11!\"&5\x11#\x15#5!\x11\x01\x13\x16\x15\x14\x06\"&5476\x1353\x1532\x16\x02264&\"\x06\x14\x02\x80\x80\x01\x00\x80\x80\x01\x00\x80\x03<\x1c(8(\xfa\xc0(88(\x03\x80(`\x1c\x84\x01x\n\f\xfe\xc7\f\x01c\xfe`(8\x80\x80\xfe\x00\x02\x8dk\b\x91ޑ\b\x15c\x80O\x16\"\xbcjKKjK\x04\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01\x84\x1c`(\xfb\x80(88(\x06@(8(\x1cD\xfe\x88\x1d\f\x019\f\xfa\x12\x04\x008(\x01\xa0\x80\x80\xfa\x00\x02\xd1\xfe\xa3\x1b\x19SmmS\x19\x1b?\x01M\x80\x80\x1a\xfe\x1a&4&&4\x00\x00\x00\x00\x06\x00\x00\xff\x00\x06\x00\x06\x00\x00\x13\x00\x1a\x00#\x009\x00L\x00^\x00\x00\x01\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x17\a\x11!&'\x01&\x01\x11!\"&5\x11!\x11\x01\x16\x15\x11\x14\a\x06#\"/\x01#\"&=\x0146;\x0176\x01276\x10'.\x01\a\x0e\x01\x17\x16\x10\a\x06\x16\x17\x16'2764'.\x01\x0e\x01\x17\x16\x14\a\x06\x16\x17\x16\x05\xbc\x1c(8(\xfa\xc0(88(\x03\x80(`\x1c\x84\x01x\n\f\xfe\xc7\f\x01c\xfe`(8\xfd\x00\x01\xec\x14\x14\b\x04\f\v\xa6\x83\x0e\x12\x12\x0e\x83\xa6\x10\x01\xb4\x1f\x13\x81\x81\x106\x14\x15\x05\x11dd\x11\x05\x15\x12\xbd\x1b\x14WW\x126&\x02\x1344\x13\x02\x13\x14\x04\x84\x1c`(\xfb\x80(88(\x06@(8(\x1cD\xfe\x88\x1d\f\x019\f\xfa\x12\x04\x008(\x01\xa0\xfa\x00\x03.\b\x16\xfd\xe0\x16\b\x02\t\xa7\x12\x0e\xc0\x0e\x12\xa7\x0f\xfdG\x18\x9f\x01\x98\x9f\x15\x06\x11\x115\x15{\xfe\xc2{\x155\x10\x0f\x94\x14]\xfc]\x13\x02$5\x149\x949\x145\x12\x11\x00\x00\x00\x05\x00\x00\xff\x00\x06\x00\x06\x00\x00\x13\x00\x1a\x00#\x003\x00C\x00\x00\x01\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x17\a\x11!&'\x01&\x01\x11!\"&5\x11!\x11\x012\x16\x15\x11\x14\x06#!\"&5\x11463\x05\x16\x15\x11\x14\a\x06#\"'\x015\x01632\x05\xbc\x1c(8(\xfa\xc0(88(\x03\x80(`\x1c\x84\x01x\n\f\xfe\xc7\f\x01c\xfe`(8\xfd\x00\x02\x804LL4\xfe\x804LL4\x03l\x14\x14\b\x04\x0e\t\xfe\xf7\x01\t\t\x0e\x04\x04\x84\x1c`(\xfb\x80(88(\x06@(8(\x1cD\xfe\x88\x1d\f\x019\f\xfa\x12\x04\x008(\x01\xa0\xfa\x00\x03\x80L4\xfe\x804LL4\x01\x804L\x02\b\x16\xfd\xc0\x16\b\x02\t\x01\nZ\x01\n\t\x00\x00\x00\x06\x00\x00\xff\x00\x06\x00\x06\x00\x00\x13\x00\x1a\x00#\x007\x00K\x00[\x00\x00\x01\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x17\a\x11!&'\x01&\x01\x11!\"&5\x11!\x11\x01>\x01\x1f\x01\x1e\x01\x0f\x01\x17\x16\x06\x0f\x01\x06&'\x03&7!\x16\a\x03\x0e\x01/\x01.\x01?\x01'&6?\x016\x16\x17\x01.\x017\x13>\x01\x1f\x01\x1e\x01\a\x03\x0e\x01'\x05\xbc\x1c(8(\xfa\xc0(88(\x03\x80(`\x1c\x84\x01x\n\f\xfe\xc7\f\x01c\xfe`(8\xfd\x00\x01`\b\x1a\v3\v\x03\b\xb6\xb6\b\x03\v3\v\x1a\b\xe2\x0e\x0e\x04\x04\x0e\x0e\xe2\b\x1a\v3\v\x03\b\xb6\xb6\b\x03\v3\v\x1a\b\xfev\r\x0f\x02\x8a\x02\x16\r?\r\x0f\x02\x8a\x02\x16\r\x04\x84\x1c`(\xfb\x80(88(\x06@(8(\x1cD\xfe\x88\x1d\f\x019\f\xfa\x12\x04\x008(\x01\xa0\xfa\x00\x03\x80\v\x03\b&\b\x1a\v\xf3\xf3\v\x1a\b&\b\x03\v\x01-\x13\x13\x13\x13\xfe\xd3\v\x03\b&\b\x1a\v\xf3\xf3\v\x1a\b&\b\x03\v\xfd\x06\x02\x16\r\x03?\r\x0f\x02\n\x02\x16\r\xfc\xc1\r\x0f\x02\x00\x01\x00'\xff\x97\x05\xd9\x06\x00\x006\x00\x00\x01\x15\x06#\x06\x02\x06\a\x06'.\x04\n\x01'!\x16\x1a\x01\x16\x1767&\x0254632\x16\x15\x14\a\x0e\x01\".\x01'654&#\"\x06\x15\x14\x1632\x05\xd9eaAɢ/PR\x1cAids`W\x1b\x01\x1b\x1aXyzO\xa9v\x8e\xa2д\xb2\xbe:\a\x19C;A\x12\x1f:25@Ң>\x02\xc5\xc6\x17\x88\xfe\xf2\xa1\x1a-0\x115r\x8f\xe1\x01\a\x01n\xcf\xda\xfe\x97\xfe\xef\xc6`\xa9\xedH\x01(\xb9\xc0\xf5\xd3\xc0\x9f\u007f\x01\x04\f' gQWZc[\xba\xd7\x00\x00\b\x00\x00\xff\x00\a\x00\x06\x00\x00\x03\x00\x06\x00\n\x00\x0e\x00\x12\x00\x15\x00\x19\x00-\x00\x00\x13\x01\x11%\x057'\t\x01%\x05'-\x01\x05'%\x11\t\x01\x17\x11\x05%\x01\x11\x05\x11\x14\a\x01\x06\"'\x01&5\x1147\x0162\x17\x01\x16\xd8\x02[\xfe\xb2\xfe\xb5\xc1\xc1\x033\x02[\xfe\xf3\xfe\xb2M\x01\x10\xfe\xf0\xfe\xf0\x8b\x01N\xfd\xa5\x04\xcd\xc1\xfe\xb5\x01\r\xfd\xa5\x033\"\xfc\xcd\x15,\x15\xfc\xcd\"\"\x033\x15,\x15\x033\"\x01o\xfen\x01g\xdf$\x81\x81\xfc\xdc\x01\x92\xb4߆\xb6\xb6\xb6]\xdf\x01g\xfen\xfe\xef\x81\x01\x02$\xb4\x01\x92\xfe\x99+\xfd\xde)\x17\xfd\xde\r\r\x02\"\x17)\x02\")\x17\x02\"\r\r\xfd\xde\x17\x00\x00\x00\x00\x02\x00\x00\x00\x00\b\x00\x05x\x00#\x00W\x00\x00\x01\x1e\x01\x15\x14\x06#\"&#!+\x02.\x015467&54632\x176$32\x04\x12\x15\x14\x06\x01\x14\x16327.\x01'\x06#\"&54632\x1e\x0532654&#\"\a\x17632\x16\x15\x14\x06#\".\x05#\"\x06\a\bo\x89\xec\xa7\x04\x0f\x03\xfbG\x01\x02\x05\xaa\xecn\\\f\xa4u_MK\x01'\xb3\xa6\x01\x18\xa3\x01\xfą|\x89g\x10?\fCM7MM5,QAAIQqAy\xa7\xa8{\x8fb]BL4PJ9+OABIRo?z\xaa\x02\xfc.\xc7z\xa4\xe9\x01\n\xe7\xa5n\xba6'+s\xa2:\x9a\xbc\xa1\xfe\xec\xa3\x06\x18\xfe\xf0z\x8ec\x14I\x0eAC65D*DRRD*\x8fwy\x8eal@B39E*DRRD*\x8d\x00\x00\x00\x00\x06\x00\x00\xff\x00\a\x00\x06\x00\x00\x0f\x00\x17\x00\x1f\x00'\x00/\x007\x00\x00\x00 \x04\x16\x12\x10\x02\x06\x04 $&\x02\x10\x126$ \a\x1762\x177\x017&47'\x06\x10\x00 7'\x06\"'\a\x12 6\x10& \x06\x10\x05\x176\x10'\a\x16\x14\x02\xca\x01l\x01L\xf0\x8e\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x02\xc0\xfe\x84\xab\xc2R\xaaR\xc2\xfb\xf1\xc2\x1c\x1c\xc2Z\x02B\x01|\xab\xc2R\xaaR\xc2\xca\x01>\xe1\xe1\xfe\xc2\xe1\x03d\xc2ZZ\xc2\x1c\x06\x00\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x0eZ\xc2\x1c\x1c\xc2\xfb\xf1\xc2R\xaaR«\xfe\x84\xfd\xbeZ\xc2\x1c\x1c\xc2\x01&\xe1\x01>\xe1\xe1\xfe\xc2\b«\x01|\xab\xc2R\xaa\x00\x01\x00 \xff \x06\xe0\x05\xd7\x00!\x00\x00\x01\x14\x02\x06\x04 $&\x0254\x12$7\x15\x06\x00\x15\x14\x1e\x02 >\x0254\x00'5\x16\x04\x12\x06\xe0\x89\xe7\xfe\xc0\xfe\xa0\xfe\xc0\xe7\x89\xc2\x01P\xce\xdd\xfe\xddf\xab\xed\x01\x04\xed\xabf\xfe\xdd\xdd\xce\x01P\xc2\x02\x80\xb0\xfe\xc0牉\xe7\x01@\xb0\xd5\x01s\xf0\x1f\xe4-\xfe\xa0\xe6\x82\xed\xabff\xab\xed\x82\xe6\x01`-\xe4\x1f\xf0\xfe\x8d\x00\x00\x01\x00\x13\xff\x00\x06\xee\x06\x00\x00c\x00\x00\x136\x12721\x14\a\x0e\x04\x1e\x01\x17\x1e\x01>\x01?\x01>\x01.\x01/\x01.\x03/\x017\x1e\x01\x1f\x016&/\x017\x17\x0e\x01\x0f\x01>\x01?\x01\x17\x0e\x01\x0f\x01\x0e\x01\x16\x17\x1e\x01>\x01?\x01>\x02.\x04/\x01&3\x161\x1e\b\x17\x12\x02\x04#\"$&\x02\x13\b\xd8\xc5\x05\x01\b(@8!\x05IH2hM>\x10\x10'\x1c\x0f\x1b\r\x0e\n)-*\x0e\rh'N\x14\x13\x01'\x15\x14\xa1\xa0!'\x03\x04\x16O\x1c\x1cg,R\x13\x13\x1f\"\x14/!YQG\x16\x15\x0154'6\x133&5\x1147#\x16\x15\x11\x14\x055\x06#\"=\x0132\x1635#47#\x16\x1d\x01#\x15632\x163\x15#\x15\x14\x1e\x0332\x014&\"\x06\x15\x14\x1626%\x11\x14\x06#!\"&5\x11463!2\x16\x02F]kbf$JMM$&\xa6N92Z2\x1d\b\x02\a\x18\x06\x15&`\x06\xe3\x06\xab\x0f9\x0eUW=\xfd\xf0N9:PO;:\x16dhe\x03\\=R\x91\x87\x01\xcd\xca\f\n+)\u007f\xb3\x17\b&'\x1f)\x17\x15\x1e-S9\xfe\xd0\x199kJ\xa5<\x04)Um\x1c\x04\x18\xa9Q\x8b\xb9/\xfc\xbe-Y\x02a^\"![\xfd\x9bY\xb1\xc4'(<`X;\x01_\x04\x02\x06\xbeL6#)|\xbe\x04\xfe\x93\x83\x04\x0etWW:;X\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\v\x00\x1b\x00\x00\t\x01#\x03\x06\a'\x03#\x01\x113\x01\x11\x14\x06#!\"&5\x11463!2\x16\x03)\x01\np\x9d\x18\x14*\x9bx\x01\ae\x02שw\xfc@w\xa9\xa9w\x03\xc0w\xa9\x02\x14\x01\xf3\xfe\xc80,\\\x018\xfe\x13\xfe\xbc\x03\x8a\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x02\x009\xff\x00\x04\xc7\x06\x00\x00\x1d\x00I\x00\x00\x00\x14\x06#\"'\x06\a\x02\x13\x16\x06\a#\"&'&>\x03767&5462\x04\x10\x02\x04#\"'.\x017>\x01\x17\x1632>\x024.\x02\"\x0e\x02\x15\x14\x17\x16\x0e\x01&'&54>\x0232\x04\x03JrO<3>5\xf7-\x01\x1b\x15\x05\x14\x1e\x02\x0e\x15&FD(=G\x10q\xa0\x01\xee\x9c\xfe\xf3\x9e@C\x15\x17\x05\x05$\x1539a\xb2\x80LL\x80\xb2²\x80L4\n\r&)\n@]\x9c\xd8v\x9e\x01\r\x04\x14\xa0q#CO\xfe\x8d\xfe\x18\x16!\x02\x1b\x14~\U000ffd42\x0172765'.\x01/\x01\"\a\x0e\x01\a#\"&'&5\x10\x01\x0e\b\x16\r\x01\x11\x0e\xb9}\x8b\xb9\x85\x851R<2\"\x1f\x14\f\x017\x12\x03\x04MW'$\t\x15\x11\x15\v\x10\x01\x01\x02\x05;I\x14S7\b\x02\x04\x05@\xee5sQ@\x0f\b\x0e@\b)\xadR#DvTA\x14\x1f\v;\x14\x04\n\x02\x020x\r\x05\x04\b\x12I)\x01\x04\x04\x03\x17\x02\xda\x13!\x14:\x10\x16>\f\x8b\x01+\x03\x14)C\x04\t\x016.\x01\x13\x00\x00\x00\x00\x06\x00\x00\xff>\b\x00\x05\xc2\x00\n\x00\x16\x00!\x00-\x00I\x00[\x00\x00\x004&#\"\x06\x15\x14\x1632\x014&#\"\x06\x15\x14\x16326\x024&#\"\x06\x15\x14\x1632\x014&#\"\x06\x15\x14\x16326\x01&#\"\x04\x02\x15\x14\x17\x06#\".\x03'\a7$\x114\x12$32\x04\x16\x01\x14\x06\a\x17'\x06#\"$&\x106$32\x04\x16\x02D2)+BB+)\x03\x193(\x1b--\x1b(3\xec1)+BB+)\x02\xac4'\x1b--\x1b'4\xfe\xf6\x1f'\xa9\xfe\xe4\xa3\x17#!\x1a0>\x1bR\t\xfdH\xfe\xde\xc3\x01MŰ\x019\xd3\x02o\x89u7ǖD\xa9\xfe䣣\x01\x1c\xa9\xa1\x01\x1c\xab\x04\nR23('3\xfe_\x1c,-\x1b\x1c-,\x01\xefR23('3\xfe_\x1c,-\x1b\x1c-,\x01\xaa\x04\x9a\xfe\xf9\x9cNJ\x03\x03\n\x04\x11\x02\u007f\xda\xcb\x01\x1f\xa9\x01\x1c\xa3\x84\xe9\xfd?u\xd5W\xb5m%\x8d\xf2\x01\x1e\xf2\x8d\x8d\xf3\x00\x01\x00\x00\xff\x00\x06\xff\x06\x00\x00\x1e\x00\x00\x01\x16\a\x01\x06\a\x06#\"'%\x03\x06#\"'.\x015\x11\t\x01%&'&7\x01632\x06\xe4!\x06\xff\x00\x05\x1b\x0e\x11\v\r\xfe;\xf2\x12\x1f\r\t\x13\x17\x03`\xfb\xd3\xfeu%\x03\x02\"\x06\x80\x0f\x11\x14\x05\xf5\x18(\xfa\x00\x1d\x10\b\x05\xb9\xfe\xd9\x17\x04\a!\x14\x01]\x04#\xfcc\xa2\x0e)(\x13\x03\xc0\t\x00\x00\x00\x00\x02\x00\x00\xff\x00\x06\xff\x05\xf7\x00\x1a\x00 \x00\x00\x01\x16\a\x01\x06\a\x06#\"'%\x01\x06#\"'.\x015\x11%&'&7\x016\x01\x13\x01\x05\t\x01\x06\xe4!\x06\xff\x00\x05\x1b\x0e\x11\v\r\xfd\xf1\xfe\xd6\x12\x1d\x0e\t\x13\x16\xfe(%\x03\x03#\x06\x80#\xfe\xcb\xdd\xfaf\x01P\x03_\xfe\"\x05\xf5\x18(\xfa\x00\x1d\x10\b\x05\xd7\xfe\xb9\x15\x04\a!\x14\x01\xc4\xc1\x0e)'\x14\x03\xc0\x15\xfa\x0e\x05+\xfcʼn\x02\u007f\xfc\xe3\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x004\x00I\x00\x00\x00\x10\x02\x06\x04#\"$'&6?\x0163\x16\x17\x1e\x0132>\x024.\x02#\"\x06\a\x17\x16\a\x06#!\"&5\x11476\x1f\x016$32\x04\x16\x05\x11\x14\x06#!\"&=\x0146;\x01\x1146;\x012\x16\x06\x00z\xce\xfe䜬\xfe\xcam\a\x01\b\x89\n\x0f\x10\aI\xd4wh\xbd\x8aQQ\x8a\xbdhb\xb4F\x89\x1f\x11\x11*\xfe@\x1a&('\x1e\x82k\x01\x13\x93\x9c\x01\x1c\xce\xfd\xfa\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\xe0\x12\x0e@\x0e\x12\x03\x1c\xfe\xc8\xfe\xe4\xcez\x91\x84\n\x19\b\x8a\t\x02\n_hQ\x8a\xbdн\x8aQGB\x8a\x1e'(&\x1a\x01\xc0*\x11\x11\x1f\x81eozΘ\xfe@\x0e\x12\x12\x0e@\x0e\x12\x01`\x0e\x12\x12\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x1b\x00\x00\x00 \x0e\x02\x10\x1e\x02 >\x02\x10.\x01\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x03\x82\xfe\xfc\xed\xabff\xab\xed\x01\x04\xed\xabff\xab\x01\x91\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x05\x00f\xab\xed\xfe\xfc\xed\xabff\xab\xed\x01\x04\xed\xab\xfe\xb7\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x01\x00>\xff\x80\x06\xc2\x05\x80\x00\x85\x00\x00\x05\"&#\"\x06#\"&54>\x02765\x034'&#!\"\a\x06\x15\x03\x14\x17\x1e\x03\x15\x14\x06#\"&#\"\x06#\"&54>\x02765'\x1146.\x04'.\x01\"&54632\x1632632\x16\x15\x14\x0e\x02\a\x06\x15\x13\x14\x17\x163!2765\x134'.\x0254632\x1632632\x16\x15\x14\x0e\x02\a\x06\x15\x13\x14\x17\x1e\x03\x15\x14\x06\x06\x92,\xb1-,\xb0,\x18\x1a\",:\x10!\x01\x01\r%\xfd]&\r\x01\x01%\x10@2(\x19\x18/\xb9.+\xaa*\x17\x19\x1f)6\x0f!\x01\x01\x01\x02\x05\b\x0e\t\x0f<.$\x18\x18.\xb9.*\xa9*\x19\x19\"+8\x0f#\x01\x01\r\x1a\x02\xbb\x19\r\x01\x01#\x12Q3\x19\x19,\xb0,+\xac+\x19\x19#-:\x0f#\x01\"\x10\x19$$\x19\x01\xf0\f/:yu\x8e\xa6xv)%$\x00\t\x00\x00\xff\x80\x06\x00\x05\x00\x00\x03\x00\x13\x00\x17\x00\x1b\x00\x1f\x00/\x00?\x00C\x00G\x00\x00%\x15!5%2\x16\x15\x11\x14\x06#!\"&5\x11463\x01\x15!5\x13\x15#5\x01\x15!5\x032\x16\x15\x11\x14\x06#!\"&5\x11463\x012\x16\x15\x11\x14\x06#!\"&5\x11463\x05\x15#5\x13\x15!5\x01`\xfe\xa0\x02\xc0\x1a&&\x1a\xff\x00\x1a&&\x1a\x01\xa0\xfc\xa0\xe0\xe0\x06\x00\xfd \xe0\x1a&&\x1a\xff\x00\x1a&&\x1a\x03\x80\x1a&&\x1a\xff\x00\x1a&&\x1a\x02@\xe0\xe0\xfc\xa0\x80\x80\x80\x80&\x1a\xff\x00\x1a&&\x1a\x01\x00\x1a&\x01\x80\x80\x80\x02\x00\x80\x80\xfc\x00\x80\x80\x04\x80&\x1a\xff\x00\x1a&&\x1a\x01\x00\x1a&\xfe\x00&\x1a\xff\x00\x1a&&\x1a\x01\x00\x1a&\x80\x80\x80\x02\x00\x80\x80\x00\x01\x00\x00\xff\x80\x06\x00\x05\x80\x00%\x00\x00\x012\x16\x10\x06 &547%\x06#\"&\x10632\x17%&546 \x16\x10\x06#\"'\x05\x16\x14\a\x056\x04\xc0\x85\xbb\xbb\xfe\xf6\xbb\x02\xfe\x98\\~\x85\xbb\xbb\x85~\\\x01h\x02\xbb\x01\n\xbb\xbb\x85~\\\xfe\x98\x02\x02\x01h\\\x02\x00\xbb\xfe\xf6\xbb\xbb\x85\f\x16\xb4V\xbb\x01\n\xbbV\xb4\x16\f\x85\xbb\xbb\xfe\xf6\xbbV\xb4\x16\x18\x16\xb4V\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00%\x005\x00\x00$4&#\"\a'64'7\x163264&\"\x06\x15\x14\x17\a&#\"\x06\x14\x16327\x17\x06\x15\x14\x162\x01\x11\x14\x06#!\"&5\x11463!2\x16\x05\x00}XT=\xf1\x02\x02\xf1=TX}}\xb0~\x02\xf1>SX}}XS>\xf1\x02~\xb0\x01}\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\xfd\xb0~:x\x10\x0e\x10x:~\xb0}}X\a\x10x9}\xb0}9x\x10\aX}\x03\xe0\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\a\x00\x00\xff\x00\a\x00\x06\x00\x00\x11\x00/\x00>\x00L\x00X\x00d\x00s\x00\x00\x00.\x01\a\x0e\x01\a\x06\x16\x17\x16327>\x0176\x01\x17\a\x17\x16\x14\x0f\x01\x16\x15\x14\x02\x06\x04 $&\x02\x10\x126$32\x17762\x1f\x01\x13\x06#\"/\x01&4762\x1f\x01\x16\x14\x17\x06\"/\x01&4762\x1f\x01\x16\x146\x14\x06+\x01\"&46;\x012'\x15\x14\x06\"&=\x01462\x16\x17\a\x06#\"'&4?\x0162\x17\x16\x14\x02E\x140\x19l\xa6,\n\x14\x19\r\v*\x12\"\x81T\x19\x03\xb8.\xf4D\x13\x13@Yo\xbd\xfe\xfb\xfe\xe2\xfe\xfb\xbdoo\xbd\x01\x05\x8f\xb6\xa1@\x135\x13D\xfb\n\f\r\n[\t\t\n\x1a\nZ\n\xdc\v\x18\vZ\n\n\t\x1b\t[\t \x12\x0e`\x0e\x12\x12\x0e`\x0e\xae\x12\x1c\x12\x12\x1c\x12\x97[\n\f\r\n\n\nZ\n\x1a\n\t\x03\x9a2\x14\n,\xa6l\x190\n\x05(T\x81\"\v\x01\xad.\xf3D\x135\x13@\xa1\xb6\x8f\xfe\xfb\xbdoo\xbd\x01\x05\x01\x1e\x01\x05\xbdoY@\x13\x13D\x01,\n\nZ\n\x1a\n\t\t[\t\x1b\xef\t\t[\t\x1b\t\n\nZ\n\x1a\xbb\x1c\x12\x12\x1c\x12\xa0`\x0e\x12\x12\x0e`\x0e\x12\x12EZ\n\n\t\x1b\t[\t\t\n\x1a\x00\x03\x00\x00\xff\x00\a\x00\x06\x00\x00\x04\x00\x14\x005\x00\x00\x01%\x05\x03!\x02 \x04\x16\x12\x10\x02\x06\x04 $&\x02\x10\x126\x016=\x01\a'\x13\x17&'\x17\x05%7\x06\a7\x13\a'\x15\x14\x177\x05\x13\a\x1627'\x13%\x02a\x01\x1f\x01\x1fm\xfe\x9d\x05\x01l\x01L\xf0\x8e\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x04m\x95f\xf0?\x86\x96\xef5\xfe\xe1\xfe\xe15\uf587>\xf0f\x95\x1e\x01F\x8btu\xf6ut\x8b\x01F\x02\xd0\xd0\xd0\xfe\xb0\x04\x80\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\xfbH\xcb\xfb\x03Y\xe0\x01C\f\xceL|\x9f\x9f|L\xce\f\xfe\xbd\xe0Y\x03\xfb˄(\xfe\xd6E''E\x01*(\x00\x00\x00\f\x00\x00\x00\x00\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00I\x00Y\x00i\x00y\x00\x89\x00\xa2\x00\xb2\x00\xbc\x00\x00%\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x03\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x03\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\"&=\x01!\x15\x14\x06#\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x03\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x03\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15!54\x05\x04\x1d\x01!54>\x04$ \x04\x1e\x04\x11\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x11\x15\x14\x06#!\"&=\x01\x01\xc0\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\xc0\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x02@\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\xc0\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\xfd\xc2\x1c&\x02\x02&\x1b\x02\xff\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\xc0\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x02@\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\xc0\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x01\x80\xfd\xfe\xfe\x82\xfe\x82\xfd\xfe\x113P\x8d\xb3\x01\r\x01>\x01\f\xb4\x8dP3\x11\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12&\x1b\xfe\x80\x1b&\xe0\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x01r\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\xfer\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x01r\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x92&\x1b\x81\x81\x1b&\xfd\xe0\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x01r\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\xfer\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x01r\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x01\x8a\r\nh\x02\x01e\n\r\x114LKM:%%:MKL4\xfeW\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x01T\x81\x1b&&\x1b\x81\x00\x00\x00\x00\x05\x00\x00\xff\x00\a\x00\x06\x00\x00\x10\x00\x14\x00%\x00/\x009\x00\x00\x01\x11\x14\x06#\x11\x14\x06#!\"&5\x11\x1363!\x11!\x11\x01\x11\x14\x06#!\"&5\x11\"&5\x11!2\x17\x01\x15!5463!2\x16\x05\x15!5463!2\x16\x02\xc0&\x1a&\x1a\xfe\x00\x1a&\xf9\a\x18\x02\xe8\xff\x00\x04\x00&\x1a\xfe\x00\x1a&\x1a&\x01\xa8\x18\a\xfc\xd9\xfe\xa0\x12\x0e\x01 \x0e\x12\x02\xa0\xfe\xa0\x12\x0e\x01 \x0e\x12\x04\xc0\xfd\x00\x1a&\xfd\xc0\x1a&&\x1a\x02\x00\x03i\x17\xfd@\x02\xc0\xfc\x80\xfe\x00\x1a&&\x1a\x02@&\x1a\x03\x00\x17\x017\xe0\xe0\x0e\x12\x12\x0e\xe0\xe0\x0e\x12\x12\x00\x01\x00\x00\xff\x00\a\x00\x06\x00\x00\x1d\x00\x00\x01\x16\x14\a\x01\x17\a\x06\x04'\x01#5\x01&\x12?\x01\x17\x0162\x16\x14\a\x01\x17\x0162\x06\xdb%%\xfeo\x96\xa0\xa3\xfe;\xb9\xfe\x96\xb5\x01j|/\xa3\xa0\x96\x01\x90&jJ%\xfep\xea\x01\x91&j\x04;&i&\xfep\x96\xa0\xa3/|\xfe\x96\xb5\x01j\xb9\x01ţ\xa0\x96\x01\x91%Jk%\xfeo\xea\x01\x90%\x00\x00\x00\x04\x00\x19\xff\f\x06\xe7\x06\x00\x00\t\x00\x15\x00:\x00g\x00\x00\x01\x14\x06\"&5462\x16\x05\x14\x06#\"&54632\x16\x13\x114&#!\"\x06\x15\x11\x1e\x052636\x17\x16\x17\x16\x176\x172\x1e\x02>\x057\x06\a\x12\a\x06\a\x06'&7\x035.\x01'\x03\x16\a\x06'&'&\x13&'&6\x17\x1e\x01\x17\x11463!2\x16\x15\x1176\x16\x03i\u007f\xb2\u007f\u007f\xb2\u007f\x01\xf6~ZY\u007f\u007fYZ~\xe1@O\xfb\xa8S;+[G[3Y\x1cU\x02D\x1b\x06\x04\x1a#\ao\x05?\x17D&G3I=J\xc6y\xfbTkBuhNV\x04\x01\b!\a\x01\x04WOhuAiS\xfby\x19*'\x04\x0f\x03^C\x04\xe9C^\x15'*\x03\x1cSwwSTvvTSwwSTvv\xfe\xf8\x02\x9bWID\\\xfd_\x17\"\x16\x0f\a\x01\x04\x01\x1c\x06\x03\x19\x1a[\x04\x03\x01\x01\x03\x06\v\x10\x17\x1f\x18\x95g\xfe\xe3\xb4q# /3q\x01F\x01\x02\b\x01\xfe\xaer2/ $r\xb4\x01\x1bg\x95%4\x1b\x02\n\x03\x02\xb6HffH\xfdJ\x0f\x1b4\x00\x00\x04\x00d\xff\x80\x06\x9c\x06\x00\x00\x03\x00\a\x00\x0f\x00\x19\x00\x00\x01\x11#\x11!\x11#\x11\x137\x11!\x11!\x157\x01\x11\x01!\a#5!\x11\x13\x03\x80\x91\x02\x1f\x91\x91\xfd\xfbV\x01F\xd9\x03\x1c\xfeN\xfe\xba\xd9\xd9\xferm\x04N\xfeN\x01\xb2\xfeN\x01\xb2\xfd\b\xfe\x03\x1b\xfb\xe7\xd9\xd9\x04\xaa\xfc\v\xfeN\xd9\xd9\x04\x86\x01!\x00\x00\x00\x00\x05\x00Y\xff\x01\x05\xaa\x05\xfd\x00\x16\x00+\x00?\x00N\x00e\x00\x00%\x15\x02\a\x06\a\x06&'&'&7>\x01727>\x01\x17\x1e\x01'\x06\x0f\x01\x04#&'&'&>\x01\x172\x17\x16\x1f\x01\x1e\x01\x01\x0e\x01\a\x06'&\x03'&676\x17\x16\x17\x1e\x01\x17\x16\x01\x16\a\x06'\x01&76$\x17\x16\x17\x16\x12\x05\x16\a\x06\x05\x06\a7\x06&'&767>\x0176\x17\x1e\x01\x17\x03\x05\x01\x05\f'6\xff#\r\x04\x01\x05\x04<\x97\x01;\x0f1\x19\x18\x1b\x96\x031x\xfe\xed\x11#\x13\f\x05\b\x12*#\r\xbdG,T\x17\x19\x039\a\xa93%\x1a\x0e\xaa/\x0e\x05\x11#0\x01v\xcbN\b\x1c\xfdZ\x05;:8\xfe\x86\b\x1b)\x01M:(\t\x03&\x02\x9b\x03\x1d\x0f\xfe\xc6C\x18\x01\x17.\x0e\x1e\x1e\x01J}2\t\x1c%0\x96\x06\xd9\u007f\xfe\xdc\r \b\t^*\x0f\x15\f\x0e\nJ\xb3F\x13\v\t\n&\xe47\x0f'X\x02\"\x192L\xb5D\x02M\x1d\x12\"\t+\xfe\xbc6\xd6\x14\x0e\x15\n\x01\x15M\x152\x15+\x11\x01'B\x1b\a\x16\x02Qf\x14\x11X\x02V#\x1b+]\x0f\n#\x12\xfd\xc1\xc8'\x14\nL\x0f\b\x02\x06\x14\x16/(\x01e\xabB\x06\x13\x11\x17\xdd9\x00\x00\x00\n\x00\x00\x00\x00\b\x00\x05\x80\x00\x03\x00\a\x00\v\x00\x0f\x00\x13\x00\x17\x00\x1b\x00#\x00,\x008\x00\x00\x01!\x11!\x13\x15!5\x01\x11!\x11\x01\x15!5\x01\x15!5\x01\x15!5\x01\x15!5\x01\x11#\x11\x14\x1626%\x11!\x11\x14\a!26\x13\x11\x14\x06#!\"&5\x11!5\x04\x00\xfe\x80\x01\x80\x80\xfd\x80\x02\x80\xfd\x80\x05\x00\xfe\x00\x02\x00\xfe\x00\x02\x00\xfe\x00\x02\x00\xfe\x00\xfc\x00\x80&4&\x06\x80\xfa\x00\v\x05\xcb\x1a&\x80pP\xf9\x80Pp\x01\x00\x04\x00\xfe\x80\xff\x00\x80\x80\x03\x00\xfd\x80\x02\x80\xfd\x00\x80\x80\x01\x00\x80\x80\x01\x00\x80\x80\x01\x00\x80\x80\xfc@\x03\xc0\xfc@\x1a&&\x1a\x04@\xfb\xc0!\x1f&\x04\xda\xfb@PppP\x04@\x80\x00\x04\x00*\x00\r\a\xd6\x05\x80\x00\t\x00\x1f\x009\x00Q\x00\x00$\"&5462\x16\x15\x147\".\x01\"\x0e\x01#\"&547>\x012\x16\x17\x16\x15\x14\x06\x01\"'.\x01#\"\x0e\x03#\"&5476$ \x04\x17\x16\x15\x14\x06\x13\"'&$ \x04\a\x06#\"&5476$ \x04\x17\x16\x15\x14\x06\x04\x14(\x92}R}h\x02L\u007f\x82\u007fK\x03\x12\x97\nN\xec\xe6\xecN\n\x97\x00\xff\v\f\x88\xe8\x98U\xab\u007fd:\x02\x11\x96\n\x84\x01x\x01\x80\x01x\x84\n\x96\xfe\v\v\xb3\xfe\u007f\xfe8\xfe\u007f\xb3\v\v\x11\x97\n\xbb\x02\x04\x02\x1a\x02\x04\xbb\n\x97\r\x93\x14 ,, \x14|2222\x96\x12\r\nMXXM\n\r\x12\x96\x01\x10\bic,>>,\x96\x12\f\n\x84\x92\x92\x84\n\f\x12\x96\x01\x0f\t\x9d\x9f\x9f\x9d\t\x96\x12\r\n\xba\xcc̺\n\r\x12\x96\x00\x00\r\x00\x00\xff\x00\x06\x80\x06\x00\x00\a\x00\x0f\x00\x17\x00\x1f\x00'\x00/\x007\x00?\x00K\x00S\x00c\x00k\x00{\x00\x00\x044&\"\x06\x14\x162$4&\"\x06\x14\x162\x004&\"\x06\x14\x162\x004&\"\x06\x14\x162\x004&\"\x06\x14\x162\x004&\"\x06\x14\x162\x004&\"\x06\x14\x162\x004&\"\x06\x14\x162\x01\x114&\"\x06\x15\x11\x14\x1626\x004&\"\x06\x14\x162\x01\x114&#!\"\x06\x15\x11\x14\x163!26\x104&\"\x06\x14\x162\x13\x11\x14\x06#!\"&5\x11463!2\x16\x01\x80KjKKj\x01\xcbKjKKj\xfe\xcbKjKKj\x03KKjKKj\xfe\xcbKjKKj\xfe\xcbKjKKj\x03KKjKKj\xfe\xcbKjKKj\x03KLhLLhL\xfe\x80KjKKj\x01\xcb&\x1a\xfb\x00\x1a&&\x1a\x05\x00\x1a&KjKKj\xcbL4\xfa\x804LL4\x05\x804L5jKKjKKjKKjK\x01\xcbjKKjK\xfe\xcbjKKjK\x01\xcbjKKjK\x01\xcbjKKjK\xfe\xcbjKKjK\x01\xcbjKKjK\xfd\x80\x01\x804LL4\xfe\x804LL\x02\xffjKKjK\x01\xc0\x01\x00\x1a&&\x1a\xff\x00\x1a&&\xfe\xa5jKKjK\x03\x00\xfa\x004LL4\x06\x004LL\x00\x02\x00\t\xff\x00\x05\xef\x06\x00\x00'\x00E\x00\x00\x01\x16\a\x02!#\"\x06\x0f\x01\x03\a\x0e\x01+\x01\"&7>\x0376;\x01\x167676767>\x01\x16\x17\x16'\x14\a\x06\a\x06\a\x14#'\"\a\x06\x03\x06#!\"&7\x13>\x013!2\x16\x17\x1e\x01\x05\xef\x12\x16W\xfe\",\x19&\x05\x047\x02\x05'\x19\xfb\x15\x18\x03\t#\x12$\t\x05&\x83\x85g\xafpf5\x18\v\x01\x03\x04\x04O\x99.P\xdeq\x8bZZd\x12\x02S\x01\v\xfe\xd9\x16\x1d\x03\xe8\x05-\x1d\x02V\"\u007f0kq\x03zTx\xfeD!\x1a\x13\xfe\xa6\x0f\x1a!\x1e\x158\xe0p\xdf8%\x02\x17'i_\x97F?\x06\x03\x01\x03;\xb3k\x81\xe9R(\x02\x01\x01`\b\xfd\xf6\n!\x16\x05\xbf\x1d&\x1a\x13)\xa4\x00\x00\x04\x00'\xff\x00\a\x00\x06\x00\x00\n\x00\x12\x00\x19\x00(\x00\x00\x012\x17\x00\x13!\x02\x03&63\x01\x06\a\x02\x0367\x12\x13\x12\x00\x13!\x02\t\x01\x10\x03\x02\x01\x02\x03&63!2\x16\x17\x12\x01\xb9!\x13\x01\n`\xfeB\u007f\xf0\f\x12\x14\x03\xa41LO\xb1(\x04\xd3\xe1\xeb\x01+#\xfe=)\xfe\x00\x04heC\xfe\xdc\x19Q\x04\x13\x10\x01g\x15#\x05s\x03`\x1a\xfe\x94\xfef\x01\xb9\x014\x10#\xfe\x9b\xc7\xc2\x016\x01\x1c\xdd\xe4\xfe\xac\x01\x8f\xfe\xbc\xfd\x13\xfeq\x02\x99\x03'\xfd\xc0\xfeX\xfe|\x020\x02\v\x01-\x01\x1b\x10\x19\x1a\x14\xfeg\x00\a\x00\x00\xff\x80\t\x00\x05\x80\x00\b\x00\x0f\x00\x18\x00\x1c\x00>\x00I\x00Y\x00\x00\x01#6?\x01>\x017\x17\x05\x03&#!\a\x04%\x03'.\x01'\x133\x01\x033\x13#\x05&#\"\x06\a\x06\x17\x1e\x01\x15\x14\x06#\"/\x01\a\x163\x16674'.\x0154636\x1f\x01%#\"\a\x03373\x16\x173\x13\x11\x14\x06#!\"&5\x11463!2\x16\a\xb7\x8a\x0e4\x03\x04\f\x03\f\xfa\x82:\v@\xfe\xf4\x02\x017\x01\x0f\xa2\x11\x1avH\x87\xaf\x01\x05%\xa6h\xa6\x02\x98EP{\x9c\x01\x01\x920&<'VF\x16\x17Jo\x82\x9d\x02\x8c1,1.F6\x0f\x01\xc0\x80A\x16\xf6\xae#\xd4\x05\x0f\x9a\x80L4\xf8\x004LL4\b\x004L\x02\"%\x8e\t\n \n7x\x01'6\rO\\\xfeJYFw\x1d\xfe\x02\x02\x81\xfd~\x02\x82\x10\x1bv^fH\x17$\x15\x1e !\v\x90\"\x01xdjD\x19\"\x15\x16!\x01\x19\b\x9b6\xfd\xb4`\x16J\x03\xc2\xfb\x004LL4\x05\x004LL\x00\x18\x00\x00\xff\x80\t\x00\x05\x80\x00\x11\x00\x19\x00+\x003\x00@\x00G\x00X\x00c\x00g\x00q\x00z\x00\x9c\x00\xb8\x00\xc7\x00\xe5\x00\xf9\x01\v\x01\x19\x01-\x01<\x01J\x01X\x01{\x01\x8b\x00\x00\x01&#\"\x0e\x02\x15\x14\x1e\x02327&\x02\x127\x06\x02\x12\x176\x12\x02'\x16\x12\x02\a\x1632>\x0254.\x02#\"\x0135#\x153\x15;\x025#\a'#\x1535\x1737\x03\x15+\x015;\x01\x153'23764/\x01\"+\x01\x15353$4632\x16\x15\x14\x06#\"$2\x17#\x04462\x16\x15\x14\x06#\"6462\x16\x15\x14\x06\"\x17\"'\"&5&547476125632\x17\x161\x17\x15\x16\x15\a\x1c\x01#\a\x06#\x06%354&'\"\a&#\"\a5#\x1535432\x1d\x0135432\x15\x173=\x01#\x15&#\"\x06\x14\x1632?\x014/\x01&5432\x177&#\"\x06\x15\x14\x1f\x01\x16\x15\x14#\"'\a\x16326\x17'\x06#\"=\x0135#5#\x15#\x153\x15\x14327\"\x06\x15\x14\x16327'\x06#\"'354&3\"\a5#\x1535432\x177&\x16\x14\x16327'\x06'\"&4632\x177&#\"\x173=\x01#\x15&#\"\x06\x14\x1632?\x01\"\a5#\x1535432\x177&\x173=\x01#\x15&\"\x06\x14\x1632?\x01\a\"#\x06\a\x06\x15\x06\x15\x14\x17\x14\x17\x1e\x013274?\x0167654'&'4/\x01\"&\x01\x11\x14\x06#!\"&5\x11463!2\x16\x04_\x80\x99g\xbd\x88QQ\x88\xbch\x99\x80\x83^_\xa3~\\[\u007f\u007f[\\]\x82_^\x83\x80\x99h\xbc\x88QQ\x88\xbdg\x99\x02e\a\x11\a\x03\x1d\x04\x05\x06\x06\x05\x03\x06\x04\x05\b\x02\x03\x03\x02\x03\x04\x01\x01\x01\x01\x01\x01\x02\x01\x06\x03\x01\xfb\x16\x16\x13\x12\x16\x16\x12\x13\x01\xa5<\x05F\x01\x87\x16$\x17\x16\x13\x12\xfa\x17$\x17\x17$\x87\x02\x02\x01\x04\x01\x01\x02\x01\x02\x02\x02\x03\x01\x04\x02\x01\x01\x01\x01\x02\x02\x01\xfa\xbc\x1e\x1d\x19 \x0f\x0e\x1f\x18\x0f\x1e\x1e!\x1e\x1d!\x1e\xa6\x1d\x1d\x11\x1a\x1d&&\x1d\x1c\x0f\xb2/\x0e\x17\x19\x17\x14\f\x16!\x1a\x1e/\r\x18\x1f\x19\x14\r\x19!\x1d!\x82\b\r\r\x1300\x1e\x1c\x1c/\x15e\x1d&'\x1e!\x16\x0e\x12\x15\"\ae$\x83\x17\f\x1e\x1e\x1d\n\b\t\t\x12'!\x1d\x13\x0e\x12\x11\x12\x17\x17\x12\x13\x10\x0e\x14\x1c!\xce\x1e\x1e\x0f\x1b\x1d''\x1d\x1c\x0e\x85\x17\f\x1d\x1d\x1d\n\b\t\b\u007f\x1d\x1d\x0f8''\x1c\x1d\x0eN\x02\x02\x01\x02\x02\x03\x01\x01\x03\x02\x04\x03\x04\x02\x02\x02\x01\x02\x01\x01\x01\x02\x02\x02\x01\x04\x01gL4\xf8\x004LL4\b\x004L\x04\xabUQ\x88\xbcgh\xbc\x88QUk\x01=\x01(\x14\x18\"\x06\x02\x04\n\x0f\v\x18\x0e\x18\x14!\x06\x02\x04\n\x11\x0e\x17\x11\x18\x0e\x19\a\x16=\x1b))\x1b=2\x8e(\x1f '\x13\x16\x0f!\f '\x14\x10\x87L#\x04\x1c\x04(>(\x10\x18\r\x01\x18&\x18\f\x18\x10\x8bDC\x10\x14(>(\x14z\x14\x10\x87L#\x04\x1c\x04\x8bDzG\x14)<)\x14\x03\x01\x01\x02\x01\x03\x02\x04\x03\x02\x02\x02\x02\x02\x01\x01\x01\x01\x01\x03\x02\x03\x04\x02\x01\x03\x01\x01\x01\x01\x04\xe5\xfb\x004LL4\x05\x004LL\x00\x00\f\x00\x00\xff\x80\t\x00\x05\x80\x00\n\x00\x11\x00\x1b\x00\x1f\x00B\x00W\x00b\x00j\x00q\x00}\x00\x8a\x00\x9a\x00\x00\x01\x14\a\x06+\x01532\x17\x16%\x14+\x01532\x054&+\x01\x113276\x173\x11#\x054&'.\x0154632\x177&#\"\x06\x15\x14\x16\x17\x16\x17\x16\x15\x14\x06#\"'\a\x16326\x055\x06#\"&54632\x175&#\"\x06\x14\x1632\x01\x11\x0e\x01\f\x02\x05!26\x004&\"\x06\x14\x162%\x13#\a'#\x13735#535#535#\x013'654&+\x01\x11353\x01\x11\x14\x06#!\"&5\x11463!2\x16\x019$\x1d<\x11\x11=\x1c$\x06\xf0@\x13\x14?\xf9SdO__J-<\x1eAA\x01@)7\x1d\x15\x1b\x15\x1d\x18\")9,<$.%\b\x13\x1c\x160\x17*,G3@\x01\x16%)1??.+&((JgfJ*\x04\xf7A\x9f\xfe\xc4\xfe\xa9\xfe\x14\xfe\xfe\x06!\x1a&\xfc\xadj\x96jj\x96\x01\x02\x90GZYG\x8eиwssw\xb8\x01\x87PiL>8aA\t\x01!M7\xf8\b7MM7\a\xf87M\x02\xf73!\x1a\xdc\x1b\x1f\r4erJ]\xfe\xb3&3Y\x01M\xe8(,\x14\n\x12\x0e\x10\x15\x1b,%7(#)\x10\r\x06\f\x16\x14\x1b,(@=)M%A20C&M\x14e\x92e\xfd\xb7\x02\x0f(X\x92\x81\x8c0&\x02Ėjj\x96j\b\x01V\xe0\xe0\xfe\xaa\t8Z8J9\xfe\xb3\x8c\x10N/4\xfe\xb3\x85\x02$\xfb\f8NN8\x04\xf48NN\x00\x00\x00\x00\x12\x00\x00\xff\x80\t\x00\x05\x80\x00\x02\x00\v\x00\x0e\x00\x15\x00\x1c\x00#\x00&\x00:\x00O\x00[\x00\xce\x00\xe2\x00\xf9\x01\x05\x01\t\x01$\x01?\x01b\x00\x00\x133'\x017'#\x153\x15#\x15%\x175\x174+\x01\x1532%4+\x01\x1532\x014+\x01\x1532\x053'%\x11#5\a#'\x15#'#\a#\x133\x13\x113\x177\x01\x14\x0e\x04\"&#\x15#'\a!\x11!\x17732%\x15#\x113\x15#\x153\x15#\x15\x01\x15\x14\x06#!\"&5\x11373\x1735\x1737\x15!572\x1d\x01!5\x1e\x026373\x1735\x173\x11#\x15'#\x15'#\"\a5#\x15&#!\a'#\x15'#\a\x11463!2\x16\x15\x11#\"\a5#\"\a5!\x15&+\x01\x15&+\x01\a'!\x11!7\x1735327\x153532\x16\x1d\x01!27\x1532%\x14\x06\a\x1e\x01\x1d\x01#54&+\x01\x15#\x1132\x16\x01\x14\x06\a\x1e\x01\x1d\x01#46.\x03+\x01\x15#\x11\x172\x16\x01\x15#\x113\x15#\x153\x15#\x15\x01\x11#\x11\x01\x14+\x0153254&\".\x01546;\x01\x15#\"\x15\x14\x166\x1e\x017\x15\x06+\x0153254&\x06.\x02546;\x01\x15#\"\x15\x14\x1e\x01\x03\x11#'\x15#'#\a#\"54;\x01\x15\"&\x0e\x04\x15\x14\x16;\x0173\x13\x113\x175wY-\x02AJF\xa3\x8e\x8e\x01=c\xbd(TS)\x01!*RQ+\xfe\xea*RQ+\x01\xcbY,\xfc\x16B^9^\x84\x19\x87\x19Ft`njUM\x02\x98\v\x11\x1c\x18'\x18)\t~PS\xff\x00\x01\x04PR\xcfm\xfe\xdd\xd9٘\x94\x94\x05\xd4M7\xf8\b7Mo\x197\x19\xda\x13q\x14\x02\x1d\n\n\x01\x17\x17@)U\t\x198\x19\xe3\"\xb6\xb4\x19\xb9\x17\xf9E(\xac\x181\xfd\x8c++\xc6\x16\xa9NM7\a\xf87Mx3\x1e\xb17\x17\xfe\xc4\x1f8\xd1\x17D\xea62\xfe\xa3\x01W74\xd3\x15;\x1f\xae\b\b\x04\x02\x119\x1f\xa8<\xfd-\x18\x16\x19\x12A\x18\"EA\x9a0:\xfe\xeb\x19\x15\x1a\x11A\x01\x01\x05\f\x17\x12F@\x991:\x02\x11\xd8ؗ\x94\x94\xfe\xedB\x02\xf7f~~\"\"12\"4(\x82w$#11#\xef\x18@}}!\x19%+%\x195(\x81v$:O\x94\\z\x84\x1a\x86\x19K\x81\x85?\a*\x0f\x1f\f\x11\x06\x1b$\x1d\\amcr\x03Vl\xfd\x86OO176Nn\xd9\x022\x16326\x05\x136&+\x01\"\a&#\"\x06\x15\x14\x163267\x06\x15\x14;\x012\x004&+\x01\"\x0f\x01'&+\x01\"\x06\x15\x14\x1e\x01\x17\x06\x15\x14;\x0127\x01%4&+\x01\"\a\x03\x06\x16;\x012?\x01>\x022\x16326\x05\x136&+\x01\"\a&#\"\x06\x15\x14\x163267\x14\x06\x15\x14;\x012\x1354+\x01\"\a\x03\a\x14\x16;\x0127\x01\x0e\x01#\a76;\x012\x16\x01\x11\x14\x06#!\"&5\x11463!2\x16\x02\xe93%\x1d#2%\x1c%\x03\x11,, \x11\x02\v\x12\x16\x1a\x18\x01_3$\x1d$2%\x1c%\xfa\xa8M>\xa0\x13\x02A\x01\b\x06L\x14\x02\x12\x01\f\x12\x10\x16\x03Vb\x015)\x01\b\x06L\x0e\x03\x1bDHeE:\x1c<\x12\x04\rE\x13\x01\xc2\b\x05M\v\aj,\x05\x11K\x05\b'-\x01R\rM\v\a\x00\xff\x01~M>\x9f\x14\x02A\x01\b\x06R\f\x04\x12\x01\f\x12\x10\x16\x03Vb\x015)\x01\b\x06L\x0e\x03\x1aEHeE:\x1d<\x11\x04\rE\x13\xdd\rJ\v\x02A\x01\b\x06B\x13\x02\xf9I\x05*'!\x11\x02\v\x13($\arL4\xf8\x004LL4\b\x004L\x02v%1 \x1c%3!x*\x1e\x01k\v\x04\x15\xa9$2 \x1c%3!\x8e;5\x13\xfeh\x06\n\x13n\b\n\x03\x02a\xe2\x01\x05\x06\n!(lI;F\x18\x14\f\t\x10\x01\x15\n\t\n\x9c\x96\x10\t\x05\x02r\x84\x04p\b\r\n\x01p8;5\x13\xfeh\x06\n\rt\b\n\x03\x02a\xe2\x01\x05\x06\n!(lI;F\x18\x14\x01\x10\x04\x10\x01\xac\x01\x0e\v\xfe`\x02\x05\t\x13\x01\x13#\x16\x01k\v\x17\x01\xdf\xfb\x004LL4\x05\x004LL\x00\x00\x00\n\x00\x00\xff\x80\t\x00\x05\x80\x00\n\x00\x0f\x002\x00H\x00W\x00[\x00l\x00t\x00\x8b\x00\x9b\x00\x00\x01\x14\a\x06#\"'5632\x05#632\x054&'.\x015432\x177&#\"\a\x06\x15\x14\x16\x17\x1e\x01\x15\x14#\"&'\a\x163276\x017#5\x0f\x033\x15\x14\x17\x163275\x06#\"=\x01\x055&#\"\x06\a'#\x113\x11632\x133\x11#\x054'&#\"\a'#\x1175\x163276\x004&\"\x06\x14\x162\x014'&#\"\x06\x15\x14\x17\x16327'\x06#\"'&'36\x13\x11\x14\x06#!\"&5\x11463!2\x16\x06=\x15\x13!\x17\x12\x1d\x1c9\x01\xb6n\x0623\xf9\xecBD$ &:B\x12CRM.0AC'\x1f0\x1dR\x1f\x12H`Q03\x01'\x13`\x81\x12.\x11>,&I / \f*\x01\x89\x0f\r /\n\n\x83\x96\x1a8\x10/\x96\x96\x02n-(G@5\b\x84\x96$ S3=\xfe,.B..B\x03\xb002^`o?7je;\x109G+\x14\x17\x05\xf8\x02\x80L4\xf8\x004LL4\b\x004L\x02yE%#\t\xe0\x1eVb\xe9;A\x19\r\x16\x0e\x1a!p &'F:A\x18\x0e\x17\x10\x1f\x19\x12q)%)\x01#o\x87\x15r\bg\xdbT$\x1e\vv\a2\xc5\x19\x8b\x03 \x1e8\xfe)\x012\x1f\xfe\xaf\x01\xd7\xdez948/\xfd{\x19\x97\v8A\x01\xc4B..B/\xfe\xebq?@\x84r\x80<7(g\x1f\x13\x13/\x0e\x02\xb1\xfb\x004LL4\x05\x004LL\x00\x00\x03\x00\x0e\xff\x00\a\xf2\x06\x00\x00\v\x00\x17\x00?\x00\x00\x01\x12\x17\x14\x06#!\x14\x06\"&'\x0524#\"&54\"\x15\x14\x16\x01\x16\x06\a\x01\x06&/\x01&6?\x01&5>\x0454\x127&5462\x16\x15\x14\a\x1e\x01\x17\x016\x16\x17\x06\x16=\xedL4\xfe@\x96ԕ\x01\x01\x00\x10\x10;U g\x043\b\x01\n\xf8\xb0\n\x1b\bT\b\x01\n\xba\x132RX='\xea\xbe\b8P8\b|\xbe5\x01\xa2\n\x1b\b\x02\xac\xfe\x9c\xc84Lj\x96\x95j\xaf U;\x10\x10Ig\x06@\n\x1b\t\xf9\xaa\b\x02\n`\n\x1b\b\xa1 \"*\\\x93\xaa\xf2\x8b\x98\x01\x05\x1c\x13\x14(88(\x14\x13\x12\x81]\x01k\b\x02\n\x00\x00\x00\x00\x04\x00\x0e\xff\x00\a\xf2\x06\x00\x00\v\x00\x16\x00&\x00N\x00\x00\x044#\"&54\"\x15\x14\x163\t\x01.\x01#\"\x0e\x02\x15\x10\x01\x14\x06#!\x14\x06\"&'7!&\x037\x12\x01\x17\x16\x06\a\x01\x06&/\x01&6?\x01&5>\x0454\x127&5462\x16\x15\x14\a\x1e\x01\x17\x016\x16\x04\x10\x10;U gI\xfd\xf7\x03m*\xb5\x85]\x99Z0\x04\xc0L4\xfe@\x96ԕ\x01\x95\x02\xf5\xa6=o=\x01CT\b\x01\n\xf8\xb0\n\x1b\bT\b\x01\n\xba\x132RX='\xea\xbe\b8P8\b|\xbe5\x01\xa2\n\x1b\xb0 U;\x10\x10Ig\x01\xeb\x02\xf8Xu?bl3\xfe\x80\xfe@4Lj\x96\x95j\x81\xbb\x01\x10a\xfe\x9c\x04\xa8`\n\x1b\t\xf9\xaa\b\x02\n`\n\x1b\b\xa1 \"*\\\x93\xaa\xf2\x8b\x98\x01\x05\x1c\x13\x14(88(\x14\x13\x12\x81]\x01k\b\x02\x00\x00\x00\x00\x05\x00\x00\xff\x80\x05\x80\x05\x80\x00\x0f\x00\x1f\x00/\x007\x00[\x00\x00%\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126%\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126%\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126\x01!'&'!\x06\a\x05\x15\x14\x06+\x01\x11\x14\x06#!\"&5\x11#\"&=\x01463!7>\x013!2\x16\x1f\x01!2\x16\x02\x00\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x01\x00\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x01\x00\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\xfd\xe0\x01\xc00\a\n\xfe\xc3\n\a\x03o\x12\x0e`^B\xfc\xc0B^`\x0e\x12\x12\x0e\x015F\x0fN(\x01@(N\x0fF\x015\x0e\x12\xa0\x02\xc0\x0e\x12\x12\x0e\xfd@\x0e\x12\x12\x0e\x02\xc0\x0e\x12\x12\x0e\xfd@\x0e\x12\x12\x0e\x02\xc0\x0e\x12\x12\x0e\xfd@\x0e\x12\x12\x03\xeeu\t\x02\x02\t\x95@\x0e\x12\xfcLSyuS\x03\xb8\x12\x0e@\x0e\x12\xa7%44%\xa7\x12\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00,\x00<\x00H\x00\x00\x01\x15\x14\x0e\x02#\"\x0054\x0032\x1e\x03\x1d\x01\x14+\x01\"=\x014&#\"\x06\x15\x14\x16326=\x0146;\x012\x16\x02 \x0e\x02\x10\x1e\x02 >\x02\x10.\x01\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04~Isy9\xcd\xfe\xed\x01\x10\xcb\"SgR8\x10v\x10\x83H\x8c\xb1\xb7\x8eD\x8c\t\x06w\x06\n\xfc\xfe\xfc\xed\xabff\xab\xed\x01\x04\xed\xabff\xab\x01\x91\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01\xcem2N+\x16\x01\x16\xcf\xcb\x01\x10\t\x1b)H-m\x10\x10F+1\xb7\x92\x97\xc50*F\a\t\t\x03+f\xab\xed\xfe\xfc\xed\xabff\xab\xed\x01\x04\xed\xab\xfe\xb7\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0e\x00b\x00\x00\x014&#\"\x0e\x02\x15\x14\x1632>\x01\x05\x14\x0e\x02\a\"\x06#\"'&'\x0e\x01#\"&54\x12632\x16\x17?\x01>\x01;\x012\x17\x16\a\x03\x06\x15\x14\x163>\x045\x10\x00!\"\x0e\x02\x10\x1e\x023276\x16\x1f\x01\x16\a\x06\a\x0e\x01#\"$&\x02\x10\x126$3 \x00\x03\xcck^?zb=ka`\xa0U\x024J{\x8cK\x06\x13\a_/\x1c\x054\x9f^\xa1\xb1\x84\xe2\x85W\x88&\x02\v\x01\t\x05v\x05\b\x05\x02x\x05\x19 \x1c:XB0\xfe\xa4\xfe܂\xed\xabff\xab\xed\x82\xe4\xb1\v\x1a\b)\b\x01\x02\nf\xfb\x85\x9c\xfe\xe4\xcezz\xce\x01\x1c\x9c\x01X\x01\xa8\x02\xf9lz=l\xa6apz\x85\xc7\x11o\xacb3\x02\x015!2BX\xbf\xae\x9d\x01\n\x9bG@\x138\x06\f\v\x05\v\xfd\x9a\x18\x18'\x1a\x01\t'=vN\x01$\x01\\f\xab\xed\xfe\xfc\xed\xabf\x90\t\x02\v1\f\f\r\tSZz\xce\x01\x1c\x018\x01\x1c\xcez\xfeX\x00\x00\x00\x00\x02\x00\x00\xff\x00\a\x00\x06\x00\x00#\x00(\x00\x00\x00\x16\x10\x0f\x01\x17\x16\x14\x0f\x01\x06\"/\x01\x01\x06+\x01\x05'\x13547\x01'&4?\x0162\x1f\x0176\t\x01'\x01\x15\x06D\xbc^\xe1h\n\n\xd2\n\x1a\ni\xfd\xa5%5\xcb\xff\x00@\x80%\x02[i\n\n\xd2\n\x1a\nh\xdf]\xfc\xc5\x02@\xc0\xfd\xc0\x06\x00\xbc\xfe\xf7]\xdfh\n\x1a\n\xd2\n\ni\xfd\xa5%\x80@\x01\x00\xcb5%\x02[i\n\x1a\n\xd2\n\nh\xe1^\xfa@\x02@\xc0\xfd\xc0\xc0\x00\x02\x00\x00\xff\x00\x06\xfe\x06\x00\x00\x10\x00)\x00\x00\x012\x16\x15\x14\a\x00\a\x06#\"&547\x016\x01\x1e\x01\x1f\x01\x16\x00#\".\x025\x1e\x03327>\x04\x06OFi-\xfe\xb4\x85ay~\xb5\\\x02~;\xfc\xba'\x87S\x01\x04\xfe\xf5\xd7{\xbes:\aD8>\x0f)\x0e\x19AJfh\x06\x00]F?X\xfd\x8b{[\xb9\u007f\x80T\x02C6\xfb\xf6Ll\x16G\xd5\xfe\xf4]\xa2\xccv\x052'\"%B];$\x0f\x00\x00\x00\x05\x00\x00\xff\x00\a\x00\x06\x00\x00-\x00o\x00\u007f\x00\x8f\x00\x9f\x00\x00%\x11!\x112>\x017>\x0132\x1e\x01\x17\x1e\x0232>\x017>\x0232\x16\x17\x1e\x022>\x017>\x0132\x16\x17\x1e\x02\x13\x15\".\x01'.\x02#\"\x0e\x01\a\x0e\x02#\"&'.\x02#\"\x0e\x01\a\x0e\x02#\"&'.\x02#\"\x0e\x01\a\x0e\x01#546;\x01\x11!\x11!\x11!\x11!\x11!\x1132\x16\x01\x14\x06#\"&54>\x0452\x16\x05\x14\x06#\"&54>\x0452\x16\x05\x14\x06#\"&54>\x0452\x16\a\x00\xf9\x00-P&\x1c\x1e+#\x18(\x16\x16\x1d$P.-P$\x1e\x15\x17'\x18#+\x1e\x1c&PZP&\x1c\x1e+#\"+\x1e\x1c&P-\x18(\x16\x16\x1d$P-.P$\x1d\x16\x16(\x18#+\x1e\x1d$P.-P$\x1e\x15\x17'\x18#+\x1e\x1c&P-.P$\x1d\x1e+#pP@\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00@Pp\xfb\x00H85K\x13\x1c\"\x1c\x13&Z\x02\x00H85K\x13\x1c\"\x1c\x13&Z\x02\x00H85K\x13\x1c\"\x1c\x13&Z\x80\xfe\x80\x01\x80\x1c\x1b\x18\x1b\x16\x0e\x10\x13\x19\x1a\x1c\x1d\x19\x19\x13\x10\x0e\x16\x1b\x18\x1b\x1c\x1c\x1b\x18\x1b\x16\x16\x1b\x18\x1b\x1c\x01@\xc0\x0e\x10\x13\x19\x1a\x1c\x1c\x1a\x19\x13\x10\x0e\x16\x1b\x19\x1a\x1c\x1d\x19\x19\x13\x10\x0e\x16\x1b\x18\x1b\x1c\x1c\x1a\x19\x1b\x16\xc0Pp\x01\xc0\xfe@\x01\xc0\xfe@\x01\xc0\xfe@p\x03\x10MSK5\x1d,\x18 \x1f:&\x94LMSK5\x1d,\x18 \x1f:&\x94LMSK5\x1d,\x18 \x1f:&\x94\x00\x02\x00\x00\xff\x80\b\x00\x05\x80\x00\x05\x00\v\x00\x00!\x15!\x113\x11\t\x01!\x11\t\x01\b\x00\xf8\x00\x80\x06\x00\x01\x00\xf9\x80\x01\xc0\x02@\x80\x06\x00\xfa\x80\x04\x00\xfc\x80\x02@\x02@\xfd\xc0\x00\x00\x00\x03\x00\x00\xff\x80\x06\xc0\x06\x00\x00\v\x00\x10\x00\x16\x00\x00\t\x01\x06\x04#\"$\x02\x10\x12$3\x13!\x14\x02\a\x13!\x112\x04\x12\x03\x00\x02\"j\xfe\xe5\x9d\xd1\xfe\x9f\xce\xce\x01aѻ\x03\x05xl\xa4\xfd\x00\xd1\x01a\xce\x02\x86\xfd\xdelx\xce\x01a\x01\xa2\x01a\xce\xfd\x00\x9d\xfe\xe5j\x02\xa2\x03\x00\xce\xfe\x9f\x00\x02\x00\x00\xff\x80\b\x00\x05\x80\x00\x05\x00\x1f\x00\x00!\x15!\x113\x11\x01\x11\x14\x06/\x01\x01\x06\"/\x01\x01'\x0162\x1f\x01\x01'&63!2\x16\b\x00\xf8\x00\x80\a\x00'\x10y\xfd\x87\n\x1a\n\xe9\xfe`\xc0\x02I\n\x1a\n\xe9\x01\xd0y\x10\x11\x15\x01\xb3\x0e\x12\x80\x06\x00\xfa\x80\x04\xe0\xfeM\x15\x11\x10y\xfd\x87\n\n\xe9\xfe`\xc0\x02I\n\n\xe9\x01\xd0y\x10'\x12\x00\x00\x01\x00\x00\x00\x00\a\x00\x04W\x00`\x00\x00\x01\x14\x17\x1e\x03\x17\x04\x15\x14\x06#\".\x06'.\x03#\"\x0e\x01\x15\x14\x1632767\x17\x06\a\x17\x06!\"&\x0254>\x0232\x1e\x06\x17\x1632654.\x06'&546\x17\x1e\x01\x17#\x1e\x02\x17\a&'5&#\"\x06\x05\f\n\n\x1e4$%\x01Eӕ;iNL29\x1e1\v ;XxR`\xaef՝\xb1Q8\x1bT\x0f\x1d\x01\x83\xfe\xff\x93\xf5\x88W\x91\xc7iW\x90gW:;*:\x1a`\x89Qs&?RWXJ8\v\x03\xafoNU0\x01\f\x16\x1e\x04\x81\x1a\x1c\x17J1F\x03@\x06#\x1d)\x1b\r\n[\xf1\x92\xc1%6_P\u007fO\x86\x1cQiX(o\xb2`\xa0\xef_?5\x98\"$\x01\x98\x9e\x01\x01\x92iʗ\\&>bd\x86s\x926\xc8aP*< \x1f\x17-;iF\x10\x11n\xa4\x04\x03\x17*\v\x1b-\x05c1\x15\x01\x15B\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00W\x00g\x00\x00\x014'.\x02'4.\x0154632\x17#\x16\x177&'.\x01#\"\x06\x15\x14\x17\x1e\x01\x17\x1e\x03\x1d\x01\x16\x06#\"'.\x05#\"\x0e\x01\x17\x15\x1e\x0232767'\x0e\x01#\"&54632\x16\x17\x1e\a326\x13\x11\x14\x06#!\"&5\x11463!2\x16\x05\x98\xea#$(\t\x04\x021$6\x11\x01\x14\x13]'\n!E3P|\x02\x10ad\x1d(2\x1b\x01S;aF\x179'EO\x80Se\xb6j\x03\x04]\xaem\xba]\x14\v<*rYs\x98\xa4hpt.\b#\x16)$78L*k\x98h\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x01\xe4\xadB\n\r%\x1c\x02\r\v\x02$/\x0f\x0f$G6\n\x1d\x14sP\a\x10`X\x1d\b\x0f\x1c)\x1a\x05:F\x90/\x95fwH1p\xb8d\x01l\xb6qn\x1b\x18mPH\xaeui\xa8kw\x15_:[9D'\x1b\x8b\x02\xe5\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x03\x00\x00\x00\x00\b\x00\x05\x00\x00\x0f\x00\x1f\x003\x00\x00\x004.\x02\"\x0e\x02\x14\x1e\x022>\x01$4.\x02#!\x16\x12\x10\x02\a!2>\x01\x12\x10\x0e\x02#!\".\x02\x10>\x023!2\x1e\x01\x04\x80Q\x8a\xbdн\x8aQQ\x8a\xbdн\x8a\x03QQ\x8a\xbdh\xfe~w\x8b\x8bw\x01\x82h\xbd\x8a\xd1f\xab\xed\x82\xfd\x00\x82\xed\xabff\xab\xed\x82\x03\x00\x82\xed\xab\x02\x18н\x8aQQ\x8a\xbdн\x8aQQ\x8a\xbdн\x8aQZ\xfe\xf4\xfe\xcc\xfe\xf4ZQ\x8a\x01\xa7\xfe\xfc\xed\xabff\xab\xed\x01\x04\xed\xabff\xab\x00\x00\x00\x02\x00\x00\x00\x00\b\x00\x05\x00\x00\x13\x00#\x00\x00\x18\x01>\x023!2\x1e\x02\x10\x0e\x02#!\".\x01\x042>\x024.\x02\"\x0e\x02\x14\x1e\x01f\xab\xed\x82\x03\x00\x82\xed\xabff\xab\xed\x82\xfd\x00\x82\xed\xab\x04\xb2н\x8aQQ\x8a\xbdн\x8aQQ\x8a\x01\xfe\x01\x04\xed\xabff\xab\xed\xfe\xfc\xed\xabff\xab\x91Q\x8a\xbdн\x8aQQ\x8a\xbdн\x8a\x00\x00\x05\x00\x00\x00\x00\t\x00\x05\x00\x00\x0e\x00\x12\x00\x18\x00,\x00\\\x00\x00\x01!\"&?\x01&#\"\x06\x10\x16326'3&'\x05\x01!\a\x16\x17\x04\x10&#\"\a\x13\x16\x06\a\x06#\"'\x03\x06\x15\x14\x16 \x00\x10\x00 \x005467'\x01\x06+\x01\x0e\x01#\"\x00\x10\x0032\x177#\"&463!\x15!'#\"&463!2\x17\x01632\x02\xfa\xfe\xc6(#\x18\xbcAH\x84\xbc\xbc\x84s\xb0\xa3\xba\x129\x01q\x01 \xfe ci\x15\x05\x05\xbc\x84<=\xae\x0f\n\x16\x0f\x15#\x12\xae]\xbc\x01\b\x01<\xfe\xf9\xfe\x8e\xfe\xf9OFA\xfe\x9f\x12!\xc5\x17\xfc\xa8\xb9\xfe\xf9\x01\a\xb9re\x89\xe0\x1a&&\x1a\x01\x80\x01\xb3U\xde\x1a&&\x1a\x01\x00!\x14\x01\v[e\xb9\x01\x80F \xfb\x1f\xbc\xfe\xf8\xbc\x91\xefU?\x94\x01\x80\x84g\x95\xc4\x01\b\xbc\x18\xfe\xfc\x174\x0e\v\x1d\x01\x04_\x82\x84\xbc\x01\xf9\xfe\x8e\xfe\xf9\x01\a\xb9a\xad?b\xfe+\x1a\xa4\xdc\x01\a\x01r\x01\a7\xb7&4&\x80\x80&4&\x1c\xfep,\x00\x00\x05\x00\x00\xff\x00\x06\x00\x06\x00\x00\a\x00\x0f\x00\x1f\x00+\x00K\x00\x00\x004&\"\x06\x14\x162$4&\"\x06\x14\x162\x13\x03.\x01#!\"\x06\a\x03\x06\x163!26\x024&#!\"\x06\x14\x163!2\x01\x11#\x15\x14\x06\"&=\x01!\x15\x14\x06\"&=\x01#\x1147\x13>\x01$ \x04\x16\x17\x13\x16\x01\x80KjKKj\x04KKjKKj\x1dH\x05#\x17\xfcj\x17#\x05H\x05&\x1e\x04&\x1e&\xe7\x1c\x14\xfd\x80\x14\x1c\x1c\x14\x02\x80\x14\x01\xac\x80KjK\xfd\x00KjK\x80\x19g\t\xb1\x01\x1b\x01V\x01\x1b\xb1\ti\x17\x01\vjKKjKKjKKjK\x02\f\x01\x80\x17\x1d\x1d\x17\xfe\x80\x1e..\x02n(\x1c\x1c(\x1c\xfd[\xfd\xa5\x805KK5\x80\x805KK5\x80\x02[po\x01\xc6Nv<\x02\x01\x14\x06+\x01\x16\x15\x14\x02\x06\x04#\"\x00'#\"&546;\x01&54\x126$32\x00\x1732\x16\x05\xb72$\xfdB$22$\x02\xbe$\x01\b\x17\xfc*$22$\x03\x8cX\xfeڭ\xb1\xfeӯ\x17\x03\xd6$22$\xfctX\x01'\xad\x84\xf2\xaeh\x01s2$\x83\x11\x83\xdc\xfeϧ\xf6\xfekc\xbd$22$\x84\x11\x83\xdc\x011\xa8\xf5\x01\x95c\xbc$2\x02\xe3F33F3VVT2#$2\x8f\xa8\xaf\xfeԱVT2#$2\x8f\xa8g\xaf\xf1\x01\x84#2UU\xa7\xfe\xcf݃\x01\n\xd92$#2UU\xa7\x011݃\xfe\xf6\xd92\x00\x00\x06\x00\v\xff\x00\x04\xf5\x06\x00\x00\a\x00\x0f\x00\x1b\x00,\x00u\x00\xa3\x00\x00\x01\x03\x17\x1254#\"\x01\x16\x1767.\x02\x01\x14\x13632\x17\x03&#\"\x06\x03\x14\x1e\x0132654'.\x03#\"\x06\x03\x14\x17\x1e\x013276\x114.\x01'&$#\"\a\x06\x15\x14\x1e\x047232\x17\x16\x17\x06\a\x06\a\x0e\x01\x15\x14\x16\x15\a\x06\x15&'\x06#\x16\x15\x14\x06#\"&547\x16\x17\x1632654&#\"\x06\a467&54632\x17\x0254632\x13\x16\x17>\x0532\x16\x15\x14\x03\x1e\x03\x15\x14\x02\x0e\x01#\"'&\x02\x03\xb9ru\xa5&9\xfe\x8c\x1e\x03%\"\f*#\xfe͟\x11 \x0fO%GR\x9f=O&\x0e^\xaa\xfc\x98op\x95\xda\x04\x86\xfe\xb8\x15\x01\xc3C8\xfcpP\b*\x19\x02\a\a\x03\x85b\xfeY\n\x05\x01_\xdc#\xfc\xf5$\xa6\x8c\x1a\x0e\x18N Pb@6\xfe\x9d)?\x91\xa4\xaa\xa9\x01\x02+0L\x1215\v\x05\x1e\"4\x1c\x13\x04\x04\x02\x13\x13$\x1c\x1a\x16\x18.\x88E\x1fs\x1e\f\f\x02\n\xce\x02\a\x0e5I\x9cQ\"!@\fh\x11\f\"\xdeY7e|\x1aJ\x1e>z\x0f\x01\xceiPe\xfd\xbb\x11\x06\x10\u007fn\x91eHbIl\xfeF\x0f>^]@\x96\xfe\xfc\xben*9\x01\r\x00\x00\x00\x00\x04\x00\x00\xff\x80\b\x00\x05\x80\x00\x1a\x006\x00[\x00_\x00\x00\x013\x0e\x01#\"&54632\x16\x17#.\x01#\"\x06\x15\x14\x1e\x0232%3\x0e\x01#\"&54632\x16\x17#.\x01#\"\x06\x15\x14\x1e\x02326%4&'.\x02'&! \a\x0e\x02\a\x0e\x01\x15\x14\x16\x17\x1e\x02\x17\x16\x04! 7>\x027>\x01\x13\x11!\x11\x03\x11\xcf\x0e\xa9\x82\xa2\xb9\xba\x8c\x94\xa8\r\xcb\x05=39?\n\x1a6'_\x02\xd6\xce\x0e\xa8\x82\xa2\xb9\xba\x8c\x94\xa8\r\xcc\x04>29?\n\x1a5'17\x01m\x1f-\x06\x0f\x1c\x02V\xfd\x9d\xfd\x8fU\x05\x19\x11\x06-\x1e\x1e-\x06\x12\x17\x06,\x01\x87\x01\x13\x02bW\x05\x18\x11\x05.\x1e\xc0\xf8\x00\x02\x10\x9e\xb5\xe8\xc8\xc2뮠@Fyu0HC$\x8b\x9e\xb5\xe8\xc8\xc2뮠@Fyu0HC$L\xb6\xcf\xc8=\b\f\x12\x02??\x04\x0f\r\b<\xc7\xd1\xd0\xc7=\b\x0e\x0e\x05! A\x04\x0e\x0e\t<\xc6\x03\xcb\xfa\x00\x06\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x05`\x05\x80\x00\x1d\x00;\x00\x00\x01\x11\x14\x06+\x01\"&5\x114&#!\x11\x14\x06+\x01\"&5\x11463!2\x1e\x01\x01\x11\x14\x0e\x01#!\"&5\x1146;\x012\x16\x15\x11!265\x1146;\x012\x16\x03\xe0\x12\x0e\xa0\x0e\x12\xa0p\xfe\xf0\x12\x0e\xa0\x0e\x12\x12\x0e\x01Ї\xe4\x85\x01\x80\x85\xe4\x87\xfe0\x0e\x12\x12\x0e\xa0\x0e\x12\x01\x10p\xa0\x12\x0e\xa0\x0e\x12\x03\x90\xfe\x10\x0e\x12\x12\x0e\x01\xf0p\xa0\xfb\x80\x0e\x12\x12\x0e\x05@\x0e\x12\x85\xe4\x01I\xfc\x90\x87\xe4\x85\x12\x0e\x03\xc0\x0e\x12\x12\x0e\xfd\x00\xa0p\x03p\x0e\x12\x12\x00\x00\x00\x04\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00>\x00S\x00c\x00\x00\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x0554&+\x01\"\a&+\x01\"\x06\x1d\x01\x14;\x012=\x0146;\x012\x16\x1d\x01\x14;\x012=\x0146;\x012\x16\x1d\x01\x14;\x012%54&#!\"\x06\x15\x11\x14;\x012=\x01\x16;\x0126\x13\x11\x14\x06#!\"&5\x11463!2\x16\x05\x1f\x1b\x18\xca\x18\x1c\x1c\x18\xca\x18\x1b\xfe\x16A5\x85D\x1c\x1cD\x825A\x157\x16\x1b\x19^\x18\x1c\x156\x16\x1c\x18a\x18\x1b\x167\x15\x02MB5\xfe\xf85B\x167\x15\x1f?\xbf5B~\x88`\xfb\xd0`\x88\x88`\x040`\x88\x02\xb6r\x18\x1c\x1c\x18r\x18\x1c\x1c\xfe\xfa5A44A5\xfa\x16\x16\xe6\x18\x1c\x1c\x18\xe6\x16\x16\xe6\x18\x1c\x1c\x18\xe6\x16v\x9a5AA5\xfef\x15\x15\xb4*A\x02\x9d\xfb\xd0`\x88\x88`\x040`\x88\x88\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x02\x00\t\x00\x19\x00\x00\x01!\x1b\x01!\x01!\x01!\t\x01\x11\x14\x06#!\"&5\x11463!2\x16\x03\x93\xfeړ\xe9\x017\xfe\xbc\xfeH\xfe\xbc\x017\x01\u007f\x02j\xaav\xfc@v\xaa\xaav\x03\xc0v\xaa\x01\xc2\x02'\xfc\x97\x04\x00\xfc\x00\x01:\x02\xa6\xfc@v\xaa\xaav\x03\xc0v\xaa\xaa\x00\x00\x00\x00\x17\x00\x00\xff\x00\b\x00\x06\x00\x00M\x00U\x00a\x00h\x00m\x00r\x00x\x00\u007f\x00\x84\x00\x89\x00\x91\x00\x96\x00\x9c\x00\xa0\x00\xa4\x00\xa7\x00\xaa\x00\xaf\x00\xb8\x00\xbb\x00\xbe\x00\xc1\x00\xcb\x00\x00\x01\x14\x06\a\x03\x16\x15\x14\x06\a\x03\x16\x15\x14\x06#\"'!\x06\"'!\x06#\"&547\x03.\x01547\x03.\x015467\x134&547\x13&54632\x17!62\x17!632\x16\x15\x14\a\x13\x1e\x01\x15\x14\a\x13\x1e\x01\x01!\x01#\x01!62\x01\x16\x15\x14\a\x13\x177\x11'\x06\a\x01!\x17%!\x06\"\x0167'\a#7\x03\x01\x17\x017\x13!\x016\x053\x01!\x11\x17\x16\x03!7\x01\x0f\x0135\a\x16\x11\x14\x16\x15\x14\a\x17\x117\x11\x17\x01/\x01\a\x117'\x06%#\x05\x17\x15\t\x02%'\x11\x05\a3\x01\x17\x13/\x02&=\x01\x03&'\t\x025\x03\x13#\x13\x01\a?\x01\x13&547\v\x01\x176\b\x00\x1a\x14\xcd\x03\x19\x14\xc1\x03!\x18\x19\x10\xfep\x114\x11\xfeq\x11\x1a\x17\"\x04\xc1\x14\x19\x03\xce\x14\x19\x1b\x14\xc7\x01\"\xd1\x04\"\x17\x1a\x12\x01\x8c\x106\x10\x01\x8e\x12\x1a\x17\"\x04\xcf\x17 \a\xbb\x13\x19\xfc'\x01\x85\xfe\xaa\x8f\xfe\xaa\x01h\x12*\xfc[\x01\x02\xd0\x0f\xbc\xbb\r\x10\x02\xa8\xfe|\xbe\x02*\xfe\xe8\x10,\x02\xaf\x01\x04@\x11\x1e\x16\xfc\xfe\xd8?\x01w\x10A\xfeU\x01M\b\xfcp\x05\x01V\xfe\x8b\x04\x0e\x12\x01\x92@\xfe˝\xc1\xa3\xa8\x04\x01\b\xab\x1e\x99\x01)\xdf\xdf\x04Ϳ\x06\x03w\x10\xfd\x93\xd5\xfe\xd7\x017\x01(\xfd{\x88\x01\xe6*U\x01%\xee\x84\x03\x01\x16\b\xd8\x05\b\xfeK\x016\xfc\xc0\xa3\xa3\xa3\xa3\x04=0\x82(\xcf\x02\x03\xab\x81M\x05\x02\x81\x15\x1f\x04\xfe\x9c\t\t\x14\x1f\x04\xfe\xaf\b\b\x17\"\x12\x14\x14\x14!\x18\b\f\x01O\x04\x1f\x14\t\t\x01d\x05\x1f\x14\x15\x1f\x04\x01X\x01\x04\x01$\x0f\x01k\n\b\x18!\x15\x15\x15\x15!\x18\x06\f\xfe\x9a\x01!\x16\r\x0e\xfe\xbc\x04\x1f\xfc\xcd\x01b\xfe\x9e\x10\x03\x1c\x04\t\n\x05\xfe\x98\x06\xc7\x01[\xc2\b\x02\x01\xc0\xc8\xc8\x10\xfbT\x06\x05DOi\x01\n\xfe\xcd@\xfe\x90\x1c\x016\xfe\xa9\x04\x0f\x01b\xfe\xb1\x06\x05\x01xB\x01A\xa6ݽ\xb1\b\x035\x01\x02\x01\x10\r\xb1\x01\r\v\xfeɝ\x01:\xec\xde\b\xfe\xf8J\xc9\x02\f\xe0\xe1+\xfe\xc5\xfe\xc1\x013\x0f\x8d\xfe\xe4\xdd,\x01\x88\xfb\x02p\x05\x01\x15\r\x10\x02\x01x\x01\x04\xfe1\xfe\xb9\x01\xf6\xdf\xfe\xe6\xfc\x89\xfe\xe5\x01\x1b\xe3\xe3F\x01i\n\x04\x01\x0f\x01(\xfd\x9cR\x03\x00\x02\x00\x00\xff\x00\x05\x80\x06\x00\x00\r\x00\x1b\x00\x00\x11463!\x01\x11\x14\x06#!\"&5%'\x114&#!\"\x06\x15\x11\x14\x163\xb7\x83\x02\xe6\x01`\xb7\x83\xfc\xf4\x83\xb7\x04а@.\xfe\x1c.@A-\x03X\x83\xbf\x01f\xfaB\x84\xbe\xbe\x84$\xb4\x01\xa9.BB.\xfe\x14.C\x00\x00\x04\x00\x00\xff\x83\x06\x00\x05}\x00\n\x00\x14\x00\x1e\x00)\x00\x00\x01\x04\x00\x03&54\x12$32\x05\x16\x17\x04\x00\x03&'\x12\x00\x01\x12\x00%\x16\x17\x04\x00\x03&\x05&'\x06\a6\x007\x06\a\x16\x03\xa6\xfe\xc3\xfe\"w\x14\xcd\x01`\xd0R\x01d]G\xfe{\xfd\xc5o]>p\x026\xfe\xa3s\x02\x11\x01c(\x0e\xfe\xdc\xfe@wg\x03\xcf\xc1\xae\x87\x9bm\x01J\xcc\x15PA\x05jy\xfe\x1d\xfe\xc1YW\xd0\x01a͊AZq\xfd\xc1\xfe{HZ\x01\x82\x02:\xfb<\x01d\x02\x14v\\gx\xfe>\xfe\xdb\x0e\x142AT\x17\xcd\x01Kn\x98\x84\xaf\x00\x00\x03\x00\x00\xff\x80\b\x00\x04\xf7\x00\x16\x00+\x00;\x00\x00\x01\x13\"'&#\"\a&#\"\a\x06+\x01\x136!2\x1763 \x012\x16\x17\x03&#\"\a&#\"\a\x03>\x0232\x1767\x03\x06\a&#\"\a\x03>\x0132\x176\x17\ae\x9b\x83~\xc8\xc1└\xe2\xc1Ȁ|\x05\x9b\xe0\x01\x02隚\xe9\x01\x02\xfe\xf1\x81Ν|\xab\xc5\xe0\x96\x96\xe0ū|iy\xb0Zʬ\xac\xf27Ӕ\x98ް\xa0r|\xd1uѥ\xac\xca\x04x\xfb\b9[\x94\x94[9\x04\xf8\u007fjj\xfb\xa69A\x03\xfdN\x8d\x8dN\xfc\x03+,#ll\"\x03\x8b\x04\x97\x9bB\xfcS32fk\x05\x00\x00\x05\x00\x00\xff\xa5\b\x00\x05[\x00\x0f\x00\x1f\x00/\x00?\x00\\\x00\x00%\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126%\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126%\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126%\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126%\x14\x06#!\"&5467&54632\x176$32\x1e\x01\x15\x14\a\x1e\x01\x05\xdc\x1e\x14]\x14\x1e\x1e\x14]\x14\x1e\xfe\xe4\x1e\x14e\x14\x1e\x1e\x14e\x14\x1e\xfe\xdc\x1e\x14e\x14\x1e\x1e\x14e\x14\x1e\xfe\xdc\x1e\x14e\x14\x1e\x1e\x14e\x14\x1e\x05\x88\xec\xa6\xfb$\xa6\xec~i\n\xa1qfN-\x01*\xbd\x95\xfc\x93\x0e\x87\xac\xa5\x02\xdd\x15\x1e\x1e\x15\xfd#\x14\x1e\x1e\x14\x02\x13\x14\x1e\x1e\x14\xfd\xed\x14\x1e\x1e\x14\x01\xad\x14\x1e\x1e\x14\xfeS\x14\x1e\x1e\x14\x01j\x14\x1e\x1e\x14\xfe\x96\x14\x1e\x1e\xa6\xa6\xec\xec\xa6t\xc52\"'q\xa1C\xb7\xea\x93\xfc\x95B8!\xdb\x00\x00\x00'\x00\x00\xff>\x06\x00\x06\x00\x00\x04\x00\t\x00\r\x00\x11\x00\x15\x00\x19\x00\x1d\x00!\x00%\x00)\x00-\x001\x005\x009\x00=\x00A\x00E\x00I\x00M\x00Q\x00U\x00Y\x00]\x00a\x00g\x00k\x00o\x00s\x00w\x00{\x00\u007f\x00\x85\x00\x89\x00\x8d\x00\x91\x00\x95\x00\x99\x00\xa5\x00\xd5\x00\x00\x11!\x11\t\x01%\x11!\x11\t\x015!\x15\x13\x15#5\x17\x15#5\x17\x15#5\x17\x15#5\x17\x15#5\x177\x17\a\x177\x17\a\x177\x17\a\x177\x17\a?\x01\x17\a?\x01\x17\a?\x01\x17\a?\x01\x17\a\x01\x15#5!\x15#5!\x15#5!\x15#5!\x15#5!\x15#5!\x15#5!\x15#5\x01\x15#53\x157\x15#5!\x15#5!\x15#5!\x15#5!\x15#5!\x15#5\x175#53\x15\a53\x15\a53\x15\a53\x15\a53\x15\a53\x15%\"&54632\x16\x15\x14\x06\x01\x14\x1e\x026\x16\x15\x14#\"'#\a\x1632>\x0254.\x01\x06&54>\x0132\x16\x1737.\x06#\"\x0e\x02\x06\x00\xfc\xf8\xfd\b\x05\x9c\xfa\xc8\x02\x95\x02\xa3\xfa\xc8Q%%%%%%%%%?\x0fi\x0f\x1f\x0fi\x0f\x1e\x0fi\x0f\x1f\x0fh\x0fOi\x0fixi\x0fiyi\x0fixi\x0fi\xfcAr\x01\x14s\x01\x15s\x01\x14r\x01\x14r\x01\x14s\x01\x15s\x01\x14r\xfb\xb8%s\xa2s\x01\x15s\x01\x14r\x01\x14r\x01\x14s\x01\x15s\xf0Ns%%%%%%%%%%\xfd\x88\x81\xb8\xb8\x81\x82\xb7\xb7\xfe\xd9'\x0232\x16\x15\x14\a\x06\x04#\".\x0154\x0032\x1e\x0532654&#\"\x06#\"&54654&#\"\x0e\x02#\"&547>\x0132\x16\x15\x14\a6\x05\x96\x01\x04\x94\xd2ڞU\x9azrhgrx\x98S\x9a\xc3Пd\xd8U\x05 \x1c\b\x0e\x15\x017\x03#\"&463!2\x1e\x04\x17!2\x16\x04\xc0&\x1a\x80&4&\x80\x1a&&\x1a\x80&4&\x80\x1a\xfd\xe6KjKKj\x03\xcbKjKKj\xcb \x19\xfb\xec\x01\a\x05\x18\x03\x98\x1a&&\x1a\xfc\x00\x1a&\x16%\x02\xb1\xcc\x1a&&\x1a\x01\x00\x10\x19\x0f\v\x04\a\x01\x04\xb1\x1a&\x03&4&\x80\x1a&&\x1a\x80&4&\x80\x1a&&\x1a\x80\xfd5jKKjKKjKKjK\x03\xc0\xfe\x00\x18%\x03z\a\x1d\x18\n\x100&4&&\x1a\x0e3D\x04\x037&4&\r\x12\x1f\x16%\a&\x00\x00\x00\x00\x04\x00\x00\xff\x80\x06\x80\x05\x00\x00\x17\x00\x1f\x00'\x00S\x00\x00\x004&\"\x0f\x01\x114&\"\x06\x15\x11'&\"\x06\x14\x17\x01\x1627\x01\x00\x14\x06\"&462\x04\x14\x06\"&462\x13\x11\x14\x06\a\x05\x1e\x02\x15\x14\a!2\x16\x14\x06#!\"&54>\x017\x03#\"&463!2\x1e\x04\x17!2\x16\x05\x00&4\x13\x93&4&\x93\x134&\x13\x01\x00\x134\x13\x01\x00\xfd\x93KjKKj\x03\xcbKjKKj\xcb \x19\xfb\xec\x01\a\x05\x18\x03\x98\x1a&&\x1a\xfc\x00\x1a&\x16%\x02\xb1\xcc\x1a&&\x1a\x01\x00\x10\x19\x0f\v\x04\a\x01\x04\xb1\x1a&\x03&4&\x13\x92\x01%\x1a&&\x1a\xfeے\x13&4\x13\xff\x00\x13\x13\x01\x00\xfd\"jKKjKKjKKjK\x03\xc0\xfe\x00\x18%\x03z\a\x1d\x18\n\x100&4&&\x1a\x0e3D\x04\x037&4&\r\x12\x1f\x16%\a&\x00\x00\x00\x00\a\x00\x00\xff\x00\b\x00\x05\x80\x00\x02\x00\x05\x00\t\x00\f\x00\x10\x00\x14\x00&\x00\x00\x13\t\x03!'\x13!\t\x02!%!\x03!\x01!\x01!%\x01\x16\x06\a\x01\x06\"'\x01.\x017\x0163!2\xd4\x02o\xfe\xd4\x01\xe9\x01]\xfdF\x89\xcc\xfe\xfa\xfe\xe0\x03\xfd\x02o\xfe\xbd\xfc\xc2\x02\xaa\xcc\xfe\xee\x02o\x01Z\xfe\xe0\xfe\xfa\x01Y\x01\x80\x0e\x02\x10\xfc@\x12:\x12\xfc@\x10\x02\x0e\x01\x80\x12!\x04\x80!\x03\x00\xfdg\x02\x99\xfc\xfc\x03\x04\x80\x01\x80\xfe\x80\xfc\xe7\x02\x99\x80\x01\x80\xfe\x80\x01\x80f\xfe\x00\x12/\x11\xfc\x00\x14\x14\x04\x00\x11/\x12\x02\x00\x1a\x00\x03\x00\x13\xff\x00\a\xed\x06\x00\x00I\x00\x97\x00\xa0\x00\x00\x0562\x1f\x01\a'\a\x06\"/\x01\a\x06\"/\x01\a\x06\"/\x01\a\x06\"/\x01\a\x06\"/\x01\a\x06\"/\x01\a\x06\"/\x017\x17762\x1f\x01762\x1f\x01762\x1f\x01762\x1f\x01762\x1f\x01762\x1f\x01%\x06\"/\x017\x17762\x1f\x017\x11\x03&6?\x01\x1135!5!\x15!\x153\x11\x17\x1e\x01\a\x03\x11762\x1f\x01762\x1f\x01\a'\a\x06\"/\x01\a\x06\"/\x01\a\x06\"/\x01\a\x06\"/\x01\a\x06\"/\x01\a\x06\"/\x01\x01\x15%\x055#5!\x15\a\x13\x134\x13\x80ZSS\x126\x12SS\x134\x13SS\x134\x13SS\x134\x13SS\x134\x13SS\x134\x13SS\x134\x13\x80ZSS\x134\x13SS\x134\x13SS\x134\x13SS\x134\x13SS\x134\x13SS\x134\x13S\xfa-\x134\x13\x80ZSS\x134\x13S@\xd2\x11\x14\x1e\xb1\x80\x01\x00\x01\x00\x01\x00\x80\xb1\x1e\x14\x11\xd2\x13\x134\x13SS\x134\x13\x80ZSS\x126\x12SS\x134\x13SS\x134\x13SS\x134\x13SS\x134\x13SS\x134\x13S\x01@\x01\x80\x01\x80\x80\xfe\x00\x13\x13\x13\x80ZSS\x13\x13SS\x13\x13SS\x13\x13SS\x13\x13SS\x13\x13SS\x13\x13SS\x13\x13\x80ZSS\x13\x13SS\x13\x13SS\x13\x13SS\x13\x13SS\x13\x13SS\x13\x13Sy\x13\x13\x80ZRR\x13\x13R@\x01%\x01:\x1a=\n:\x01+\x80\x80\x80\x80\xfe\xd5:\n=\x1a\xfe\xc6\xfe\xdb\x12\x13\x13RR\x13\x13\x80ZSS\x13\x13SS\x13\x13SS\x13\x13SS\x13\x13SS\x13\x13SS\x13\x13S\x04\x1a\x80\x80\x80\x80\x80\x80\x00\x00\x00\x04\x00\x00\xff\x80\x05\x80\x06\x00\x00\x03\x00\a\x00C\x00v\x00\x00!\x13/\x01\x01\x13\x0f\x01\x01&'&#\"\a\x06\"'&#\"\a\x06\a\x16\x17\x1e\x01\x17\x1e\t32>\x03;\x012\x1e\x0332>\b7>\x0176\x01\x14\x06#!\"&54>\x037'3&547&547>\x017632\x162632\x17\x1e\x01\x17\x16\x15\x14\a\x16\a3\a\x1e\x03\x02@``\x80\x01\x80\x80\x80`\x01\x00\x02\x02\nVFa\a\x1c\aaFV\n\x02\x02\x02\x02\x02\v\x02\x02\v\x03\f\x05\r\v\x11\x12\x17\r$.\x13\n\r\v\f\v\r\n\x13.$\r\x17\x12\x11\v\r\x05\f\x03\v\x02\x02\v\x02\x02\x01\xa2\x92y\xfc\x96y\x92\t\x1d.Q5Z\xd6\x16\x02\xc2\xd2\x11E$ ,\x1el\x90*%>>%*\x90>*98(QO\xe1!\u007f\xa0\x8f\x00\x03\x00\x00\x00\x00\b\xfd\x05\x00\x00L\x00\\\x00p\x00\x00\x01\x16\x0e\x02'.\x01'&67'\x0e\x01\x15\x14\x06#!#\x0e\x01#\"\x00\x10\x0032\x177&+\x01\"&46;\x012\x1e\x02\x17!3'#\"&7>\x01;\x012\x1f\x0176;\x012\x16\x1d\x01\x14\x06+\x01\x176\x17\x1e\x01\x01267!\"'&7\x13&#\"\x06\x10\x16(\x016\x10&#\"\a\x13\x16\x06\a\x06#\"'\x03\x06\x15\x14\b\xfd\fD\x82\xbbg\xa1\xed\x10\fOOG`n%\x1b\xff\x00E\x17\xfc\xa8\xb9\xfe\xf9\x01\a\xb9LL\x18{\xb5@\x1a&&\x1a\x80N\x86c,\x1d\x02\x00sU\xde\x1e&\x05\x04&\x18\xfd!\x14Fr\x13\x1be\x1a&&\x1a\xb3s\x83\x90\x8f\xca\xf8\xd4s\xb0\x17\xfe\xc6#\x14\x12\x11\x93/,\x84\xbc\xbc\x05\x80\x01\b\xbc\xbc\x84<=\xae\x0f\n\x16\x0f\x15#\x12\xae]\x01\xf4g\xbf\x88L\a\v\xe4\xa0o\xc7GkP\xe4\x82\x1b'\xa4\xdc\x01\a\x01r\x01\a\x1b-n&4&\x1b2\x1d\x16\x80-\x1e\x17\x1e\x1cir\x13&\x1a\x80\x1a&\xac?\x1b\x1a\xd9\xfd\xfb\x91o\x1f \x1f\x01\x15\r\xbc\xfe\xf8\xbc\xbc\x01\b\xbc\x18\xfe\xfc\x174\x0e\v\x1d\x01\x04_\x82\x84\x00\x00\x03\x00\x00\xff\x00\x05\x80\x05\xe0\x005\x00O\x00W\x00\x00!\x14\x0e\x02 .\x0254>\x0276\x16\x17\x16\x06\a\x0e\x04\a\x1e\x042>\x037.\x04'.\x017>\x01\x17\x1e\x03\x01\x11\x14\x06+\x01\x11\x14\x06#!\"&5\x11#\"&5\x11463!2\x16\x02\x14\x06\"&462\x05\x80{\xcd\xf5\xfe\xfa\xf5\xcd{BtxG\x1a,\x04\x05\x1f\x1a:`9(\x0f\x01\x030b\x82\xbfԿ\x82b0\x03\x01\x0f(9`:\x1a\x1f\x05\x04,\x1aGxtB\xfe\x80&\x1a@&\x1a\xff\x00\x1a&@\x1a&K5\x01\x805K`\x83\xba\x83\x83\xba?e=\x1f\x1f=e?1O6#\f\x05\x1f\x1a\x1a,\x04\n\x1b\x18\x17\x10\x04\v\x1f#\x1e\x14\x14\x1e$\x1f\f\x04\x0e\x18\x17\x1b\n\x04,\x1a\x1a\x1f\x05\f#6O\x03O\xfe\x80\x1a&\xfe\x80\x1a&&\x1a\x01\x80&\x1a\x01\x805KK\x01\xa8\xba\x83\x83\xba\x83\x00\x02\x00\x00\xff\x80\a\x00\x05\x80\x00\x1b\x00?\x00\x00\x01!\x0e\x01\x0f\x01\x01\x06\"'\x01&'!267\x1b\x01\x1e\x013267\x13\x17\x16\x01\x14\a!'.\x01\a\x06\a\v\x01.\x01\"\x06\a\x03!&54632\x1e\x02\x17>\x0332\x16\x05\x00\x011\x05\n\x04\x03\xfd\x91\x124\x12\xfd\x90\x05\x10\x01q\x16#\x05F\xbe\x06\"\x16\x15\"\x06\x928\x12\x02'g\xfe\x8fo\b#\x13-\v\x81\xc4\x06#,\"\x05t\xfeYg\xfe\xe0>\x81oP$$Po\x81>\xe0\xfe\x02\x00\x06\t\x03\x04\xfd\xa8\x12\x12\x02Z\x02\x12\x1b\x15\x01\x19\xfde\x14\x1a\x1a\x14\x01\xe5p#\x01\xac\x91\x9b\xdd\x11\x14\x02\x05)\xfeR\x02\xae\x14\x1a\x1b\x15\xfe0\x9b\x91\xdc\xf8+I@$$@I+\xf8\x00\x00\x02\x00\x02\xff\x00\x04\x80\x05\xfc\x00+\x003\x00\x00\x01\x14\x00\a\x1132\x16\x1d\x01\x14\x06+\x01\x15\x14\x06+\x01\"&=\x01#\"&=\x0146;\x01\x11.\x01\x027>\x0276\x04\x12$\x10\x00 \x00\x10\x00 \x04\x80\xfe\xd9\xd9\xe0\x0e\x12\x12\x0e\xe0\x12\x0e@\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\x96\xf3\x81\f\v\x8bᅪ\x01*\xae\xfc\x00\x01\a\x01r\x01\a\xfe\xf9\xfe\x8e\x03\xc0\xdd\xfe\xb9\x18\xfe\xfc\x12\x0e@\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\x12\x0e@\x0e\x12\x01\x04\x10\xae\x01\x12\x9b\x86\xe6\x92\x0f\x13\x92\xfe\xea\x12\xfe\x8e\xfe\xf9\x01\a\x01r\x01\a\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00'\x00/\x00\x00\x012\x16\x15\x11\x14\x06+\x01\"&5\x11\x01\x16\x15\x14\x0e\x02\".\x024>\x0232\x17\x01!\"&=\x01463\x00 \x00\x10\x00 \x00\x10\x05\xc0\x1a&\x12\x0e@\x0e\x12\xfe\x82~[\x9b\xd5\xea՛[[\x9b\xd5u˜\x01~\xfe\xfb\x0e\x12\x12\x0e\xfdg\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\x05\x80&\x1a\xfe`\x0e\x12\x12\x0e\x01\x06\xfe\x81\x9c\xcbu՛[[\x9b\xd5\xea՛[~\x01~\x12\x0e@\x0e\x12\xfa\x80\x01\a\x01r\x01\a\xfe\xf9\xfe\x8e\x00\x00\x00\x00\x02\x00\x00\xff\x00\x04\x80\x06\x00\x00=\x00E\x00\x00\x01\x16\x12\x15\x14\x00\a\x1532\x16\x1d\x01\x14\x06+\x01\x15\x14\x06+\x01\"&=\x01#\"&=\x0146;\x015&\x0054\x127&'&6;\x012\x17\x1e\x012676;\x012\x16\a\x06\x00 \x00\x10\x00 \x00\x10\x03>\x91\xb1\xfe\xd9\xd9`\x0e\x12\x12\x0e`\x12\x0e@\x0e\x12`\x0e\x12\x12\x0e`\xd9\xfeٱ\x91\xa5?\x06\x13\x11E\x15\b,\xc0\xec\xc0,\b\x1d=\x11\x13\x06?\xfd\xa4\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\x04\xc4H\xfe\xeb\xa7\xdd\xfe\xb9\x18\x84\x12\x0e@\x0e\x12`\x0e\x12\x12\x0e`\x12\x0e@\x0e\x12\x84\x18\x01Gݧ\x01\x15H`\xb1\x10\x1b\x14j\x82\x82j\x14\x1b\x10\xb1\xfb\xdc\x01\a\x01r\x01\a\xfe\xf9\xfe\x8e\x00\x02\x00\x02\xff\x00\x05\x80\x06\x00\x00B\x00J\x00\x00\x01463!2\x16\x15\x11\x14\x06+\x01\"&=\x01\a\x16\x15\x14\x00\a\x1532\x16\x1d\x01\x14\x06+\x01\x15\x14\x06+\x01\"&=\x01#\"&=\x0146;\x015.\x01\x0276\x0076\x16\x17%#\"&5\x00 \x00\x10\x00 \x00\x10\x04\x00\x12\x0e\x01 \x1a&\x12\x0e@\x0e\x12\xfe~\xfe\xd9\xd9`\x0e\x12\x12\x0e`\x12\x0e@\x0e\x12`\x0e\x12\x12\x0e`\x95\xf3\x82\f\x10\x01 \xcbv\xdcX\x00\xff\x86\x0e\x12\xfd\x87\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\x05\xe0\x0e\x12&\x1a\xfe\xe0\x0e\x12\x12\x0e\x86\xff\x9e\xc9\xdd\xfe\xb9\x18\x84\x12\x0e@\x0e\x12`\x0e\x12\x12\x0e`\x12\x0e@\x0e\x12\x84\x10\xae\x01\x11\x9b\xcc\x01+\x17\x0eBF\xfe\x12\x0e\xfb`\x01\a\x01r\x01\a\xfe\xf9\xfe\x8e\x00\x00\x02\x00\x00\xff\x00\x06\x80\x06\x00\x00k\x00s\x00\x00\x01463!2\x16\x15\x11\x14\x06+\x01\"&=\x01\a\x16\x15\x14\x00\a\x1532\x16\x1d\x01\x14\x06+\x01\x15\x14\x06+\x01\"&=\x01#\"&=\x0146;\x015&\x00547'\a\x0e\x01/\x01.\x01?\x01'\x15\x14\x06+\x01\"&5\x11463!2\x16\x1d\x01\x14\x06+\x01\x177>\x01\x1f\x01\x1e\x01\x0f\x01\x176 \x17%#\"&5\x00 \x00\x10\x00 \x00\x10\x05\x00\x12\x0e\x01 \x1a&\x12\x0e@\x0e\x12\xfe~\xfe\xd9\xd9`\x0e\x12\x12\x0e`\x12\x0e@\x0e\x12`\x0e\x12\x12\x0e`\xd9\xfe\xd9~4e\t\x1a\n0\n\x01\tio\x12\x0e@\x0e\x12&\x1a\x01 \x0e\x12\x12\x0e\x85jV\t\x1a\n0\n\x01\tZ9\x9e\x01\x92\x9e\x00\xff\x86\x0e\x12\xfd\x87\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\x05\xe0\x0e\x12&\x1a\xfe\xe0\x0e\x12\x12\x0e\x86\xff\x9e\xc9\xdd\xfe\xb9\x18\x84\x12\x0e@\x0e\x12`\x0e\x12\x12\x0e`\x12\x0e@\x0e\x12\x84\x18\x01G\xddɞ5o\n\x01\b,\b\x1b\nsp\x86\x0e\x12\x12\x0e\x01 \x1a&\x12\x0e@\x0e\x12k^\n\x01\b,\b\x1b\nc8~~\xfe\x12\x0e\xfb`\x01\a\x01r\x01\a\xfe\xf9\xfe\x8e\x00\x00\x00\x00\x05\x00\x02\xff\x00\x06\xfe\x05\xfd\x008\x00>\x00K\x00R\x00_\x00\x00\x01\x16\x02\x06\a\x1132\x16\x1d\x01\x14\x06+\x01\x15\x14\x06+\x01\"&=\x01!\x15\x14\x06+\x01\"&=\x01#\"&=\x0146;\x01\x11.\x01\x0276\x0076\x176\x17\x16\x00\x016\x10'\x06\x10\x0327&547&#\"\x00\x10\x00\x01\x11&'\x06\a\x11\x012\x00\x10\x00#\"\a\x16\x15\x14\a\x16\x06\xfe\f\x81\xf3\x96\xe0\x0e\x12\x12\x0e\xe0\x12\x0e@\x0e\x12\xfe\x00\x12\x0e@\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\x96\xf3\x81\f\x11\x01'\xcdΫ\xab\xce\xcd\x01'\xfc\x93\x80\x80\x80\xc0sg\x9a\x9ags\xb9\xfe\xf9\x01\a\x02\xf9\x89ww\x89\x02@\xb9\x01\a\xfe\xf9\xb9sg\x9a\x9ag\x03\xef\x9b\xfe\xee\xae\x10\xfe\xfc\x12\x0e@\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\xe0\x0e\x12\x12\x0e\xe0\x12\x0e@\x0e\x12\x01\x04\x10\xae\x01\x12\x9b\xce\x01-\x13\x15ss\x15\x13\xfe\xd3\xfdʃ\x01l\x83\x83\xfe\x94\xfe\xf69\xa5\xe2\xe0\xa79\xfe\xf9\xfe\x8e\xfe\xf9\xfe\x80\x01\x04\x0fOO\x0f\xfe\xfc\x01\x80\x01\a\x01r\x01\a9\xa7\xe0\xe2\xa59\x00\x00\x04\x00\x01\xff\x06\a\x80\x06\x00\x00F\x00P\x00^\x00l\x00\x00\x01463!2\x16\x15\x11\x14\x06+\x01\"&=\x01\a\x1e\x01\a\x06\x00\a\x06$'.\x037>\x0276\x16\x17%#\"&=\x01463!2\x16\x15\x11\x14\x06+\x01\"&=\x01\a\x16\x17\x16\x17%#\"&5\x014'\x0e\x01\x15\x14\x17>\x01%\x14\x16\x17&54\x007.\x01#\"\x00\x012\x0054&'\x16\x15\x14\x00\a\x1e\x01\x06\x00\x12\x0e\x01 \x1a&\x12\x0e@\x0e\x12\xfeL?\x16\x1f\xfe\xf2\xb7\xd2\xfe\xa3CuГP\b\t\x8a\xe2\x87v\xdbY\x00\xff\x86\x0e\x12\x12\x0e\x01 \x1a&\x12\x0e@\x0e\x12\xfe;\"\xb6\x92\x00\xff\x86\x0e\x12\xfe\x00\x04\xa2\xda\x04\xa2\xda\xfc\x80ޥ\x03\x01\x0e\xcb5݇\xb9\xfe\xf9\x03\xc0\xb9\x01\aޥ\x03\xfe\xf2\xcb5\xdd\x04`\x0e\x12&\x1a\xfe\xe0\x0e\x12\x12\x0e\x86\xff_\ue036\xfe\xfc\x1a\x1dڿ\x06g\xa3\xdew\x87\xea\x95\x0f\x0eBF\xfe\x12\x0e@\x0e\x12&\x1a\xfe\xe0\x0e\x12\x12\x0e\x86\xffJ_\ts\xfe\x12\x0e\xfe\xa0\x14&\x19\xfa\xa7\x14&\x19\xfa\xa7\xa8\xfc\x17\x1d\x1e\xd2\x01?%x\x92\xfe\xf9\xfc\a\x01\a\xb9\xa8\xfc\x17\x1c\x1f\xd2\xfe\xc1%x\x92\x00\x04\x00\x06\xff\x00\b\x00\x06\x00\x00J\x00P\x00\\\x00h\x00\x00\x01463!2\x16\x15\x11\x14\x06+\x01\"&=\x01\a\x1e\x01\a\x06\x00\a\x06'\x06\a\x1532\x16\x1d\x01\x14\x06+\x01\x15\x14\x06+\x01\"&=\x01#\"&=\x0146;\x015.\x01\x0276\x0076\x17632\x17%#\"&5\x016\x10'\x06\x10\x00\x10\x00327&\x107&#\"\x012\x00\x10\x00#\"\a\x16\x10\a\x16\x06\x80\x12\x0e\x01 \x1a&\x12\x0e@\x0e\x12\xfeL?\x16 \xfe\xf7\xb5ߺu\x8b`\x0e\x12\x12\x0e`\x12\x0e@\x0e\x12`\x0e\x12\x12\x0e`\x9b\xf9}\x17\x19\x01\r\xba\u0e92\xaeɞ\x00\xff\x86\x0e\x12\xfd\x00\x80\x80\x80\xfd\x80\x01\a\xb9ue\x9a\x9aeu\xb9\x039\xb9\x01\a\xfe\xf9\xb9ue\x9a\x9ae\x05\xe0\x0e\x12&\x1a\xfe\xe0\x0e\x12\x12\x0e\x86\xff_\ue034\xfe\xfc\x1b\"|N\x0f\x84\x12\x0e@\x0e\x12`\x0e\x12\x12\x0e`\x12\x0e@\x0e\x12\x84\x11\xb9\x01\"\xa2\xbb\x01\x0f\x1d\"|a~\xfe\x12\x0e\xfb\xe7\x83\x01l\x83\x83\xfe\x94\x01o\xfe\x8e\xfe\xf99\xa7\x01\xc0\xa79\xfc\x80\x01\a\x01r\x01\a9\xa7\xfe@\xa79\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00;\x00C\x00\x00\x012\x16\x15\x11\x14\x06+\x01\"&5\x11\a\x17\x16\x14\x0f\x01\x06\"/\x01\a\x16\x15\x14\x0e\x02\".\x024>\x0232\x177'&4?\x0162\x1f\x017!\"&=\x01463\x00 \x00\x10\x00 \x00\x10\x05\xc0\x1a&\x12\x0e@\x0e\x12Ռ\t\t.\t\x1a\n\x8cN~[\x9b\xd5\xea՛[[\x9b\xd5u˜N\xac\t\t.\t\x1a\n\xac\xd5\xfe\xfb\x0e\x12\x12\x0e\xfdg\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\x05\x80&\x1a\xfe`\x0e\x12\x12\x0e\x01\x06\u058c\n\x1a\t.\t\t\x8dO\x9c\xcbu՛[[\x9b\xd5\xea՛[~N\xac\n\x1a\t.\t\t\xac\xd5\x12\x0e@\x0e\x12\xfa\x80\x01\a\x01r\x01\a\xfe\xf9\xfe\x8e\x00\x00\x00\x00\x02\x00\x02\xff\x04\x04\x80\x06\x00\x009\x00A\x00\x00\x01\x16\x00\x15\x14\x02\x04'.\x02'&\x12675#\"&=\x0146;\x015\a\x06\"/\x01&4?\x0162\x1f\x01\x16\x14\x0f\x01\x06\"/\x01\x1532\x16\x1d\x01\x14\x06+\x01\x02 \x00\x10\x00 \x00\x10\x02\x80\xd9\x01'\xae\xfe֪\x85\xe1\x8b\v\f\x81\xf3\x96\xa0\x0e\x12\x12\x0e\xa0\\\n\x1a\t.\t\t\xca\x134\x13\xca\t\t.\t\x1a\n\\\xa0\x0e\x12\x12\x0e\xa0\xf9\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\x03|\x18\xfe\xb9ݧ\xfe\xea\x92\x13\x0f\x92憛\x01\x12\xae\x10\x84\x12\x0e@\x0e\x12\xa5\\\t\t.\t\x1a\n\xc9\x13\x13\xc9\n\x1a\t.\t\t\\\xa5\x12\x0e@\x0e\x12\xfb\x80\x01\a\x01r\x01\a\xfe\xf9\xfe\x8e\x00\x00\x02\x00\x04\x00\x00\a\x80\x04~\x009\x00A\x00\x00\x01\x16\x14\a\x01\x06\"/\x01&4?\x01!\x15\x14\x06+\x01\"&=\x01#\x06\x00#\"$\x027>\x0276\x04\x16\x173546;\x012\x16\x1d\x01!'&4?\x0162\x17\x00 \x00\x10\x00 \x00\x10\am\x13\x13\xfe\xda\t\x1b\t-\n\n\xb9\xfe\xda\x12\x0e@\x0e\x12\x84\x18\xfe\xb9ݧ\xfe\xea\x92\x13\x0f\x92憛\x01\x12\xae\x10\x84\x12\x0e@\x0e\x12\x01&\xb9\n\n-\t\x1b\t\xfb@\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\x02m\x134\x13\xfe\xda\n\n-\t\x1b\t\xb9\xe0\x0e\x12\x12\x0e\xe0\xd9\xfeٮ\x01*\xaa\x85\xe1\x8b\v\f\x81\xf3\x96\xe0\x0e\x12\x12\x0e\xe0\xb9\t\x1b\t-\n\n\xfc\xed\x01\a\x01r\x01\a\xfe\xf9\xfe\x8e\x00\x00\x02\x00\x00\xff\x00\x04\x80\x06\x00\x00\x17\x00\x1f\x00\x00\x01\x14\x00\a\x11\x14\x06+\x01\"&5\x11&\x0054>\x022\x1e\x02\x00 \x00\x10\x00 \x00\x10\x04\x80\xfe\xd9\xd9\x12\x0e@\x0e\x12\xd9\xfe\xd9[\x9b\xd5\xea՛[\xfd\a\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\x03\xc0\xdd\xfe\xb9\x18\xfd\x9c\x0e\x12\x12\x0e\x02d\x18\x01G\xddu՛[[\x9b\xd5\xfd\xcb\x01\a\x01r\x01\a\xfe\xf9\xfe\x8e\x00\x00\x02\x00\x00\x00\x00\x04\x80\x04\x80\x00\a\x00\x17\x00\x00\x00\x10\x00 \x00\x10\x00 \x00\x14\x0e\x02\".\x024>\x022\x1e\x01\x04\x00\xfe\xf9\xfe\x8e\xfe\xf9\x01\a\x01r\x01\x87[\x9b\xd5\xea՛[[\x9b\xd5\xea՛\x01\x87\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\x025\xea՛[[\x9b\xd5\xea՛[[\x9b\x00\x00\x01\x00\x00\xff\x80\x06\x00\x05\x80\x00$\x00\x00\x012\x16\x15\x11\x14\x06#!\x1137#546375&#\"\x06\x1d\x01#\x153\x11!\"&5\x11463\x05\xab#22#\xfey\xc7\x1e\xe5/Dz?s\x88\xa3\xc8\xc8\xfd!#22#\x05\x802#\xfa\xaa#2\x02S\xe8\x9488\x01\xcf\t\xa0\x92\xab\xe8\xfd\xad2#\x05V#2\x00\x00\x00\x01\x00\x00\xff\x80\x05\x00\x06\x00\x00L\x00\x00\x114>\x0332\x04\x16\x15\x14\x0e\x03#\"&'\x0e\x06\x0f\x01'&546\x127&54632\x16\x15\x14\x06\x15\x14\x1632>\x0454&#\"\x00\x15\x14\x1e\x02\x15\x14\x06#\"'.\x03K\x84\xac\xc6g\x9e\x01\x10\xaa&Rv\xacgD\x86\x1d\n$\v\x1e\x16*2%\x0e\t\x0f+Z\a hP=DXZ@7^?1\x1b\r۰\xc8\xfe\xf4\x19\x1d\x19\x1e\x16\x02\x0f3O+\x16\x03\xabl\xbf\x8eh4\x85\xfe\xa0`\xb8\xaa\x81M@8'\x93+c+RI2\x05\n\x9d\x1f\\\xe5\x01Z\x1eAhS\x92Q>B\xfa>?S2Vhui/\xad\xc1\xfe\xfd\xc7,R0+\t\x1cZ\x03\x0fRkm\x00\x00\x00\x00\x03\x00\x00\xffz\x06\x00\x05\x86\x00+\x00>\x00Q\x00\x00\x002\x16\x17\x16\x15\x14\a\x0e\x01#\"'.\x01'&7567632\x1632\x16\x17\x1e\x01\x15\x14\x06\x15\x14\x17\x16\x17\x16\x17\x1632\x032>\x024.\x02\"\x0e\x02\x15\x14\x17\a7\x16\x12 \x04\x16\x12\x10\x02\x06\x04#\"'\x05\x13&54\x126\x03\xcc\x1a\xa9\x05\x02\x11\x10n/9\x85b\x90LH\x01\x03G\x18\x1c\x06\x18\a\x13\x0f\b\b2E\x05\"D8_\f\n\x0fp\u007f\xe9\xa8dd\xa8\xe9\xfe\xe9\xa8dxO\xf2\x9e\"\x012\x01\x17\xcaxx\xca\xfe\xe9\x99ê\xfe_\x88lx\xca\x022X\t\x05\n!+'5>-\x92pkW\b[C\x16\x03\r\x15\x14\x88\a\x15I\n\a\bI@50\a\xfeOd\xa8\xe9\xfe\xe9\xa8dd\xa8\xe9\u007f˥\xe9Mh\x05fx\xca\xfe\xe9\xfe\xce\xfe\xe9\xcax^\x86\x01\x95\xb2ә\x01\x17\xca\x00\x00\t\x00\x00\x00\x00\a\x00\x05\x80\x00\x03\x00\a\x00\x0f\x00\x13\x00\x1b\x00#\x00'\x00+\x00/\x00\x007!5!\x11!5!\x004&\"\x06\x14\x162\x01!5!\x004&\"\x06\x14\x162\x124&\"\x06\x14\x162\x13\x11!\x11\x01\x11!\x11\x01\x11!\x11\x80\x04\x00\xfc\x00\x04\x00\xfc\x00\x06 8P88P\xfa\x18\x04\x00\xfc\x00\x06 8P88P88P88P\x98\xf9\x00\a\x00\xf9\x00\a\x00\xf9\x00\x80\x80\x01\x80\x80\xfd\x98P88P8\x04 \x80\xfd\x98P88P8\x028P88P8\xfd \xfe\x80\x01\x80\x02\x00\xfe\x80\x01\x80\x02\x00\xfe\x80\x01\x80\x00\x00\x03\x00\x00\xff\x80\b\x00\x05\x80\x00\a\x00+\x00N\x00\x00\x00 &\x106 \x16\x10\x01!2\x16\x1d\x01\x14\x06#!\x11\x14\x06+\x01\"&5\x11!\"&=\x01463!\x1146;\x012\x16\x15\x01\x14\x163!\x15\x06#!\"&54>\x0532\x17\x1e\x01267632\x17#\"\x06\x15\x03_\xfe\xc2\xe1\xe1\x01>\xe1\x02@\x01`\r\x13\x13\r\xfe\xa0\x13\r\xc0\r\x13\xfe\xa0\r\x13\x13\r\x01`\x13\r\xc0\r\x13\xfd L4\x01\x00Dg\xfc\x96y\x92\a\x15 6Fe=\x13\x14O\x97\xb2\x97O\x14\x13\x84U\xdf4L\x02\x80\xe1\x01>\xe1\xe1\xfe\xc2\xfe\x9f\x13\r\xc0\r\x13\xfe\xa0\r\x13\x13\r\x01`\x13\r\xc0\r\x13\x01`\r\x13\x13\r\xfd\xc04L\xee2\x8ay5eud_C(\x11====\x11`L4\x00\x00\x00\x03\x00\x00\xff\x80\a\xf7\x05\x80\x00\a\x003\x00V\x00\x00\x00 &\x106 \x16\x10\x01\x17\x16\x15\x14\x0f\x01\x06#\"/\x01\a\x06#\"/\x01&54?\x01'&54?\x01632\x1f\x017632\x1f\x01\x16\x15\x14\a\x05\a\x06\x15\x14\x1f\x01\x06#!\"&54>\x0532\x17\x16 7632\x17\x0e\x01\x15\x14\x17\x03_\xfe\xc2\xe1\xe1\x01>\xe1\x02\xb5\xf9\t\t\x88\t\r\x0e\t\xf9\xf9\t\x0e\r\t\x88\t\t\xf9\xf9\t\t\x88\t\r\x0e\t\xf9\xf9\t\x0e\r\t\x88\t\t\xfd\x15\xb5%%S\x15\x17\xfc\x96y\x92\a\x15 6Fe=\x13\x14\x9a\x01J\x9a\x14\x13\x1c\x1d\x1c\x1a%\x02\x80\xe1\x01>\xe1\xe1\xfe\xc2\xfd\xdf\xf9\t\x0e\r\t\x88\t\t\xf9\xf9\t\t\x88\t\r\x0e\t\xf9\xf9\t\x0e\r\t\x88\t\t\xf9\xf9\t\t\x88\t\r\x0e\t\xf9\xb5%65%S\x03\x8ay5eud_C(\x11zz\x11\x06\x1b.!6%\x00\x03\x00\x00\x00\x00\b\x00\x05\x00\x00\x12\x00\x1a\x00$\x00\x00\x01!2\x16\x15\x11!\x11!\x11!\x1146;\x012\x16\x15\x004&\"\x06\x14\x162!54&#!\"\x06\x15\x11\x01\x00\x06\xc0\x1a&\xff\x00\xfa\x00\xff\x00&\x1a\x80\x1a&\x02@\x96Ԗ\x96\xd4\x05V\xe1\x9f\xfd@\x1a&\x02\x00&\x1a\xfe@\x01\x00\xff\x00\x04\xc0\x1a&&\x1a\xfe\x16Ԗ\x96Ԗ@\x9f\xe1&\x1a\xfe\x80\x00\x00\x00\x00\x02\x00\x00\xff\x00\x06\x00\x06\x00\x00\x16\x00\x19\x00\x00\x01\x033\x15!\a!\x15!\t\x01!5!'!53\x03!\x01!\t\x01\x13#\x06\x00\xc0\xc0\xfe\xee7\x01I\xfee\xfe\x9b\xfe\x9b\xfee\x01I7\xfe\xee\xc0\xc0\x01\x00\x01C\x01z\x01C\xfe\x00l\xd8\x06\x00\xfe@\xc0\x80\xc0\xfc\xc0\x03@\xc0\x80\xc0\x01\xc0\xfd\x00\x03\x00\xfb@\x01\x00\x00\x00\x00\x03\x00\x00\xff\x00\x06\x00\x06\x00\x00\x17\x00\x1f\x00#\x00\x00\x012\x04\x15\x11\x14\x06\a\x17\x16\x06#!\"&?\x01.\x015\x114$3\x12264&\"\x06\x14\x01\x11!\x11\x04@\xb9\x01\a\xfb\xb4\xd5\x10\x10\x16\xfb\xe0\x16\x10\x10մ\xfb\x01\a\xb9\xf0\xa0pp\xa0p\x03\x00\xfb\x80\x06\x00\xbb\x85\xfc\x80\x82\xb8\x05\xca\x0f((\x0f\xca\x05\xb8\x82\x03\x80\x85\xbb\xfa\xc0p\xa0pp\xa0\x01\xd0\x02\x00\xfe\x00\x00\x00\x00\x00\x05\x00\x00\xff\x00\x06\x00\x06\x00\x00\x17\x00\x1f\x00#\x00+\x00/\x00\x00\x012\x04\x15\x11\x14\x06\a\x17\x16\x06#!\"&?\x01.\x015\x114$3\x02264&\"\x06\x14\x01\x11!\x11\x00264&\"\x06\x14\x01\x11!\x11\x04@\xb9\x01\a\xfb\xb4\xd5\x10\x10\x16\xfb\xe0\x16\x10\x10մ\xfb\x01\a\xb9\xe2\x84^^\x84^\x02@\xfd\xe0\x03\xfe\x84^^\x84^\x01@\xfd\xc0\x06\x00\xbb\x85\xfc\x80\x82\xb8\x05\xca\x0f((\x0f\xca\x05\xb8\x82\x03\x80\x85\xbb\xfa\xe0^\x84^^\x84\x01\xc2\x02\x00\xfe\x00\xfd\xe0^\x84^^\x84\x01\xc2\x02\x00\xfe\x00\x00\x00\x00\x00\x04\x00\x00\xff\x8a\a\x00\x05v\x00\x12\x00\x15\x00\x1c\x00(\x00\x00\x01\x11\x14\x06#\"'%.\x015\x114632\x17\x01\x16\x17\t\x02\x11\x14\x06\"'%\x01\x14\x00\a\t\x01632\x17\x01\x16\x02U\x19\x18\x11\x10\xfe/\x15\x1d\x14\x13\x0e\x1e\x01\xff\x03@\x02\x16\xfd\xea\x04k\x1c0\x17\xfeG\x02\x19\xfd\xff,\xfez\x01D\x11#\x0e\f\x02\x1d\x04\x04[\xfbk\x19#\b\xe9\n/\x17\x04t\x14\x1c\x0f\xff\x00\x03g\xfc\x9e\x01\n\x02F\xfb\xe2\x19\x1f\r\xdc\x03\xe5\x03\xfc\xbfG\x02z\x02\x0f\x1c\x06\xfe\xf2\x02\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\v\x00\x0f\x00\x00\t\x01#\x03\x06\a'\x03#\x01\x113\x01\x11!\x11\x03)\x01\np\x9d\x18\x14*\x9bx\x01\ae\x02\xd7\xfa\x00\x02\x14\x01\xf3\xfe\xc80,\\\x018\xfe\x13\xfe\xbc\x04\xaa\xfa\x00\x06\x00\x00\x00\x18\x00T\xff\x06\b\xa4\x05\xff\x00\v\x00\x17\x00#\x00/\x00D\x00M\x00\xfc\x01\x06\x01\x12\x01\x1b\x01%\x012\x01<\x01G\x01Q\x01^\x01l\x01w\x01\xb3\x01\xc2\x01\xd9\x01\xe9\x01\xfe\x02\r\x00\x00\x05\x0e\x01\a\x06&'&676\x16\x05\x1e\x01\x17\x16676&'&\x067\x1e\x01\x17\x16654&'&\x06\x05\x0e\x01\a\x06&54676\x16\x013\"\a\x1e\x01\x15\x14\x06#\"'\x06\x15\x14\x163264&7.\x01\a>\x02\x1e\x01\x01\x16\a\x16\x15\x16\x0e\x01\a\x06&'\x04%\x0e\x01'.\x01767&76\x1767&76\x1767476\x176\x17\x16\x175\"'.\x01'&767>\x02\x16\x173\x16\x17\x16\x17>\x017&'&'47.\x01'.\x017676\x16\x17\x14\x1e\x03\x17\x16767&\a76767.\x04'$\x01\x16\x17\x1673>\x03?\x01>\x01\x17\x16\x17\x16\x06\a\x0e\x01\a\x15\x06\a\x06\a\x1e\x01\x1767673>\x01\x1e\x01\x17\x16\x17\x16\a\x0e\x01\a\x06#\x14\a676\x176\x17\x16\x15\x16\x176\x17\x16\a\x16\x176\x01\x14\a\x16\x176&'&\x06\a\x1e\x01\a6767.\x01'\x06\a\"'\x16\x17276&\x0567&54&\a\x0e\x01\x17\x16\x17&671&'\x0e\x01\a\x16\x1767\x06\x0f\x015\x06\x17\x16\x05\x1e\x01\x17\x1e\x017>\x017&\x00\"\x06\x15\x14\x162654\x03&\a5\x06\x16\x17\x1e\x017>\x01&\x05>\x01&'5\x06#\x0e\x01\x16\x17\x1e\x01%\x06\x16\x17\x1667>\x017\x06\a\x16\a\x16\x04\x176$7&74>\x01=\x01\x15.\x01'\x06\a\x06'&'&'\x0e\b#\x06'\x0e\x03\a\x06#\x06'\x06'&'&'&'\x06\a\x16\x0365.\x01'&\x0e\x01\x17\x1e\x01\x17\x1667\x16\x1767.\x01'\x06\a\x14\x06\x15\x16\a\x06\a\x06\a#\x06\x17\x16\x17\x04%&'\x06\a\x06'&'\x06\a#\x152%6767\a65&'&'&7&5&'\x06\a\x16\x056.\x01\a\x0e\x01\a\x14\x17\x1e\x017>\x01\x01\xde\b&\x12\x195\x02\x01R\x1b\x17\x16\x054\a&\x13\x195\x01\x02S\x1b\x16\x169\rW\"-J\x870(/\xfar\rV\"-J\x870(.\x02\xc9\x01)#\x1b\"6&4\x1c\x05pOPpp\xe0c\xf3|\x1bo}vQ\x02\xf2\b\x13\a\x01[\x8060X\x16\xfdQ\xfd\xc4\x17W1V\xbb\x01\x02\x05\x13\b\x06\x19\x0e\x1b\a\t\v\x1c\x1d\x1e\r\x17\x1c#\x1a\x12\x14\v\a5X\v\t\t\x0fN\x02\"&\x1c\x05\r.\x0e\x03\x02\n)\n\x0f\x0f\x17D\x01>q\x1c \x15\b\x10J\x17:\x03\x03\x02\x04\a\x05\x1b102(z/=f\x91\x89\x14*4!>\f\x02S\x015b!\x11%\n\x19\x12\x05\x12\x03\x04\x01\x05\x01\v\x06(\x03\x06\x04\x02!\x1f$p8~5\x10\x17\x1d\x01\x1a\x10\x18\x0e\x03\x0e\x02.\x1c\x04\x12.:5I\r\b\x0f\r\b\x0e\x03~\xfe\xf7T\x8a\n\x13\x03\x0e\x18\x0f\x0e\x0e\x1c\x18\x114~9p# !\x02\n\x02)\x05\f\x01\x05\x01\x05\x03\x12\x05\x12\x18\b&\x11 ?()5F\t\x021\x18\x0f\x04\a\x05\x1c\f\t\x1c\x10\x12\r\t\n\x1c\x1e\x15\b\x03\xaf\x1d\x19 d%{\x1d\x13\x04v*\x85:\r \x0e\x0e@e\x10\x0f\n\x01s|\x03D\x861d \x19\x1d\x12\x04\x13\x1d{\x8b\x1f\x0e:\x85*\x06\x0f\x10dA\x11A|o\x04\x0e\x13\x01Yk\x03'&\x8d\x13\x12\a\b\x14\x83<\x02\x02\x83\xa5tu\xa5\xa5ut\xfe&\x02\x02\x01\x1bv\a\x0e\x01\v\x03HC\xba\x04XX\x13\x01\x03\x14TR\x05\x0f\x02\xc8;w\x19\b\x06\x12\x10\x94\x1d\x02\x82\x17\r\x8d\xc671\u0099\r\x15\x02\x03\x03\x01\x01\x01\x02\a\x01Z*&'\x06\b\r1\x05\b\x06\x05\x03\x02\x02\x01\x01\t\x14\x11\x13\v\x03\x02\x01\x119?\t\b.\r\r\x1d$\x06\x04\x02\xfd\x84\x0e\x10Gv\v\f5k65P\x02\x02<\xdc?8q=4\x88a\x04\t\x01\x06\x02\x12\x13\x17\v\r\vSC\"\xcd\x15\x15\x931#\x16\x03\x03\x15\x1c<\x80\x01/6B&!\x01ML\b\x11\t\x18\x14\x12\x04\x05\x04\b\xbe^;\x8c6k5\f\vwF\x10\x0e1<\x02\x02P\x00\x00\x03\x00\x00\xffC\t\x01\x05\xbd\x00\a\x00\x0f\x00;\x00\x00$\x14\x06\"&462\x04\x14\x06\"&462\x01\x1e\x05\f\x0132\x1e\x04\x0e\x03\a\x06\a>\x05.\x03\a\x06$.\a\x05\xf4`\x88aa\x88\xfdsa\x88``\x88\xfdZ9k\x87\x89\xc3\xcd\x01'\x019؋ӗa-\x03*Gl|M\xb9e\x1d_]`F&\fO\x9a\xfe\xb1\xa8\xfe\xdcܽ\x82sDD!/+\x88``\x88aa\x88``\x88a\x051\x0154&'\"&#!\x11!26\x13\x11\x14\x06#!\"&5\x11463!2\x16\a\x9f\x1f\x17\b\n\x99\x99\n\b\x17\r\x1e\x17\x03\f\x8b\x8b\x03\v\x01\x17\xfbi\xe4LCly5\x88)*\x01H\x02\xcacelzzlec0h\x1c\x1c\u007f\xb7b,,b\xb7\u007fe\x03IVB9@RB\x03\x12\x05\xfe9\x01\xebJ_\x80L4\xf8\x004LL4\b\x004L\x0244%\x05\x02\x8c\x02\x05\xaf2\"\x04\x01\x81\x01\x04\xe0\x014\xfe\xcc:I;p\x0f\x10\x01\x01!q4\a\bb\xbab\b\a3p\f\x0f\x02\x02\x06(P`t`P(\x06\x04\x8e6E\x05\x03\bC.7B\x03\x01\xfe\x02I\x036\xfb\x004LL4\x05\x004LL\x00\x00\x05\x00\x00\xff\x80\t\x00\x05\x80\x00\x05\x00\v\x00\x1a\x00.\x00>\x00\x00\x01\x11\x0e\x01\x14\x16$4&'\x116\x00\x10\x02\x04#\".\x0254\x12$ \x04\x014.\x02#!\"\x04\x02\x15\x14\x12\x043!2>\x02\x01\x11\x14\x06#!\"&5\x11463!2\x16\x03Zj\x84\x84\x02b\x84jj\x01[\x9d\xfe\xf2\x9fwٝ]\x9d\x01\x0e\x01>\x01\x0e\x02\x1co\xb8\xf3\x83\xfeӰ\xfeٯ\xae\x01*\xae\x01-\x81\xf5\xb8o\x01XL4\xf8\x004LL4\b\x004L\x01'\x02\xb5)\xbd꽽\xea\xbd)\xfdJ)\x01\xd1\xfe\xc2\xfe\xf2\x9d]\x9d\xd9w\x9f\x01\x0e\x9d\x9d\xfeL\x8b\xf5\xa6`\xa2\xfeֺ\xab\xfe۪e\xa9\xec\x03\x06\xfb\x004LL4\x05\x004LL\x00\x00\x00\x03\x00\x00\xff\x00\a\x00\x06\x00\x00\x0f\x00\x1f\x00;\x00\x00\x05\x114&#!\"\x06\x15\x11\x14\x163!26\x13\x11\x14\x06#!\"&5\x11463!2\x16\x01\x15#54&#!\"\x06\x15\x11\x14\x16;\x01\x15#\"&5\x11463!2\x16\x06\x80\x13\r\xfb\xc0\r\x13\x13\r\x04@\r\x13\x80^B\xfb\xc0B^^B\x04@B^\xfe\x80\x80\x13\r\xfb\xc0\r\x13\x13\r\xa0\xa0B^^B\x04@B^`\x04@\r\x13\x13\r\xfb\xc0\r\x13\x13\x04M\xfb\xc0B^^B\x04@B^^\x01>\xa0\xa0\r\x13\x13\r\xfb\xc0\r\x13\x80^B\x04@B^^\x00\x00\x06\x00\x00\xff\x00\b\x80\x06\x00\x00\x02\x00\x05\x005\x00=\x00U\x00m\x00\x00\t\x01!\t\x01!\x01\x0e\x01\a\x11!2\x16\x1d\x01\x14\x06#!\"&=\x01463!\x11.\x01'!\"&=\x01463!>\x012\x16\x17!2\x16\x1d\x01\x14\x06#\x04264&\"\x06\x14\x01\x14\x0e\x02\".\x0254>\x03762\x17\x1e\x04\x05\x14\x0e\x02\".\x0254>\x03762\x17\x1e\x04\x06\xc0\xfe\x80\x03\x00\xf9\x80\xfe\x80\x03\x00\x01\xb5\x0e?(\x02`\x0e\x12\x12\x0e\xfa\xc0\x0e\x12\x12\x0e\x02`(?\x0e\xfe\x15\x0e\x12\x12\x0e\x01\xeb\x15b|b\x15\x01\xeb\x0e\x12\x12\x0e\xfd?B//B/\x04\x90]\x8e\x93\x84\x93\x8e]Frdh\x04\x12L\x12\x04hdrF\xfb\x00]\x8e\x93\x84\x93\x8e]Frdh\x04\x12L\x12\x04hdrF\x04@\xfd@\x02\xc0\xfd@\x03\x80(?\x0e\xfa\xf5\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x05\v\x0e?(\x12\x0e@\x0e\x129GG9\x12\x0e@\x0e\x12\x10/B//B\xfcaItB!!BtI\v\x8cѶ\xba\a!!\a\xba\xb6ь\vItB!!BtI\v\x8cѶ\xba\a!!\a\xba\xb6ь\x00\x00\x02\x00\x00\xff\x00\x06\x00\x06\x00\x00-\x00M\x00\x00\x01\x10\x02\a\x16\x12\x1132\x16\x1d\x01\x14\x06#!\"&=\x0146;\x01\x10\x127&\x02\x11#\"&=\x01463!2\x16\x1d\x01\x14\x06#\x01>\x035!\x14\x1e\x02\x17\x1e\x01\x14\x06\a\x0e\x03\x15!4.\x02'.\x0146\x05\x80\u0560\xa0\xd5`\x0e\x12\x12\x0e\xfa@\x0e\x12\x12\x0e`\u0560\xa0\xd5`\x0e\x12\x12\x0e\x05\xc0\x0e\x12\x12\x0e\xfd\x8aM\x90sF\xfc\x00Fs\x90M\x13\x17\x17\x13M\x90sF\x04\x00Fs\x90M\x13\x17\x17\x05\x80\xfe\xfb\xfeojj\xfeo\xfe\xfb\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x01\x05\x01\x91jj\x01\x91\x01\x05\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\xfd<\x1d\u007f\xb2\xf2\x84\x84\xf2\xb2\u007f\x1d\a!(!\a\x1d\u007f\xb2\xf2\x84\x84\xf2\xb2\u007f\x1d\a!(!\x00\x00\x03\x00\x00\xff\x00\x06\x00\x06\x00\x00-\x003\x00?\x00\x00\x01\x10\x02\a\x16\x12\x1132\x16\x1d\x01\x14\x06#!\"&=\x0146;\x01\x10\x127&\x02\x11#\"&=\x01463!2\x16\x1d\x01\x14\x06+\x01!\x14\x17!6\x114.\x02'#\x0e\x03\x15\x05\x80\u0560\xa0\xd5`\x0e\x12\x12\x0e\xfa@\x0e\x12\x12\x0e`\u0560\xa0\xd5`\x0e\x12\x12\x0e\x05\xc0\x0e\x12\x12\x0e\xe0\xfc\x00\t\x03\xee\tDq\x8cL\xe6L\x8cqD\x05\x80\xfe\xfb\xfeojj\xfeo\xfe\xfb\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x01\x05\x01\x91jj\x01\x91\x01\x05\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12B>=\xfaC\x82\xef\xb1\u007f\x1f\x1f\u007f\xb1\xef\x82\x00\x00\x00\x00\x03\x00\x00\xff\x00\x06\x00\x06\x00\x00-\x003\x00;\x00\x00\x01\x10\x02\a\x16\x12\x1132\x16\x1d\x01\x14\x06#!\"&=\x0146;\x01\x10\x127&\x02\x11#\"&=\x01463!2\x16\x1d\x01\x14\x06+\x01!\x14\x17!6\x03.\x01'#\x0e\x01\a\x05\x80\u0560\xa0\xd5`\x0e\x12\x12\x0e\xfa@\x0e\x12\x12\x0e`\u0560\xa0\xd5`\x0e\x12\x12\x0e\x05\xc0\x0e\x12\x12\x0e\xe0\xfc\x00U\x03VU96\xb7g\xe6g\xb76\x05\x80\xfe\xfb\xfeojj\xfeo\xfe\xfb\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x01\x05\x01\x91jj\x01\x91\x01\x05\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12β\xb2\xfc\x0e\x8d\xc9**ɍ\x00\x00\x02\x00\x00\xff\x00\x06\x00\x06\x00\x00-\x00G\x00\x00\x01\x10\x02\a\x16\x12\x1132\x16\x1d\x01\x14\x06#!\"&=\x0146;\x01\x10\x127&\x02\x11#\"&=\x01463!2\x16\x1d\x01\x14\x06#\x01>\x035!\x14\x1e\x02\x17\x1e\x01\x14\x06\a\x06\a!&'.\x0146\x05\x80\u0560\xa0\xd5`\x0e\x12\x12\x0e\xfa@\x0e\x12\x12\x0e`\u0560\xa0\xd5`\x0e\x12\x12\x0e\x05\xc0\x0e\x12\x12\x0e\xfd\x8aM\x90sF\xfc\x00Fs\x90M\x13\x17\x17\x13\x89k\x02\xbck\x89\x13\x17\x17\x05\x80\xfe\xfb\xfeojj\xfeo\xfe\xfb\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x01\x05\x01\x91jj\x01\x91\x01\x05\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\xfd<\x1d\u007f\xb2\xf2\x84\x84\xf2\xb2\u007f\x1d\a!(!\a3\x91\x913\a!(!\x00\x00\x00\x03\x00\x00\xff\x00\x06\x00\x06\x00\x00\x0f\x009\x00I\x00\x00\x052\x16\x1d\x01\x14\x06#!\"&=\x014637>\b7.\b'!\x0e\b\a\x1e\b\x17\x132\x16\x1d\x01\x14\x06#!\"&=\x01463\x05\xe0\x0e\x12\x12\x0e\xfa@\x0e\x12\x12\x0eb\x03\x1a\":1P4Y,++,Y4P1:\"\x1a\x03\x04\xfc\x03\x1a\":1P4Y,++,Y4P1:\"\x1a\x03b\x0e\x12\x12\x0e\xfa@\x0e\x12\x12\x0e@\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12@7hVX@K-A\x1e\x1c\x1c\x1eA-K@XVh77hVX@K-A\x1e\x1c\x1c\x1eA-K@XVh7\x06\x00\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x00\x00A\x00j\x00\x00\x01\"\x06\x1d\x01#54&#\"\x06\x15\x11'54&#\"\x06\x1d\x01\x14\x17\x01\x16\x15\x14\x163!26=\x0147\x136=\x014&#\"\x06\x1d\x01#54&'&#\"\x06\x1d\x01#54&'&'2\x17632\x16\x17632\x16\x1d\x01\x14\a\x03\x06\x15\x14\x06#!\"&5\x01&=\x014632\x17>\x0132\x176\x03\x005K @0.B @0.B#\x016'&\x1a\x02\x80\x1a&\nl\n@0.B 2'\x0e\t.B A2\x05\bTA9B;h\"\x1b d\x8c\rm\x06pP\xfd\x80Tl\xfe\xccL\x8dc\v\x05\x06\x8b_4.H\x04\x80K5\x80]0CB.\xfeS\x1e\xac0CB.\xe0/#\xfe\xd8'?\x1a&&\x1a\x19)$\x01\xb4$)\xf60CB. }(A\b\x02B.\x80z3M\x05\x01\x802\"61\a\x8fd\xf639\xfeL\x18/PpuT\x01(If\xe0c\x8d\x01_\x82\x15E\x00\x00\x00\x00\x02\x00\x00\xff\x00\x06`\x06\x00\x001\x00X\x00\x00\x00\"\x06\x15\x11#\x114&\"\x06\x15\x19\x01'&#\"\x06\x15\x14\x17\x01\x163!267\x1365\x114&\"\x06\x15\x11#\x114&\"\x06\x15\x11#\x114&2\x16\x17632\x16\x1d\x016\x16\x15\x11\x14\a\x03\x0e\x01#!\"&'\x01&54632\x17\x114632\x176\x03\x9e\\B B\\B\x9a&@5K\x1a\x01\x80&@\x02\xb0\"6\aL\x05B\\B B\\B \xb4\x88s\x1f\x13\x17c\x8di\x97\bL\x0e}Q\xfdP\x01\x03%&#\"\x06\x15\x14\x16\x17\x05\x15!\"\x06\x14\x163!754?\x01\x0327%>\x015\x114&#!\a\x06\x15\x11\x14\x1626=\x013\x15\x14\a\x1e\x01\x15\x14\x06\a\x05\x041\xb1\xa3?\x17>I\x05\xfe\xfbj\x96\x96jq,J[\x96j.-\x02t\x01\x91j\x96lV\xfe\xad\\\x8f\x9b\xa3\x1e$B.\x1a\x14\x01R1?\x01@B.\x1a\x14\xfe\xde\x1c\x12+\x10\x10?2\x14\x12\x01`\x1e$\xe8\xfdv\x18\x165K-%\x02\x0e\xfd\x805KK5\x02\x17\xe9.olRI\x01S+6K5\xfë$B\\B 94E.&\xfeʀ\x8d15\x05\x1euE&\n\x96Ԗ\x11\x1c\x83Pj\x96\x11\xef\x96j\xfddX\x8b\x15U\x17\x02\xc7GJ\x0e7!.B\n\x9a\nP2\xff\x00.B\n\x84\r\b\x1a\x15%\x162@\t\xa0\x0e7\x03\x11\xf8\bK5(B\x0e\xc8@KjKj\xc6?+f\xfc\x00\x13U\vE,\x02\x9c5K~!1\xfe\xd8.>F.\xd0\xd0F,\bQ5*H\x11\x8d\x00\x00\x00\x00\x02\x00\x00\xff\x00\b\x00\x06\x00\x00$\x00b\x00\x00\x012\x16\x17\x01\x16\x15\x11\x14\x06#!\"&=\x01%!\"&=\x01463!7!\"&'&=\x01463\x01\x114'\x01&#!\"\x06\x15\x14\x1e\x01\x17>\x013!\x15!\"\x06\x15\x14\x17\x1e\x013!32\x16\x15\x14\x0f\x01\x0e\x01#!\"\x06\x1d\x01\x14\x163!2\x17\x05\x1e\x01\x1d\x01\x14\x163!26\x04\u007f=n$\x02\x0132\x16\x17\x1b\x01>\x0132\x16\x17\x1e\x01\x15\x14\a\x03>\x0532\x16\x15\x14\x06\a\x01\x06#\x03\"\x06\a\x03#\x03.\x01#\"\x06\x15\x14\x17\x13#\x03.\x01#\"\x06\x15\x14\x17\x13\x1e\x01\x17\x13\x1e\x013!27\x01654&#\"\a\x0554\x1a\x017654&#\"\x06\a\x03#\x13654&\x01\xcbMy\x13e\r\x05t\a|]\x11\x83WS\x82\x14Sg\x14\x82SY\x85\x0e\\x\a{\n7\x160\"1\x19i\x9692\xfe\x05DU1&=\t\xa4\u007f\x91\t=&0@\x03\x84\x1ac\t>&/B\x03t\a\x04\bd\b4!\x02\xb6*\"\x01\xfb8K4+\"\xfe\xcd@H\x03\x04@/'=\tt\x1a\x96\x03?\xff\x00_K\x01\x9193-\x16\x01\xdd\x1b\x1e]\x88\nUlgQ\xfe\xa4\x01\xacQgsW\n\x8a]\x18#\xfe\x00\a+\x10\x1e\v\v\x94i>p&\xfe\x843\x06\x800&\xfdV\x02Z&0B/\x0f\r\xfd\xdd\x01\x98%3B.\x0e\f\xfe\"\x1ct\x1e\xfeo )\x1a\x01{+C4I\x1a\xe6\xe3\x04\x01\f\x01(\r\x12\v/D0&\xfe\x1e\x02p\x0e\x0e0D\x00\x05\x00\x00\xff\x00\x06\x80\x06\x00\x003\x00[\x00_\x00c\x00g\x00\x00\x01\"\x06\x15\x19\x01'&#\"\x06\x15\x14\x17\x01\x163!267\x136=\x014&\"\x06\x15#54&#\"\x06\x1d\x01#54&#\"\x06\x1d\x01#\x114&'2\x16\x1d\x01632\x17632\x17632\x16\x1d\x01\x14\a\x03\x0e\x01#!\"&'\x01&54632\x17\x1146\x13\x11#\x11!\x11#\x11!\x11#\x11\x02\x805K\x97)B4J\x1a\x01\x80&@\x02\xce\x16#\x05\\\x188P8 @0.B J65K J6k\x95\x16\ncJ/4qG\x1b\x1d^\x82\x1c\\\x10hB\xfd2.\xfe\xd81!~K5\x03y\x17?\xa3\xb1^\\\xfe\xadVl\x96j\x01\x91\x02t-.j\x96[J,qj\x96\x96j\xfe\xfb\x05I7$\x1e\xa3\x9b?1\x01R\x14\x1a.B\x87\x10\x10+\x12\x1c\xfe\xde\x14\x1a.B$\x1e\x01`\x12\x142?\x01g\x16\x18\xfdvEo.\xe9\x02\x175KK5\xfd\x80\x02\x0e%-K\xfa\xeb6+\x01SIR[\xfe\xca&.E49 B\\B$\x88\xfe\xcc5K\x00\x00\x00\x00\x02\x00\x00\x00\x00\a\xb4\x04\x00\x00\x19\x00G\x00\x00\x01\x15\x14\x06#!\x11\x14\x06+\x01\"&5\x11!\"&=\x01463!2\x16\x05\x13\x16\a\x06+\x01\"&'\v\x01\x06+\x01\"'\v\x01\x0e\x01+\x01\"'&5\x13>\x01;\x012\x17\x13\x16\x17>\x017\x136;\x012\x16\x03Y\x13\r\xfe\xd6\x12\r\x87\r\x13\xfe\xd7\r\x13\x12\x0e\x03\x19\r\x13\x04\x0eM\x01\t\n\r\x86\f\x12\x01.\xbd\b\x15x\x14\t\xbc-\x01\x12\f\x87\r\n\tN\x01\x12\f\x8e\x14\t\xdc\n\n\x03\r\x04\xdd\t\x14\x8d\r\x12\x03\xe0u\r\x12\xfc\xd4\r\x13\x12\x0e\x03,\x12\ru\x0e\x12\x13\n\xfc?\r\v\n\x11\f\x02L\xfeW\x13\x13\x01\xab\xfd\xb2\f\x11\n\n\x0e\x03\xc1\f\x11\x13\xfd\xf8\x18\x1b\a#\t\x02\b\x13\x11\x00\x00\x00\x00\x04\x00\x00\xff\x00\a\x00\x06\x00\x00\t\x00*\x00:\x00J\x00\x00\x014'&+\x01\x11326\x17\x13\x16\a\x06+\x01\"'\x03#\x11\x14\x06+\x01\"&5\x11463!2\x17\x1e\x01\x15\x14\x06\a\x16\x02 \x04\x06\x02\x10\x12\x16\x04 $6\x12\x10\x02&\x00\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x04\x12UbUI\x06-\xfe\xd4\xfe\xf0\xc5uu\xc5\x01\x10\x01,\x01\x10\xc5uu\xc5\x01ڎ\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x03AX!\x12\xfe\xe7J\xd9\xfe\x8b\x11\x0e\x10\x11\x01m\xfe\xa2\x0e\x12\x12\x0e\x03\xc0\x0e\x12\x18\x1f\x9cf\\\x93$\n\x036u\xc5\xfe\xf0\xfe\xd4\xfe\xf0\xc5uu\xc5\x01\x10\x01,\x01\x10\xc5\xfeK\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x8e\xf0\x00\x00\x04\x00\x00\xff\x00\a\x00\x06\x00\x00-\x00[\x00k\x00{\x00\x00\x01276/\x01&'&\x0f\x01\x0e\x05#\"&54632\x16\x1f\x01\x1676?\x016'.\x04#\"\x06\x15\x14\x16!276/\x01&'&\x0f\x01\x0e\x05#\"&54632\x16\x1f\x01\x1676?\x016'.\x04#\"\x06\x15\x14\x16\x02 \x04\x06\x02\x10\x12\x16\x04 $6\x12\x10\x02&\x00 \x04\x16\x12\x10\x02\x06\x04 $&\x02\x10\x126\x02]\x99h\x0e\v-\x06\x12\x10\v\x04\x04\x0f\x14\x1b\x1e%\x13Lb`J%E\x10\x10\v\x0f\x10\b5\r\x0f\x03\x10,5R-\x94\xc4\xc2\x03\f\x99h\x0e\n-\b\x11\x10\v\x04\x04\x0f\x14\x1b\x1e%\x13Lb`J%E\x10\x10\v\x0f\x10\b5\r\x0f\x03\x10,5R-\x93\xc5\xc2'\xfe\xd4\xfe\xf0\xc5uu\xc5\x01\x10\x01,\x01\x10\xc5uu\xc5\xfd\xa4\x01l\x01L\xf0\x8e\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01/h\x12\x12R\r\x04\x02\r\x03\x04\f\x0f\x0e\f\adMLc\x1c\x0e\x0e\v\x01\x02\fN\x14\x13\x04\x10\x1f\x19\x14\xc1\x90\x92\xbfh\x12\x12R\x0e\x03\x02\r\x03\x04\f\x0f\x0e\f\adMLc\x1c\x0e\x0e\v\x01\x02\fN\x14\x13\x04\x10\x1f\x19\x14\xc1\x90\x92\xbf\x041u\xc5\xfe\xf0\xfe\xd4\xfe\xf0\xc5uu\xc5\x01\x10\x01,\x01\x10\xc5\x01\x15\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x00\x00\x02\x00@\xff\xe0\a\xc0\x05 \x00\v\x00\x17\x00\x00\t\x04\x17\a'\t\x017\t\x03'7\x17\t\x01\a\x01\a\x01\x02\xe0\x01\x80\xfe\x80\xfd`\x02\xa0\xa8`H\xfe \x01\xe0\xc1\xfe\xdf\x02\xa0\x02\xa0\xfd`\xa8`H\x01\xe0\xfe \xc1\x01!`\xfe\x80\x02\xe0\xfe\x80\xfe\x80\x02\xa0\x02\xa0\xa8`H\xfe \xfe \xc1\x01\x1f\x02\xa0\xfd`\xfd`\xa8`H\x01\xe0\x01\xe0\xc1\xfe\xe1`\x01\x80\x00\x00\x00\x00\x03\x00\x00\xff\x00\a\x00\x06\x00\x00\v\x00\x17\x00'\x00\x00%\t\x01\a\x17\a\t\x01\x177'\t\x057'7\t\x01'\a\x00\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x02\xcd\x01\x0f\xfe\xe9X\xc0`\xfe\xe9\x01\x17(W\u007f\xfe:\x03,\x01\xc6\xfe:\xfe\xf1\x01\x17X\xc0`\x01\x17\xfe\xe9(W\x03L\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\xb6\x01\x0f\x01\x17X\xbf`\x01\x17\x01\x17(W\x80\xfe:\xfeB\x01\xc6\x01\xc6\xfe\xf1\xfe\xe9X\xbf`\xfe\xe9\xfe\xe9(X\x01\xf9\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x8e\xf0\x00\n\x00\x00\xff\xdc\t\x00\x05$\x00\v\x00\x13\x00\x1c\x00%\x00/\x009\x00E\x00S\x00[\x00\x80\x00\x00\x01\x14\x06#\"&54632\x16$\x14\x06\"&462\x054&\"\x06\x14\x1626$4&#\"\x06\x14\x162%\x14\x06#\"&462\x16$\x14\x06#\"&4632\x00\x10\x00#\"\x0e\x01\x14\x1e\x0132\x01&! \a2\x1e\x02\x154>\x02\x00\x10\x00 \x00\x10\x00 \x13!\x0e\x01\a\x16\x15\x14\x02\x04#\"&'\x06\a.\x01'\x0e\x01#\"$\x02547.\x01'!6$32\x04\x02\x8b7&'77'&7\x04\x827N77N\xfc'q\xa0qq\xa0q\x04\x81qPOrq\xa0\xfcE\xa3st\xa3\xa4\xe6\xa3\x04\x82\xa3ts\xa3\xa3st\xfc\xdf\xfe\xf1\xbf}\xd4||\xd4}\xbf\x03\xab\xfe\xfe\xd2\xfe\xc1\xfeuԙ[W\x95\xce\x02Q\xfe\xf2\xfe\x82\xfe\xf1\x01\x0f\x01~\x04\x01\u007f,>\tn\x9a\xfe\xf8\x9b\x85\xe8P/R\vU P酛\xfe\xf8\x9an\t>,\x01m\x95\x01\x9c\xe2\xe0\x01\x8a\x02\x1b'77'&77\x02N77N6^Orq\xa0qq\x01\xa0qq\xa0q\xc0t\xa3\xa4棣\x01棣\xe6\xa3\xfe(\x01~\x01\x0f|\xd5\xfa\xd5|\x04\von[\x9a\xd4usј^\xfd\a\x01~\x01\x0f\xfe\xf1\xfe\x82\xfe\xf1\x04\x043\u007f3\x97\xba\x9c\xfe\xf8\x99pc8{\x16y%cq\x99\x01\b\x9c\xba\x973\u007f3dqp\x00\x03\x00f\xff\x00\x04\x9a\x06\x00\x00\t\x00\x13\x00L\x00\x00\x00 \x0054\x00 \x00\x15\x14\x00\"\x06\x15\x14\x162654\x01\x1e\x01\x0e\x02\a\x06\a\x17\x01\x16\x14\x0f\x01\x06\"'&'\x01\x06\"/\x01&47\x017&'.\x0367>\x02\x16\x17\x1e\x04326?\x01>\x01\x1e\x01\x03<\xfe\x88\xfe\xf6\x01\n\x01x\x01\n\xfe\x96\xb8\x83\x83\xb8\x83\x01,\r\x04\r(-'s\xc8I\x01\v\x1e\x1e\f\x1fV\x1fC\xc8\xfe\xf5\x1fV\x1e\f\x1f\x1f\x01\vH\xcbr'-(\r\x04\r\n$0@!\x05\x14BHp9[\xa6%&!@0$\x02u\x01\n\xbb\xbc\x01\n\xfe\xf6\xbc\xbb\x01\x9b\x83]\\\x83\x83\\]\xfd\xa7\x1b-$)!\x19I\x15H\xfe\xf5\x1fV\x1e\r\x1e\x1eD\xc8\xfe\xf4\x1e\x1e\r\x1eV\x1f\x01\vH\x15I\x19!)$-\x1b\x14\x1e\x0e\x12\x1a\x04\x0e#\x1a\x163\x19\x19\x1a\x12\x0e\x1e\x00\x04\x00\x00\xff\x80\x06\x00\x05\x80\x00\a\x006\x00>\x00N\x00\x00\x00\x14\x06\"&462\x01.\x01\x06\a\x0e\x02\"&/\x01.\x01\x06\a\x06\x16\x17\x16\x17\a\x06\a\x06\x14\x1f\x01\x162?\x01\x16\x17\x162?\x0164/\x0267>\x01\x02\x10& \x06\x10\x16 \x01\x11\x14\x06#!\"&5\x11463!2\x16\x03\x9f]\x84]]\x84\x013\n$;\x1f\n&|\x82v\x1b\x1b\x1f;$\n\x16(CS\x8f3\x8e1\x16\x16\t\x16=\x16\xbfrM\x16=\x16\t\x16\x16\xbf4\x8dTC(G\xbe\xfe\xf4\xbe\xbe\x01\f\x02z\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x03\xfe\x84]]\x84]\xfd\xf6\x14\x18\x05\x19\b\x18($\x12\x12\x19\x05\x18\x14-;,5\x0e4\x8e0\x16=\x16\t\x16\x16\xbfsL\x16\x16\t\x16=\x16\xbe4\x0e5,;\x01\x12\x01\f\xbe\xbe\xfe\xf4\xbe\x01\xe8\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x02\x00\x00\xff\x80\x06\xb8\x05\x80\x00\x12\x00(\x00\x00\x012\x16\x15\x11\x14\x02\x06\x04#\"$&\x025\x11463\x0127\x01654&#\"\a\t\x01&#\"\x06\x15\x14\x17\x01\x16\x06\x1dAZ\x88\xe5\xfe\xc1\xaf\xb0\xfe\xc1\xe6\x88\\@\x02\xc1/#\x01\x94%E1/#\xfe\xbd\xfe\xbd#.1E$\x01\x95!\x05\x80[A\xfd\xf9\xb0\xfe\xc0懇\xe6\x01@\xb0\x02\a@\\\xfb\xd8!\x01\x84#21E!\xfe\xca\x016!E13\"\xfe|!\x00\x00\x00\x01\x00\x00\xff\x98\t\x00\x05g\x00L\x00\x00\x05\x01\x06\x00\a\x06&5&\x00'.\x02#4&5!\x15\x0e\x02\x17\x16\x00\x176\x127&\x02'&'5\x05\x15\x0e\x01\x17\x1e\x01\x17676&'6452>\x013\x15\x0e\x01\a\x03\x16\x12\x17\x01.\x02'5\x05\x17\a\x06\a\x00\a\x05\xd6\xfe\xd9\x19\xfe\xf5A\x015R\xfe\xa5V\x15[t,\x01\x02G'Q4\x10\x1a\x01}-\x1f\xda\x16\x13\xd6\x1d&\xa3\x02\x01r!\xd5\r\xe5\a\x01\xb9\x0eG;\x1a\x01\xcc\x01\x01\x8b>\xfd\xf2!g\x02\xb71\xfd\xff\x85\x01\x01\x01\xc1\x03\x14\xca2sV\x05&\b2\x02\x1c:#;\xfc\x90d=\x01\x9b*'\x01\xe45E\x022\x01/\x02..F\xefD֕71\x02\a$\x06\x01\x011\x02>2\xfeF!\xfd\xfe\x11\x03\xf9&1\x0e\x012\x04\x02,\x04\x8d\xfb@K\x00\x05\x00\x00\xff\x00\a\x00\x06\x00\x00\n\x00\x18\x00r\x00\x82\x00\x92\x00\x00\x01\x14\x06#\"&5462\x16\x17\x01\x0e\x04\a\x01>\x04%\x14\a.\x02#\"\x15\x14\x17\x0e\x01\a'&#\"\x06\x1f\x01\x06#\"'>\x0254#\"\x0e\x01\a.\x01'7654&\x0f\x01&547\x1e\x023254&/\x01>\x017\x17\x16326/\x01632\x17\x06\x15\x14327\x1e\x01\x17\a\x06\x15\x14\x16?\x01\x1e\x01\x10\x02&$ \x04\x06\x02\x10\x12\x16\x04 $6\x12\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x03\xb5!\x19\x1a&\"2&\x0f\x01^\tu\x86\x8b_\x03\xfe\xa3\ax\x84\x8c^\x02\x8ah\x03\x1c\x19\x04\r;J݃\x10\x01\x0e\x05\x06\x01\x10HJǭ\x01\x18\x13\r\x06\x16\x17\x02q\x9e\x1fE\n\v\x05D\x0em\x02!\x1b\x04\r\x19\x14\x14M\xe0\x84\x0f\x02\r\x05\x06\x01\x0fG?̯'\f\v%o\x99\x1f8\n\v\x049\x0eU\u007f\xd6\xfe\xd8\xfe\xba\xfe\xd8\xd6\u007f\u007f\xd6\x01(\x01F\x01(\xd6ߎ\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x02\x83\x1a&!\x19\x1a&!S\x02E\bm|\x82[\x06\xfd\xbc\an{\x83[<ɪ\x02\x12\x0f\r\n\"p\x9d C\n\v\x04D\x0fi\x02%\x1e\x04\r\x1d(\x03K\xe1\x84\x0f\x03\f\x05\x06\x01\x0fHCέ\x01\x16\x10\f\x06\x13\f\fp\x9a\x1eC\n\v\x05B\rm8\t\r@Kނ\f\x02\x0e\x05\x06\x01\rH\xe7\x01F\x01(\xd6\u007f\u007f\xd6\xfe\xd8\xfe\xba\xfe\xd8\xd6\u007f\u007f\xd6\x02\x81\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x8e\xf0\x00\x00\x04\x00\x00\xff\x01\a\x00\x06\x00\x00\v\x00\x16\x00\"\x00*\x00\x00\x016\x17\x16\x17%&\x04\a\x016$\t\x01\x16\x047\x03&$\x025\x10%\x16\x12\x02\x06\a\x06%\x016\x02'$2\x16\x14\x06\"&4\x03}\xf0\xd3\xe8x\xfd\x1a\xa0\xfe\xf43\xfe\xec\x80\x01n\xfd\xdd\x01QH\x01\x16\x9a\xe6\xd4\xfe\xa6\xc7\x06\xc4:\x03dΏ\xe6\xfe\xf4\x01\x95X\ve\xfe8\xfa\xb1\xb1\xfa\xb1\x06\x00\x02z\x86\xee'\t\xa7\x92\x01\xa8\x9f\xad\xfel\xfdi\x8f\x94\x1d\xfe=!\xf9\x01\u007f\xdc\x01\v7\x96\xfe\xbf\xfe\xdd\xfdS\x85\x0e\x02o\x83\x01?v\x06\xb1\xfa\xb1\xb1\xfa\x00\x00\x01\x00\x02\xff\x00\a\x00\x05\xc9\x00M\x00\x00\x01 \x00'&\x02\x1a\x017\x03>\x01\x17>\x017\x0e\x01\x17\x1e\x03\x17\x16\x06\a\x0e\x02\a\x17'\x06\x1e\x027>\x02\x17\x1e\x01\a\x0e\x04'\x0e\x01'\x1e\x01>\x0276.\x01'\x1e\x01\x176\x02'\x04\x00\x13\x16\x02\x0e\x01\x04\x03\x87\xfe\xe5\xfeEl:\x12F\x98g\v\vr\r*\xedt6\x83\a\x19K3U\b\x0f\v\x19\x05\x17Z8\x0f\x8b\x12\x153P)3^I%=9\t\x01\x03\x0e\x16)\x1a<\xa9}J\xb1\xa0\x95k\x1b+\bC-Wd\x1b\x0f\x91\x89\x01\t\x01&\x04\x02U\xa2\xd8\xfe\xe9\xff\x00\x01-\xf8\x83\x01T\x01E\x01+]\xfe\xe7\x0e\x03\x11Qr\x02-\xcf<\b\v\x04\x04\x01\x05Q#\a\x170\n\xbdC+M8\x1b\a\t3'\x02\x04:$\x02\a\x12\r\b\x03_Q\v=+\x1fIf5[ˮ&&SG\xaa\x01ZoM\xfek\xfe\xc5\u007f\xff\x00ܬc\x00\x00\x00\x02\x00\x00\xff\x00\a\x00\x06\x00\x00#\x007\x00\x00\x01&#\"\x04\a\x0e\x01\a\x15\x1e\x01\x17\x16\x04327\x06\x04#\"'&$&\x0254\x126$;\x01\x16\x04\x01\x14\x02\a\x06#\"'6\x1254\x02'632\x17\x16\x12\x05ե\u009b\xfe\xecfKY\x04\x04YKf\x01\x14\x9b¥y\xfeͩ\x1d\x0e\xaf\xfe\xc4䆎\xf0\x01L\xb6\x03\xa8\x011\x01\xa4\x9a\x88hv\x89v\x9a\xc7ƚw\x87wk\x87\x97\x05\x1cn\x92\u007f]\xfa\x8d*\x8d\xfa]\u007f\x92nlx\x01\b\x94\xee\x01D\xb1\xb6\x01L\xf0\x8e\x01w\xfc\xf8\xc0\xfe\xab~?T8\x01b\xe4\xe3\x01b9SA}\xfe\xac\x00\x00\x00\x04\x00\x00\xff\x10\a\x00\x05\xf0\x00+\x005\x00?\x00F\x00\x00\x01\x14\a!\x14\x163267!\x0e\x01\x04#\"'\x06#\"\x114767\x12%\x06\x03\x12\x00!2\x17$32\x1e\x02\x15\x14\a\x16\x034&#\"\a\x1e\x01\x176\x01\x14\x16327.\x01'\x06\x01!.\x01#\"\x06\a\x00\a\xfb\x81۔c\xad2\x01\xa78\xe5\xfeΨ\xbb\xa9\xe4\xa6\xed-\x11\\\xc7\x01\x14\xb8\xf3?\x01\xb9\x01\x19\x1e\x0f\x00\xff\xb2@hU0KeFjTl\x92y\xcbE3\xf9\xc6aVs\x97z\xb7.b\x01\xf8\x02\xd8\x05؏\x90\xd7\x02W80\x92\xc5]T\x9f\xf4\x85St\x01\as\xa0<\xa9\x01h\xf6O\xfe\xed\x01\x12\x01_\x01u\x1a7bBt\xaa\xb6\x01\xb0SbF/\xa9o\x87\xfb|V]SHކ\xcd\x02J\x8e\xbe\xbe\x00\x00\x00\x00\x02\x00\x00\xff\x80\a\x80\x05\x80\x00\x0f\x003\x00\x00\x01\x114&#!\"\x06\x15\x11\x14\x163!26\x13\x11\x14\x06#!\x15!2\x16\x1d\x01\x14\x06#!\"&=\x01463!5!\"&5\x11463!2\x16\a\x00\x13\r\xf9\xc0\r\x13\x13\r\x06@\r\x13\x80^B\xfd \x01`\x0e\x12\x12\x0e\xfc\xc0\x0e\x12\x12\x0e\x01`\xfd B^^B\x06@B^\x01 \x03\xc0\r\x13\x13\r\xfc@\r\x13\x13\x03\xcd\xfc@B^\x80\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x80^B\x03\xc0B^^\x00\x00\x00\x00\x02\x00\x16\xff\x80\x06\xea\x05\x80\x00\x17\x00>\x00\x00\x133\x06\a\x0e\x03\x1e\x01\x17\x16\x17\x16\x17\x16\x17!\"&5\x1146)\x012\x16\x15\x11\x14\x06+\x016\x03\x05\x0e\x03\a\x06'.\x02'.\x0167>\x0176\x1e\x03\x17%&\x8a\xc5F8$.\x0e\x03\x18\x12\x13\x04\x023\x1e9_\xfe\xf00DD\x04\xe8\x0140DD0\xb2\xd4\x10\xfe+\x02\x14*M7{L *=\"#\x15\n\x12\x14U<-M93#\x11\x01\xd4D\x05\x80@U8v\x85k\x9d_Y\x13\t\xee[\xabhD0\x05\x180DD0\xfa\xe80D\xd2\x01ce-JF1\f\x1aB\x1bD\xbe\xa3\xa3\xc8N&)@\r\f\v\x17/1 d\xaf\x00\x00\x00\x00\x04\x00\x0e\xff\x00\x05y\x06\x00\x00%\x00F\x00\xab\x00\xc5\x00\x00\x05\a\x06\a\x06#\"'&'&'&'&76\x17\x16\x15\x16\x17\x16\x17\x16\x17\x163276?\x016\x17\x16\x17\x16\x01\a\x17\x16\a\x06#\"/\x01\a\x06#\"/\x01&54?\x01'&7632\x1f\x0176\x17\x16\x05\x14\a\x06\a\x0e\x01\"&'&'&5#&76\x17\x16\x173\x11567632\x16\x15\x14\x06#\"'&76\x1f\x01\x1e\x0132654'&#\"\a\x06\x15\x11\x1632>\x0254'&#\"\a\x06\x0f\x01\x0e\x02'.\x015\x11463!2\x14#!\x113>\x017632\x16\x17\x16\x17\x16\x03\x16\x14\x06\a\x06#\"'&'&#\"\a\x06'&767632\x17\x16\x05y\x06q\x92\x9a\xa3\xa5\x98\x94oq>*\f\x0443\x05\x01\x12\x1c2fb\x80\x84\x90\x8f\x85\x80a\x06\n\x0f\f\x15$\xfe\x15B?\x15\x1c\x11\x0f\n\t>B\x05\n\x0f\x10\x02\x12\bBB\x10\x1e\x12\r\x06\aAA\x12\x1e\x1b\x01\xc7.-QP\xd6\xf2\xd6PR+\x0f\x01\t42\n%<\x01\x03ci\x94\x93\xd0ђ:6\x1c\x0f\x10\x1c\x0e\x0e&\vh\x90HGhkG@n\x84`\xb2\x86I\x8d\x8c\xc7Ȍ5\x18\x02\b\n!\x16\x15\x1f\x15\x11\x03m\x1e\x1e\xfc\xd5\x01(|.mzy\xd6PQ-.\x1f\t\v\v\x1a\r\t\aje\x80\x94\x85\x81\x1b\x12\t\x01\x03\r\x82\xa9\xa4\x98\x89\v\x06q>@@?pp\x92gV\x1c\b\b\x1c\x01\x03ZE|fb6887a\x06\n\x04\x03\x13%\x02RB?\x15\x1c\x11\n=B\x05\x10\x02\x0f\x0e\a\nAB\x10\x1d\x12\x05BA\x11\x1e\x1bJvniQP\\\\PRh!\a\x1b\x11\x10\x1ccD\x01S\x02\x88`gΒ\x93\xd0\x10\v23\b\x03\x03\x06\x8fgeFGPHX\xfecCI\x86\xb0_ƍ\x8c\x8c5\"\x02\v\t\n\b\x05\x17\x0f\x02\xa8\x0f\x17n\xfe\x1d*T\x13.\\PQip\x01\xd0\b\x14\x10\r\x1a\a[*81\n/\x19\r\x10\x049@:\x00\x00\x04\x00\x1d\xff\x00\x06\xe1\x06\x00\x00\x1b\x00>\x00t\x00\x82\x00\x00%6\x16\x14\a\x0e\x04#\".\x03'.\x01>\x01\x16\x17\x16\x17\x04%6%\x16\x06\a\x06\a\x06&7>\x01'.\x03\x0e\x02#\x0e\x03*\x02.\x01'&676\x16\x01\x14\x1e\x02\x1f\x01\a.\x01/\x01&'\x0e\x03.\x0254>\x05754'&#\"\x0e\x03\a%4>\x0332\x1e\x03\x15\x01\x14\x17\x167676=\x01\x0e\x03\x06\x0f\x0f\x16\x0f\r>\x81\x99\xdfvw\ued25d\"\b\x04\x06\n\r\x05\xc0l\x01\x85\x01\x9a\xbe\x01\x98\v\x11\x14\"3\x11\x12\t\x15/\x11\x05\x15!\x1a,\x13+\x01\x06\x0e\b\t\x05\x06\x03\x03\x01\x01\x06j2.|\xfe\x84\x1b%&\x0e\r\xe3(N\x13\x13\v\x0e&w\x88\x90\x83h>8X}x\x8cc2\x15\"W\x06\x15<4<\x12\xfe\xda,Z~\xb1fd\xa2aA\x19\xfd`FBIT\x1e\x0e;hmA<\x06\x06\x1d\x13\x107QC1>[u])\t\x0f\t\x05\x01\x04u1\xb0V(\xd2\x10k1S)\x0e\n\x13-\x99\x16\a\t\x03\x02\x02\x02\x04\x01\x01\x01\x01\x01\x02\x02\x100\x06\a\f\x01\xa9\x1fB2*\v\v\xe0%M\x14\x14\v\x16;W(\x060S\x8f[T\x8c]I)\x1c\t\x02\u007fA 5\x02\x16%R7\x1b&\x1a\x80\x1a&T\x01\xa8\x01,\xfe\xd4\xfeX\xfe\xd4\x02\x00\x0e\x12\x12\x0e\x92\xce\x12\x1c\x12\xa9\x01\xc0\x0f\xfdq\x1a&&\x1a\x02\x8f\x041\xfe\xd4\xfeX\xfe\xd4\x01,\x01\xa8L\x12\x1c\x12Β\x0e\x12\x12\x0ew\xa9\x00\x00\x00\x00\x03\x00%\xff\x00\x06\xdb\x06\x00\x00\x1b\x00%\x00;\x00\x00\x01\x16\x14\x0f\x01\x06#!\"&5\x11463!546;\x012\x16\x1d\x01!2\x17\x01!\x11\x14\x06+\x01\"&5\x012\x16\x15\x11\x14\x06#!\"/\x01&4?\x0163!5!\x15\x06\xd1\n\n\x8d\x1c(\xfa\xc0\x1a&&\x1a\x02@&\x1a\x80\x1a&\x02\x00(\x1c\xfc\xbc\x01\x00&\x1a\x80\x1a&\x03@\x1a&&\x1a\xfa\xc0(\x1c\x8d\n\n\x8d\x1c(\x02\x00\x01\x00\x04\xd7\n\x1a\n\x8d\x1c&\x1a\x01\x00\x1a&@\x1a&&\x1a@\x1c\xfb\xdc\xfe\x00\x1a&&\x1a\x03\xc0&\x1a\xff\x00\x1a&\x1c\x8d\n\x1a\n\x8d\x1c\xc0\xc0\x00\x04\x00\x00\xff\x00\b\x00\x05\xfb\x00\x1b\x00\x1f\x00#\x00'\x00\x00\x01\x16\x15\x11\x14\x06\a\x01\x06'%\x05\x06#\"'&5\x11467\x016\x17\x05%6\x05\x11\x05\x11%\x11%\x11\x01\x11\x05\x11\a\xe4\x1c\x16\x12\xfd\x80\x18\x18\xfd\x98\xfd\x98\n\x0e\x13\x11\x1c\x16\x12\x02\x80\x18\x18\x02h\x02h \xfb\x18\x02@\xfb`\x02 \x04\xe0\xfd\xe0\x05\xf5\x14!\xfa\x80\x14 \a\xff\x00\v\v\xf6\xf6\x05\v\x14!\x05\x80\x14 \a\x01\x00\v\v\xf6\xf6\r\x9a\xfb\n\xe6\x04\xf6\r\xfb\n\xd9\x04\xf6\xfa\xfd\x04\xf6\xd9\xfb\n\x00\x00\x03\x00\x00\xff\x00\a\x00\x06\x00\x00\x11\x00#\x005\x00\x00\x012\x16\x15\x11\x14\a\x01\x06#\"&5\x1147\x016!2\x16\x15\x11\x14\a\x01\x06#\"&5\x1147\x016!2\x17\x01\x16\x15\x11\x14\x06#\"'\x01&5\x1146\x02\x00\r\x13\x11\xfe \a\b\r\x13\x11\x01\xe0\a\x04\xe8\r\x13\x11\xfe \a\b\r\x13\x11\x01\xe0\a\xfb\xa8\b\x06\x02\x00\x12\x13\r\b\x06\xfe\x00\x12\x13\x06\x00\x13\r\xfa@\x14\b\xff\x00\x04\x13\r\x05\xc0\x14\b\x01\x00\x04\x13\r\xfa@\x14\b\xff\x00\x04\x13\r\x05\xc0\x14\b\x01\x00\x04\x03\xff\x00\n\x13\xfa@\r\x13\x03\x01\x00\n\x13\x05\xc0\r\x13\x00\x00\x00\x00\x04\x00\x00\xff \a\x00\x05\x00\x00\a\x00\x0f\x00\x17\x008\x00\x00\x004&\"\x06\x14\x162$4&\"\x06\x14\x162$4&\"\x06\x14\x162\x00\x10\x02\x04#\"'\x06\x05\x06\a\x06&'&7>\a7.\x0154\x12$ \x04\x02\x80KjKKj\x01\xcbKjKKj\x01\xcbKjKKj\x01\xcb\xf0\xfed\xf4ne\xad\xfe\xfa4\"\f\x14\x03\x04\x18\x05%\x0e!\x0f\x1a\x0e\x0f\x05\x92\xa7\xf0\x01\x9c\x01\xe8\x01\x9c\x02KjKKjKKjKKjKKjKKjK\x01.\xfe\xa4\xfe٫\x12\xad8\n\x03\x01\x0e\v\x0f\x16\x05!\x0e%\x1a00C'Z\xfd\x8f\xae\x01'\xab\xab\x00\x00\x00\x00\x05\x00\x00\xff\x00\a\x00\x05\x00\x00\a\x00\x0f\x00\x17\x00.\x00W\x00\x00\x00\x14\x06\"&462\x04\x14\x06\"&462\x04\x14\x06\"&462\x02 \x04\x06\x15\x14\x16\x1f\x01\a\x06\a6?\x01\x17\x1632$6\x10&\x01\x14\x02\x04#\"'\x06\x05\x06\a#\"&'5&6&>\x027>\x057&\x0254>\x01$ \x04\x1e\x01\x02\x80KjKKj\x01\xcbKjKKj\x01\xcbKjKKj\xe9\xfeh\xfe\x9dя\x82W\x1b\x18.\x98{+9E=\xcc\x01c\xd1\xd1\x01Q\xf0\xfed\xf4FK\xc6\xfe\xfa1A\x05\x0f\x18\x04\x03\x05\x01\n\x02\f\x02\a0\x15)\x18\x1e\v\x9d\xb5\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x02\xb5jKKjKKjKKjKKjKKjK\x01\x80\x8b\xec\x89p\xcbJ2`[Q?l&\x06\b\x8b\xec\x01\x12\xec\xfe\x8b\xae\xfe٫\b\xafC\x0e\b\x15\x11\x01\x04\x10\x04\x0f\x03\x0e\x02\b5\x178.H(Y\x01\x06\x96\x82\xed\xacee\xac\xed\x00\x04\x00\x00\xff\t\x04\x00\x05\xf7\x00\x03\x00\x06\x00\n\x00\r\x00\x00\t\x01\x11\t\x01\x11\x01\x19\x01\x01\x11\t\x01\x11\x02\x00\x02\x00\xfe\x00\xfe\x00\x02\x00\xfe\x00\x02\x00\x02\x00\x01Y\x01'\xfd\xb1\xfe\xd8\x03w\xfd\xb1\x01(\x04\x9e\xfd\xb1\xfe\xd8\x02O\xfe\xd9\x01'\xfd\xb1\x00\x00\x00\x01\x00R\xff\xc0\x06\xad\x05@\x00$\x00\x00\x01\x06\x01\x00#\"\x03&\x03\x02#\"\a'>\x017676\x16\x17\x12\x17\x16327676#\"\a\x12\x05\x16\x06\xad\n\xfe\xbe\xfe\xb3\xe5\x8eb,XHU\x12mM\x18\xa8.\x9cU_t\x17,\x167A3ge\b\rz9@x\x01S\xfb\x03\xfa\xec\xfea\xfeQ\x01\a\xa0\x01B\x01\x06Lb\x15\x97(\x8a\b\t\x81\x8b\xfe\xe1V\xf9\xa1\xa1U\x8b\x1a\x01\x89\v\b\x00\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x03\x00\n\x00\x00\x11!\x11!\x01\x03\x13!\x13\x03\x01\x06\x00\xfa\x00\x04=\xdd\xdd\xfd\x86\xdd\xdd\x01=\x05\x80\xfa\x00\x01\xa5\x02w\x01)\xfe\xd7\xfd\x89\xfe\xd0\x00\x00\x00\x00\x04\x00\x00\xff\x80\x06\x00\x05\x80\x00\x03\x00\x12\x00A\x00U\x00\x00\x11!\x11!\x01\a\x17\a\x177\x177'7'#'#\a\x052\x16\a74.\x02#\"\x06\x1d\x01#\x1532\x15\x11\x14\x06\x0f\x01\x15!5'.\x02>\x015\x1137#\"76=\x014>\x02\x015'.\x01465\x11!\a\x17\x16\x15\x11\x14\x06\x0f\x01\x15\x06\x00\xfa\x00\x03\x8c\fK\x1f\x19kk\x19\x1fK\f_5 5\xfe\x96 \x19\x01\xae#BH1\x85\x84`L\x14\n\rI\x01\xc0\x95\x06\x05\x02\x01\x01\xbf&\xe7\x06\x04\x04\x03\f\x1b\x02v6\a\x05\x02\xfe\xed\x17S\x17\f\x0eF\x05\x80\xfa\x00\x04\xc0!Sr\x1999\x19rS!``\xa3 /\x157K%\x0es}H\x80\b\xfe\x82\x0e\f\x01\aXV\x0e\x01\x01\x04\x04\n\x05\x01\x83\x80\x06\x06\x03P\x1b\x1b\x1d\v\xfc\xc3V\t\x01\x03\x03\f\x06\x02\be\x16\a\x14\xfe\x8e\x0e\t\x02\tV\x00\x00\x04\x00\x00\xffd\a\x00\x06\x00\x00/\x009\x00Q\x00[\x00\x00\x01\x14\x06\a\x16\x15\x14\x02\x04 $\x02547.\x0154632\x176%\x13>\x01\x17\x05>\x0132\x16\x14\x06\"&5%\x03\x04\x17632\x16\x01\x14\x16264&#\"\x06\x0164'&\"\a\x0e\x01\"&'&\"\a\x06\x14\x17\x1e\x022>\x01&2654&#\"\x06\x14\a\x00;2\f\xd5\xfe\x90\xfeP\xfe\x91\xd5\v3>tSU<\xda\x01)t\x03\x18\x0e\x01q\x12H+>XX|W\xfe\xb2h\x01,\xdb:USt\xfa\xa2W|XX>=X\x03*\v\v\n\x1e\v)\xa0\xa0\xa0)\v\x1e\n\v\v+\x97^X^\x97\x16|WX=>X\x02\xb2:_\x19.2\x9b\xfe\xf8\x99\x99\x01\b\x9b//\x19a:Ru?\x98\n\x02\t\r\x10\x03Q%-W|XW>J\xfe(\t\x97=u\xfe\xe7>XX|WX\xfe`\v\x1e\v\n\n*((*\n\n\n\x1f\v+2\t\t2\xf8X>=XW|\x00\x00\x00\x01\x00E\xff\x02\x06\xbb\x06\x00\x000\x00\x00\x133>\x03$32\x04\x17\x16\x1d\x01!\x1e\x03>\x017\x11\x06\f\x01'&\x02'&\x127\x0e\x01\a!6.\x04/\x01\x0e\x03E\x01\x10U\x91\xbe\x01\x01\x94\xe7\x01noh\xfb\x9b\x01i\xa8\xd3\xd7\xc9I\\\xfe\xed\xfe\xa2\x8d\xbd\xf5\x02\x03\xe4\xd30<\x10\x02{\b >ORD\x16\x16\x87\xf9ƚ\x02\xe5~\xe7˕V\xd3ƻ\xff\xbco\xa3R \x1aC3\xfe\x877J\x026I\x01`\xc4\xf2\x01Tb<\x83^M~M8\x1a\x0f\x01\x01\x05O\x82\x97\x00\x00\x00\x04\x00\x00\xff\x80\t\x00\x05\x80\x00\t\x00\r\x00\x11\x00\x1b\x00\x005\x11!\x11\x14\x06#!\"&\x01\x15!5!\x15!5\x012\x16\x1d\x01!5463\t\x00^B\xf8@B^\x02\x80\x01\x80\xfd\x00\x01\x00\x06`B^\xf7\x00^B \x02`\xfd\xa0B^^\x01\"\x80\x80\x80\x80\x04\x80^B\xe0\xe0B^\x00\x00\x00\x03\x00\x00\xff\x00\x06\xbb\x06\x00\x00\x1f\x000\x00;\x00\x00%'\x0e\x01#\".\x0154>\x0232\x16\x177&$#\"\x04\x06\x02\x10\x12\x16\x0432$\t\x01\x06\x00!\"$&\x02\x10\x126$3 \x00\x17\x03#\x15#\x1132\x1e\x01\x0e\x01\x060\xdaJ\xf5\x8d\x93\xf8\x90U\x91\xc7n\x83\xe9L\xd7n\xfe\x9fʡ\xfe\xda\xd4~~\xd4\x01&\xa1\xd5\x01q\xfe@\x02\xb5t\xfeK\xfe\xee\xb6\xfe\xb4\xf0\x8e\x8e\xf0\x01L\xb6\x01\x04\x01\xa5}\x9f'`\x88 -\f\n-\xf6ox\x8a\x90\xf8\x92nǑUyl}\xa9\xc0~\xd4\xfe\xda\xfe\xbe\xfe\xda\xd4~\xd6\x02F\xfe\xa0\xfd\xfeڎ\xf0\x01L\x01l\x01L\xf0\x8e\xfe\xf5\xe9\xfet\xa0\x01`(88(\x00\x04\x00 \xff\x00\x06\xe0\x06\x00\x00\x03\x00\a\x00\v\x00\x0f\x00\x00\t\x017!\x01'\x11\x01\x1f\x01\x11\t\x02!\x01\x05\x93\xfd\x9a\\\x03W\xfa\xb5\xb8\x04\x9f\x14\x93\xfd\xec\x01\\\xfe\f\xfc\xa9\x01d\x03;\x01\x82\x97\xfc\xdet\x03Z\xfd\x19`_\xfc\xa6\x01O\x02\u007f\xfc\xde\x02;\x00\x00\x03\x00\x00\xff\x00\x06\x80\x05\xf0\x00\v\x00\x17\x00}\x00\x00\x0154+\x01\"\x1d\x01\x14;\x012%54+\x01\"\x1d\x01\x14;\x012\x05\x11!\x114&\"\x06\x15\x11!\x114;\x012\x1d\x013\x114;\x012\x1d\x01354;\x012\x1d\x01354>\x02\x163\x11&5462\x16\x15\x14\a\x15632\x1632632\x1d\x01\x14\x06#\"&#\"\a\x1526\x1e\x02\x1d\x01354;\x012\x1d\x01354;\x012\x15\x11354;\x012\x02\x80\x10`\x10\x10`\x10\x02\x00\x10`\x10\x10`\x10\x02\x00\xfd\x80p\xa0p\xfd\x80\x10`\x10\x80\x10`\x10\x80\x10`\x10\x80\x05\f\a\x10\x01 !,! -&\x15M\x10\x11<\a\x10F\x1b\x12I\x13(2\x01\x10\a\f\x05\x80\x10`\x10\x80\x10`\x10\x80\x10`\x10\x02\x10\xe0\x10\x10\xe0\x10\x10\xe0\x10\x10\xe0\x10\x10\xfd\x10\x01@PppP\xfe\xc0\x02\xf0\x10\x10p\x02p\x10\x10pp\x10\x10pp\x06\a\x03\x01\x01\x01\x87\x0f#\x17 \x17#\x0f\x11\n\x0f\x0f\x10\xd2\x0f\r\x0f\f\x85\x01\x01\x03\a\x06pp\x10\x10pp\x10\x10\xfd\x90p\x10\x00\x01\x00\x00\x00\x00\t\x00\x05\x80\x00j\x00\x00\x01\x16\x14\a\x05\x06#\"'&=\x01!\x16\x17\x1e\x05;\x015463!2\x16\x15\x11\x14\x06#!\"&=\x01#\".\x05'.\x03#!\x0e\x01#\"&4632\x16\x1732>\x027>\x06;\x01>\x0132\x16\x14\x06#\"&'#\"\x0e\x04\a\x06\a!546\x17\b\xf0\x10\x10\xfe\xc0\b\b\t\a\x10\xfc\xa6%.\x10\x11\x1f\x17\x1f \x11`\x12\x0e\x01@\x0e\x12\x12\x0e\xfe\xc0\x0e\x12` :,.\x1c'\x12\x13\x17\x1c,-\x18\xfe\x98\x16\x8aXj\x96\x96jX\x8a\x16h\x18-,\x1c\x17\x13\x12'\x1c.,: k\x15b>PppP>b\x15k\x11 \x1f\x17\x1f\x11\x10.%\x04Z \x10\x02\xdb\b&\b\xc0\x05\x04\n\x12\x80:k%$> $\x10`\x0e\x12\x12\x0e\xfe\xc0\x0e\x12\x12\x0e`\x14\x1b6&L')59I\"Tl\x96ԖlT\"I95)'L&6\x1b\x149Gp\xa0pG9\x10$ >$%k:\x80\x12\x14\v\x00\x00\x00\x00\x03\x00\x00\xff\x00\a\x00\x06\x00\x00\a\x00\x11\x00!\x00\x00\x00\x14\x06+\x01\x1132\x00\x10&#!\x113\x1132\x00\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x04~O8\xfd\xfd8\x01\x02\xb7\x83\xfeO\xb4\xfd\x82\x02\x87\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x03>pN\x01\r\xfe\xf7\x01\x04\xb8\xfc\x80\x01\r\x01i\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x8e\xf0\x00\x04\x00\x00\xff\xd9\t\x00\x05'\x00'\x00:\x00M\x00a\x00\x00\x014&'\x06\a\x0e\x01#\"'.\x017654.\x01#\"\x06\a\x16\x17\x16\x14\x06\"'&#\"\x06\x14\x163!267\x14\x06#!\"&54676$32\x00\x17\x1e\x01\x17\x14\a\x06#\"'.\x0176\x10'&>\x01\x16\x17\x16$\x10\a\x06#\"'.\x017654'&676\x16\x17\x06mD5\a\x10\a)\x18\f\f\x1f\x1c\n\x17z\xd2{\x86\xe26lP\x16,@\x17Kij\x96\x96j\x04\x16Oo\x99Ɏ\xfb\xea\xa9\xf0ȕ>\x01>\xc3\xeb\x01[\x17t\x99\xfaa\x17)\x18\x13\x1a\f\x12GG\x12\f4?\x12a\x01\x00\x86\x17)\x17\x13\x1a\r\x12ll\x12\r\x1a\x1a>\x12\x01\xb6;_\x15-/\x18\x1c\x03\n9\x1eGH{\xd1z\x92y\x1cN\x17@,\x16K\x95ԕoN\x8e\xc8繁\xe4\x16\xb8\xe4\xfe\xc3\xe7\x19\xbby\xaf\x90!\r\x11?\x1ah\x01\x02h\x1a>$\r\x1a\x8eD\xfe\x18\xc7\"\r\x12>\x1a\xa4\xc2â\x1a?\x11\x12\f\x1b\x00\x02\x00$\xff\x00\x05\xdc\x06\x00\x00\t\x00n\x00\x00\x05\x14\x06\"&5462\x16'\x0e\x01\x15\x14\x17\x06#\".\x0554>\x032\x1e\x03\x15\x14\a\x1e\x01\x1f\x012654.\x04'&'.\x0354>\x0332\x1e\x03\x15\x14\x0e\x03#\"#*\x01.\x045.\x01/\x01\"\x0e\x01\x15\x14\x1e\x03\x17\x1e\b\x05\xdc~\xb4\u007f\u007f\xb4~\xe9s\x9b!\x92\xe9m\xb8{b6#\f\t\x1c-SjR,\x1b\b\x17\x1cl'(s\x96\x12-6^]I\x1c\x0ft\x8eg))[\x86\xc7zxȁZ&\x1e+6,\x11\x02\x06\x13\x1a4$.\x1c\x14\x0fX%%Dc*\n&D~WL}]I0\"\x13\n\x02\rY\u007f\u007fYZ\u007f\u007f\xbf\x0f\xafvJ@N*CVTR3\x0e\x13/A3$#/;'\x0e\"/\x1b\x1e\x02\x01fR\x1a-,&2-\"\r\a7Zr\x89^N\x90\x83a94Rji3.I+\x1d\n\n\x12&6W6\x10\x13\x01\x01>N%\x18&60;\x1d\x1996@7F6I3\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x1f\x00+\x00\x00\x01\x114&#!\"\x06\x15\x11\x14\x163!26%\x114&#!\"\x06\x15\x11\x14\x163!26\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x02\xc0\x12\x0e\xff\x00\x0e\x12\x12\x0e\x01\x00\x0e\x12\x01\xc0\x12\x0e\xff\x00\x0e\x12\x12\x0e\x01\x00\x0e\x12\x01\x80\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01`\x02@\x0e\x12\x12\x0e\xfd\xc0\x0e\x12\x12\x0e\x02@\x0e\x12\x12\x0e\xfd\xc0\x0e\x12\x12\x01\xff\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x04\x00\x00\xff\x80\x06\x00\x05\x80\x00\v\x00\x17\x00'\x007\x00\x00\x00 \x04\x12\x10\x02\x04 $\x02\x10\x12\x00 >\x01\x10.\x01 \x0e\x01\x10\x16%\"&5\x1146;\x012\x16\x15\x11\x14\x06#!\"&5\x1146;\x012\x16\x15\x11\x14\x06#\x02/\x01\xa2\x01a\xce\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01\x9e\x01(\xfa\x92\x92\xfa\xfe\xd8\xfa\x92\x92\x01\xee\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x0e\xfd\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x0e\x05\x80\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xfb\xae\x92\xfa\x01(\xfa\x92\x92\xfa\xfe\xd8\xfaN\x12\x0e\x02@\x0e\x12\x12\x0e\xfd\xc0\x0e\x12\x12\x0e\x02@\x0e\x12\x12\x0e\xfd\xc0\x0e\x12\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x1b\x00\x00\x01\x114&#!\"\x06\x15\x11\x14\x163!26\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04@\x12\x0e\xfd\xc0\x0e\x12\x12\x0e\x02@\x0e\x12\x01\xc0\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01`\x02@\x0e\x12\x12\x0e\xfd\xc0\x0e\x12\x12\x01\xff\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\v\x00\x17\x00'\x00\x00\x00 \x04\x12\x10\x02\x04 $\x02\x10\x12\x00 >\x01\x10.\x01 \x0e\x01\x10\x167\"&5\x11463!2\x16\x15\x11\x14\x06#\x02/\x01\xa2\x01a\xce\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01\x9e\x01(\xfa\x92\x92\xfa\xfe\xd8\xfa\x92\x92n\x0e\x12\x12\x0e\x02@\x0e\x12\x12\x0e\x05\x80\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xfb\xae\x92\xfa\x01(\xfa\x92\x92\xfa\xfe\xd8\xfaN\x12\x0e\x02@\x0e\x12\x12\x0e\xfd\xc0\x0e\x12\x00\x00\x00\x00\x03\x00\x00\xff\x00\a\x00\x06\x00\x00\v\x00%\x00=\x00\x00%\x13\x16\a\x06#!\"'&7\x13\x01\x13!\x13>\x013!\x15\x14\x1626=\x01!\x15\x14\x1626=\x01!2\x16%\x11\x14\x06\"&5\x114&\"\x06\x15\x11\x14\x06\"&5\x1146 \x16\x06\xdd#\x03\x13\x13\x1d\xf9\x80\x1d\x13\x13\x03#\x06]V\xf9TV\x03$\x19\x01\x00KjK\x01\x80KjK\x01\x00\x19$\xfe\x83&4&\x96Ԗ&4&\xe1\x01>\xe1\x80\xfe\xc7\x1c\x16\x15\x15\x16\x1c\x019\x03G\xfc\xf9\x03\a\x18!\x805KK5\x80\x805KK5\x80!\xa1\xff\x00\x1a&&\x1a\x01\x00j\x96\x96j\xff\x00\x1a&&\x1a\x01\x00\x9f\xe1\xe1\x00\x06\x00\x00\xff\x00\b\x00\x06\x00\x00\x15\x00#\x00/\x00;\x00I\x00m\x00\x00\x012\x16\x14\x06+\x01\x03\x0e\x01#!\"&'\x03#\"&463\x01>\x01'\x03.\x01\x0e\x01\x17\x13\x1e\x013%\x114&\"\x06\x15\x11\x14\x1626%\x114&\"\x06\x15\x11\x14\x1626%\x136.\x01\x06\a\x03\x06\x16\x17326\x01\x03#\x13>\x01;\x01463!2\x16\x1532\x16\x17\x13#\x03.\x01+\x01\x14\x06#!\"&5#\"\x06\a\x805KK5\x0fs\bH.\xfb\x00.H\bs\x0f5KK5\x01e\x1a#\x02 \x02)4#\x02 \x02%\x19\x01\xa0&4&&4&\x01\x80&4&&4&\x01` \x02#4)\x02 \x02#\x1a\x05\x19%\xfb~]\x84e\x13\x8cZ\xa7&\x1a\x01\x80\x1a&\xa7Z\x8c\x13e\x84]\vE-\xa7&\x1a\xfe\x80\x1a&\xa7-E\x03\x00KjK\xfdj.<<.\x02\x96KjK\xfc\xe0\x02)\x1a\x01\xa0\x1a#\x04)\x1a\xfe`\x19\"@\x01\xa0\x1a&&\x1a\xfe`\x1a&&\x1a\x01\xa0\x1a&&\x1a\xfe`\x1a&&\x15\x01\xa0\x1a)\x04#\x1a\xfe`\x1a)\x02\"\x04\xda\xfed\x01\xb9Xo\x1a&&\x1aoX\xfeG\x01\x9c,8\x1a&&\x1a8\x00\x02\x00!\xff\x80\x06\xdf\x05\x80\x00\x03\x00O\x00\x00\x01\x13#\x03\x01\a\x06#!\x03!2\x17\x16\x0f\x01\x06#!\x03\x06+\x01\"'&7\x13#\x03\x06+\x01\"'&7\x13!\"'&?\x0163!\x13!\"'&?\x0163!\x136;\x012\x17\x16\a\x033\x136;\x012\x17\x16\a\x03!2\x17\x16\x03\xdf@\xfe@\x03\xfe8\a\x18\xfe\xb9@\x017\x0f\n\n\x048\x05\x1a\xfe\xb9Q\a\x18\xe0\x10\n\t\x03N\xfeQ\a\x18\xe1\x0f\n\t\x03N\xfe\xc9\x0f\n\t\x038\a\x18\x01G@\xfe\xc9\x0f\n\n\x048\x05\x1a\x01GQ\a\x19\xe0\x0f\n\t\x03N\xfeQ\a\x19\xe0\x0f\n\t\x03N\x017\x0f\n\t\x02\x00\x01\x00\xff\x00\x01\xf8\xe0\x18\xff\x00\f\x0e\x0e\xe0\x18\xfe\xb8\x18\f\f\x10\x018\xfe\xb8\x18\f\f\x10\x018\f\f\x10\xe0\x18\x01\x00\f\x0e\x0e\xe0\x18\x01H\x18\f\f\x10\xfe\xc8\x01H\x18\f\f\x10\xfe\xc8\f\f\x00\x00\x00\x00\x04\x00k\xff\x00\x05\x95\x06\x00\x00\x02\x00\x05\x00\x11\x00%\x00\x00\x01\x17\a\x11\x17\a\x03\t\x03\x11\x03\a\t\x01\x17\x01\x00\x10\x02\x0e\x02\".\x02\x02\x10\x12>\x022\x1e\x02\x03I\x94\x95\x95\x94\x83\x01\xd0\xfe\xce\x012\xfe0\xff]\x01@\xfe\xc0]\x00\xff\x02\xcf@o\xaa\xc1\xf6\xc1\xaao@@o\xaa\xc1\xf6\xc1\xaao\x01㔕\x03\x8c\x95\x94\xfca\x01\xd0\x012\x012\x01\xd0\xfd\x9d\x00\xff]\xfe\xbf\xfe\xbf]\x00\xff\x01p\xfe^\xfe\xc7\xc9|11|\xc9\x019\x01\xa2\x019\xc9|11|\xc9\x00\x00\x00\x00\x03\x00(\xff\x00\x03\xd8\x06\x00\x00\x02\x00\x05\x00\x11\x00\x00%7'\x117'\x13\t\x01\x11\x01'\t\x017\x01\x11\x01\x02T\xad\xad\xad\xad \x01d\xfd\xe5\xfe\xd7l\x01t\xfe\x8cl\x01)\x02\x1bq\xac\xac\x01n\xac\xac\xfd\xf1\xfe\x9c\xfd\xe4\x02\xc7\xfe\xd8l\x01u\x01ul\xfe\xd8\x02\xc7\xfd\xe4\x00\x05\x00\x00\xff\x80\x06\x00\x05\x80\x00\a\x00\x0f\x00\x17\x00)\x001\x00\x00$4&\"\x06\x14\x162\x004&\"\x06\x14\x162\x00\x10\x06 &\x106 \x13\x14\a\x01\x06+\x01\"&547\x016;\x012\x16\x04\x10\x06 &\x106 \x05\x00LhLLh\xfdLLhLLh\x04L\xe1\xfe\xc2\xe1\xe1\x01>\x81\r\xfb\xe0\x13 \xa0\x1a&\r\x04 \x13 \xa0\x1a&\xfd`\xe1\xfe\xc2\xe1\xe1\x01>\xcchLLhL\x03LhLLhL\xfe\x1f\xfe\xc2\xe1\xe1\x01>\xe1\x02\xc0\x14\x12\xfa\x80\x1a&\x1a\x14\x12\x05\x80\x1a&\xbb\xfe\xc2\xe1\xe1\x01>\xe1\x00\x00\x00\x05\x00\x03\xffG\x06\xfd\x05\xb9\x00\x06\x00\n\x00\x10\x00\x17\x00\x1d\x00\x00\x13\t\x01.\x017\x13)\x01\x011\x01\x13!\x1362\x01\x13\x16\x06\a\t\x011!\x1362\x17h\x03\x18\xfc\x9c\x12\x0e\ae\x01\xce\x02\x94\xfe\xb6\xfd\xf0\xc6\xfe2\xc6\b2\x050e\a\x0e\x12\xfc\x9c\x03\x18\xfe2\xc6\b2\b\x03>\xfc\t\x02v\r+\x15\x014\xfc\t\x06[\xfd\x9c\x02d\x17\xfd\x85\xfe\xcc\x15+\r\xfd\x8a\x03\xf7\x02d\x17\x17\x00\x00\x00\x04\x00\x00\xff \a\x00\x05\xe0\x00\x03\x00\x0f\x00\x13\x001\x00\x00\x0135#\x015\x06\a\x06&'\x17\x1e\x0172\x01!5!\x05\x14\a\x16\x15\x14\x04#\"&'\x06\"'\x0e\x01#\"$547&54\x12$ \x04\x12\x01\x80\xa0\xa0\x03Eh\x8b\x87\xf9`\x01X\xf8\x94\x81\xfe(\x02\x80\xfd\x80\x04\x80cY\xfe\xfd\xb8z\xce:\x13L\x13:\xcez\xb8\xfe\xfdYc\xf0\x01\x9d\x01\xe6\x01\x9d\xf0\x02\xc0\xe0\xfd\xd4\\$\x02\x01_K`Pa\x01\x01}\xe0\xc0\xbb\xa5f\u007f\x9d\xdeiX\x01\x01Xiޝ\u007ff\xa5\xbb\xd1\x01a\xce\xce\xfe\x9f\x00\x00\x00\x00\t\x00\x00\xff\x80\x06\x00\x05\x80\x00\x03\x00\a\x00\v\x00\x0f\x00\x13\x00(\x00+\x00.\x00>\x00\x00\x01\x15#5\x13\x15#5\x01\x15!5\x01\x15!5\x01\x15!5\x01\x114&+\x01\x01'\a\x01#\"\x06\x15\x11\x14\x163!26\x017!\x057!\x05\x11\x14\x06#!\"&5\x11463!2\x16\x02\x03\xfc\xfc\xfc\x03\xf2\xfe\xab\x01U\xfd`\x02\xa0\xfd`\x03'\f\b \xfe\x86\xd2\xd2\xfe\x86 \b\f\f\b\x04\xd8\b\f\xfc\xa9\xb9\xfej\x02\x8b\xdd\xfej\x02\xe2V>\xfb(>VV>\x04\xd8>V\x02q\x80\x80\x00\xff\u007f\u007f\xfe\x01\x80\x80\x01\x00\x80\x80\x00\xff\u007f\u007f\xfc\xa4\x04\xd8\b\f\xff\x00\xab\xab\x01\x00\f\b\xfb(\b\f\f\x04^\x96\x96\x96\x14\xfb(>VV>\x04\xd8>VV\x00\x00\x00\x02\x00\x00\xff\x00\a\x00\x06\x00\x00\x1f\x00=\x00\x00\x01&'&'&'&\x06\x1f\x01\x1e\x03\x17\x16\x17\x1e\x04\x17\x1676'&'&\x02\x01.\x05\x02' \f\x01\x1e\x03\x0e\x01\a\x06\x15\x01#\x01\x0e\x02.\x02\x03\x80h8\x8b\xd0\"$Y\n''>eX5,\t\x04,Pts\x93K\x99\x01\x0125\x1cM\xcc\xfeRLqS;:.K'\x01\x11\x01\xc1\x015\xe9\x8aR\x1e\x05\x0e\r\r\x01Ch\xfe\xe7\x16\x8bh\xac\x95\xba\x02\xd0\xc4R\xcat\x13\x11(\x10\x1e\x1f+e\x84^T\x11\bT\x8a\xaa\x82u B\x06\x03\"$\x15:\x012\xfe~<\x82\x9d\x98\xdc\xc6\x012\x88Hp\xb1\xa8\xe5\xaa\xe3wTT\x17\xfe\xb9\x01\x1d\x02\x18\x0e\x02 V\x00\x00\x05\x00\x00\xff\x00\a\x00\x06\x00\x00/\x007\x00G\x00W\x00g\x00\x00\x00.\x01\a\x04 %&\x0e\x01\x16\x17\x16\x17\x0e\x02\x0f\x01\x06\x16\x17\x1632?\x01673\x16\x1f\x01\x16327>\x01/\x01.\x02'676$4&\"\x06\x14\x162\x04\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x00 \x04\x06\x02\x10\x12\x16\x04 $6\x12\x10\x02&\x00\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x05d\f-\x1a\xfe\xfb\xfe\xe8\xfe\xfb\x1a-\f\x1b\x1a\xc2m\x02\x1b\x1a\x1c\t\n\x16\x19\t\x0e,\x10\b6\x11*\x116\b\x10,\x0e\t\x19\x16\n\t\x1c\x1a\x1b\x02m\xc2\x1a\xfe\xb7KjKKj\x02\x8bo\xbd\xfe\xfb\xfe\xe2\xfe\xfb\xbdoo\xbd\x01\x05\x01\x1e\x01\x05\xbd\xfeK\xfe\xc8\xfe\xe4\xcezz\xce\x01\x1c\x018\x01\x1c\xcezz\xce\x01Ȏ\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x03U4\x1b\x06>>\x06\x1b4-\x06.\f\x9e\xdeYG\x15\x190\n\x04)\x14\x8bxx\x8b\x14)\x04\n0\x19\x15GYޞ\f.\x06\xa3jKKjKq\xfe\xe2\xfe\xfb\xbdoo\xbd\x01\x05\x01\x1e\x01\x05\xbdoo\xbd\x01lz\xce\xfe\xe4\xfe\xc8\xfe\xe4\xcezz\xce\x01\x1c\x018\x01\x1c\xce\xfe0\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x8e\xf0\x00\x00\x00\x03\x00D\xff\x00\x05\xbb\x06\x00\x00/\x007\x00H\x00\x00\x00\x16\a\x03\x0e\x01#\"'.\x017\x13\a\x16\x15\x14\a'654&#\"\a'67\x01'\a\x06.\x016?\x01>\x01\x17\x01\x16\x17\x16\x0f\x01%\x02\"&462\x16\x14\x0127\x17\x06#\".\x01547\x17\x06\x15\x14\x16\x05|D\x05,\x04=)\x06\x03,9\x03#\x8f7\x94\x89[͑\x86f\x89x\xa4\x01\b\x95\xb5!X:\x05 \xef\x1aD\x1e\x01\xe8$\f\x11+\xcd\x01s)\x94hh\x94i\xfc\xdajZ\x8b\x92\xbd\x94\xfb\x92t\x8b<\xcd\x02\xf6F/\xfd\xd9*8\x01\x03C,\x01\xad\bq\u007f\u061c\x89e\x86\x91\xce\\\x8ar\x1b\x01,W\xa1\x1e\x05BX\x1d\xd5\x17\a\x12\xfe\xe5\x15/C2\xe8\x14\x01\xa9h\x94hh\x94\xfa\xbe=\x8bt\x92\xfa\x94\xbc\x94\x8bXm\x91\xcd\x00\x00\x00\x04\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00>\x00N\x00Z\x00\x00\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x14\x0e\x02\a\x0e\x02\x1d\x01\x14\x06+\x01\"&=\x014>\x037>\x0154&#\"\a\x06\a\x06#\"/\x01.\x017632\x16\x02 \x0e\x02\x10\x1e\x02 >\x02\x10.\x01\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x03p\x12\x0e\xa0\x0e\x12\x12\x0e\xa0\x0e\x12\x01\x00\x1e=+& \x1d\x17\x12\x0e\xa0\x0e\x12\x15\x1b3\x1f\x1d5,W48'\x1d3\t\x10\v\bl\n\x04\az\xe3\x81\xdb\xee\xfe\xfc\xed\xabff\xab\xed\x01\x04\xed\xabff\xab\x01\x91\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01P\xa0\x0e\x12\x12\x0e\xa0\x0e\x12\x12\x01\xe22P:\x1e\x15\x12\x14\x1c\x0f \x0e\x12\x12\x0eD#;$#\x10\r\x19$\x1f*;\x1b\x14?\f\x06R\a\x1a\n\xc0\xb3\x01Cf\xab\xed\xfe\xfc\xed\xabff\xab\xed\x01\x04\xed\xab\xfe\xb7\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x04\x00'\xff\x03\x05Y\x06\x00\x00\t\x00>\x00O\x00`\x00\x00\x00\"&5462\x16\x15\x14\x01\x14\x06&'\x01.\x01\x0f\x01\x06\x1f\x01\x13\x03\x06\a\x06\a\x06'.\x0176\x1b\x01\a\x17\x16\x0e\x02\x0f\x01\x06.\x035\x03\x13632\x17\x01\x16\x1f\x01\a\x16\x05\x1e\x01\x1f\x01\x16\x17\x16\a\x06.\x01'#&'\x03\x01\x16\x15\x14\a\x06.\x01'&\x01\x166?\x0165\x01\xae\x80\\\\\x80[\x01\x8c(\t\x01\x06\x02|\x03\x93\x1f\x03\t\v\x14\x06r\xfe\xcb\x03\b\x03\x03\v\x04\xc9[A@[[@A\xfd#2#\x16\x17\x01\xb6\f\a\x02\x03\b\r\x8b\xfe\x9e\xfe7\xc0*\x1a\x06\x1a\x19\r<\x1b\x11\x02Y\x01\xa0\xa4\xde\x18$\x13\r\x01\x02\x03\f\x14\x18\x0f\x02\x01+\x01}\"(\xfd\xf7\x05\f\x03\x01\r\xa6q\xe087] F\x1b\x16\f \x13\x10\t\x01_\xfe\xad1\b\x05\x02\x05\v)\n\xac\x01\xe9\x01\x04\x02\x02\t\b\x00\x00\x00\a\x00\x03\x00\xe3\t\x00\x04\x1c\x00\x02\x00\v\x00#\x001\x00K\x00e\x00\u007f\x00\x00\x013\x03\x054&+\x01\x11326\x01\x13\x14\x06+\x01\"&=\x01!\a\x06#!\"&7\x0163!2\x16\x04\x10\x06#!\"&5\x11463!2\x01\x14\x0e\x03\a#>\x03?\x014.\x03'3\x1e\x03\x1f\x01\x14\x0e\x03\a#>\x03?\x014.\x03'3\x1e\x03\x1f\x01\x14\x0e\x03\a#>\x03?\x014.\x03'3\x1e\x03\x17\x01\xf8\xab\x01\x03Xe`64[l\xfd\xc2\x01\x13\x0e\xd8\x0e\x13\xfe\xdd7\n\x12\xfe\xf5\x15\x13\r\x02,\t\x12\x01L\x0e\x14\x03;\xfb\xc7\xfe\xf2\x0e\x14\x14\x0e\x01\f\xc8\x01\x98\x01\x0f\x1c=+3&9\x1a\x10\x01\x01\x01\x0e\x1a8&+)>\x1d\x11\x02\xb9\x01\x0f\x1c>+3&9\x1a\x10\x01\x01\x01\x0e\x198&+)>\x1d\x11\x02\xb6\x01\x0f\x1c=+3&8\x1a\x10\x01\x01\x01\x0e\x198&+)>\x1d\x11\x01\x02\x1e\x01\t\xa6Wj\xfe|r\x01\xca\xfd\f\x0e\x14\x14\x0e>Q\x0f$\x11\x02\xf5\x0e\x14\xc6\xfe~\xdc\x14\x0e\x02\xf4\x0e\x14\xfed\v$kaw+-wi[\x1b\x1b\b\x1d[\\\x83;/xgY\x1a\x1a\v$kaw+-wi[\x1b\x1b\b\x1d[\\\x83;/xgY\x1a\x1a\v$kaw+-wi[\x1b\x1b\b\x1d[\\\x83;/xgY\x1a\x00\x04\x00\x00\xff\x00\x05\x80\x05\xf2\x00J\x00\\\x00m\x00\x82\x00\x00\x054.\x01'.\x02'&#\"\x06#\"'.\x03'&47>\x037632\x16327>\x027>\x0254&'&#\"\a\x0e\x03\a\x06\a\x0e\x01\x10\x16\x17\x16\x17\x16\x17\x16\x17\x16327>\x01\x13\"&47654'&462\x17\x16\x14\a\x06\x16\"'&476\x10'&462\x17\x16\x10\a\x16\"'&47>\x01\x10&'&462\x17\x16\x12\x10\x02\a\x02i\x1a$\x02\x01\b\t\t\x0f$\x17^\x18\"\r\x06\n\x05\b\x01%%\x01\b\x05\n\x06\r\"\x18^\x17$\x0f\t\t\b\x01\x02$\x1aW \x14\x19\"@9O?\x1d\x1f\x06\x031&&18\x1b?t\x03\x03@\"\x19\x14 W\x9f\x1a&\x13%%\x13&4\x13KK\x15\xb86\x12\x13\x13pp\x13&4\x13\x96\x96\xa36\x12\x13\x13ZaaZ\x13&4\x13mttm\x99\v^x\t\x04-\x1b\b\x0e\v\v\x05\x15\x13\x1d\x04\x80\xfe\x80\x04\x1d\x13\x15\x05\v\v\x0e\b\x1b-\x04\tx^\v\x16=\f\b\x12\x11/U7C\f\ak\xda\xfe\xf2\xdakz'[$\x01\x01\x12\b\f=\x03\xa7&5\x13%54'\x134&\x13K\xd4K\x13\xb5\x13\x134\x13r\x01\x027>\x0254\x00 \x00\x15\x14\x06\"&54>\x022\x1e\x02\x04\x14\x06\"&462%\x14\x06\"&54&#\"\x06\x15\x14\x06\"&546 \x16%\x16\x06\a\x06#\"&'&'.\x017>\x01\x17\x16\x05\x16\x06\a\x06#\"'&'.\x017>\x01\x17\x16\x80&4&&4\xe6&4&&4S\x01\x00Z\xff\x00\x01\xad&4&&4\x02\xe9\x174$#\x1f\x1d&\x0f\xe1\x9f\x1a&&\x1aj\x96\x173$\"('$\xfe\xf9\xfe\x8e\xfe\xf9&4&[\x9b\xd5\xea՛[\xfd\xfd&4&&4\x01F&4&\x83]\\\x84&4&\xce\x01$\xce\x01\x8a\n\x16\x19\t\x0e\x13!\aD\x9c\x15\b\x10\x114\x15\xb7\x01%\t\x15\x19\v\f,\x10\\\xcd\x16\a\x10\x104\x15\xeb\xa64&&4&\x9a4&&4&\x01-\xff\x00Z\x01\x00\x874&&4&\x01\x00;cX/)#&>B)\x9f\xe1&4&\x96j9aU0'.4a7\xb9\x01\a\xfe\xf9\xb9\x1a&&\x1au՛[[\x9b\xd5\xdb4&&4&@\x1a&&\x1a]\x83\x83]\x1a&&\x1a\x92\xceΏ\x190\n\x04\x16\x13\xb2u\x104\x15\x15\b\x10\x89\x85\x190\n\x04)\xee\x9b\x104\x15\x16\a\x10\xaf\x00\x00\x00\x00\x04\x00\x03\xff\x00\b\xfd\x06\x00\x00\x11\x00#\x00g\x00\xb0\x00\x00\x01&'.\x01#\"\x06\x15\x14\x1f\x01\x1632676%4/\x01&#\"\x06\a\x06\a\x16\x17\x1e\x01326\x01\x0e\x01'&#\"\a2632\x16\x17\x16\x06\a\x06#2\x17\x1e\x01\a\x0e\x01+\x01&'%\a\x06#\"'\x03&6?\x01\x136\x1276\x1e\x01\x06\a\x06\a676\x16\x17\x16\x06\a\x06\a632\x17\x1e\x01%\x13\x16\x06\x0f\x01\x03\x06\x02\a\x06#\"'&6767\x06\a\x06#\"&'&6767\x06#\"'.\x017>\x01\x17\x16327\"\x06#\"&'&6763\"'.\x017>\x01;\x02\x16\x17\x057632\x04\b;\x19\x11>%5K$\n\"0%>\x11\x19\x02s$\n\"0%>\x11\x19;;\x19\x11>%5K\xfeV\x11L#>H30\x03\r\x03\\\x9d(\x11\x1b$\x12\x15\x15\x12$\x1b\x11(\x9d\\\x06\x10\x1c\xfe\xde\xef\x0e\x0f(\x11\xa0\v\x0e\x16є\x11\x95y\x1fO2\a\x1fF/{\x90(?\x04\x050(TK.5sg$\x1a\x03\xb1\xa0\v\x0e\x16є\x11\x95y\x1a#-\x1d\x19\a\x1fF/{\x90\x04\b$7\x04\x050(TK.5sg$\x1a\x12\x11L#>H30\x03\r\x03\\\x9d(\x11\x1b$\x12\x15\x15\x12$\x1b\x11(\x9d\\\x06\x01\x0e\x1c\x01#\xef\x0e\x0f(\x02@\x025\"'K58!\b\x1f'\"5\x828!\b\x1f'\"5\x02\x025\"'K\x01\x12#\x1a\x11\x1f\x11\x01dS$K\x11\t\t\x11K$Sd\x02\x02\x1bx\a#\x01@\x171\rw\x01\v\x9b\x01\x11d\x19\a>N\x1a;ET\x11\x050((?\x04\n-\n2\x12K|\xfe\xc0\x171\rw\xfe\xf5\x9b\xfe\xefd\x16#\x1fN\x1a;ET\x11\x010$(?\x04\n-\n2\x12K$#\x1a\x11\x1f\x11\x01dS$K\x11\t\t\x11K$Sd\x02\x02\x1bx\a\x00\x00\x00\x04\x00\x00\xff\x00\a\x00\x06\x00\x00\x13\x00D\x00N\x00\\\x00\x00\x01\x14\x162654& \x06\x15\x14\x16265462\x16\x02\"\x0e\x02\x15\x14\x162654\x00 \x00\x15\x14\x0e\x01\a\x0e\x03\x15\x14\x06#\"\x06\x14\x1632654>\x027>\x0354.\x01\x01\x17\x01\x06\"/\x01&47\x01\x17\x16\x14\x0f\x03&'?\x0162\x04 &4&\xce\xfe\xdc\xce&4&\x84\xb8\x84h\xea՛[&4&\x01\a\x01r\x01\a$'(\"$3\x17\x96j\x1a&&\x1a\x9f\xe1\x0f&\x1d\x1f#$4\x17[\x9b\xfd\xc2\xe2\xfd\xbd\f\"\f\xa8\f\f\x06@\xa8\f\f\xe9\x1aGB\x81[\xcf\r\"\x02\xc0\x1a&&\x1a\x92\xceΒ\x1a&&\x1a]\x83\x83\x01\xe3[\x9b\xd5u\x1a&&\x1a\xb9\x01\a\xfe\xf9\xb97a4.'0Ua9j\x96&4&\xe1\x9f)B>&#)/Xc;u՛\xfd\x8c\xe2\xfd\xbd\f\f\xa8\f\"\f\x06\x06\xa8\f\"\r\xe9\x19G\x99i[\xcf\f\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x14\x00X\x00h\x00\x00\x01\x14\a\x0e\x01\a\x0e\x01\a\x06#\"&5467632\x16\x014&'&#\"\a'>\x0154#\"\a\x0e\x02\x15\x14\x1632\x14\a\x06\a\x0e\x01#\"54>\x0354'.\x01#\"\x0e\x01\x15\x14\x1632>\x017>\x01767632\x17\x16326\x13\x11\x14\x06#!\"&5\x11463!2\x16\x03b\r\v)\n\x02\x05\v\x14\v:4FD\x1c\x17\x1c\x11\x01\xe6N\r\x15\r[\x87\x02\x031\xf2\x18,^\x95J\xa1\x93\x19\x01\x04\x16\x0eK-*\x15\x1d\x1e\x16\a\x18E\x1f#9\x19gWR\x92Y\x15\x06\x13\x05\x03\vvm0O\x01\x03\x05\t\xb8\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x03\xfd\x1bC2\xc82\v\x03\x01\x02c@X\xac&\x0e!\xfe9\x0e{\x05\bM\x02\x16\xe2A\xe9\x06\x11\x91\xbc_\x92\x9e\x06\x02\"S4b/\x18/ \x19\x0f\x01\x03\a\x16\x1dDR\"Xlj\x92P\x16Y\x16\f\x06<\x12\x01\t\x02\x0f\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x00\x02\x00%\xff\x00\x05\xda\x05\xff\x00\x19\x00e\x00\x00\x014.\x02#\"\a\x06\x02\x15\x14\x1e\x0232\x16>\x0276\x1276\x01\x14\x06#'.\x02#\"\a\x06\a\x0e\x01\a\x0e\x03#\"&54>\x0132\x16\x17\x14\x0e\x03\x15\x14\x1632>\x03754&*\x01\x06#\"&54>\x02763 \x11\x14\x02\a\x17>\x0132\x17\x1e\x01\x02\xe8\x04\r\x1d\x17''il\x11$E/\x04\x1c\f\x14\n\x02\x10@\x10\x13\x02\xf2\x0f\b\x06\x16P@\x1f\xa7\xb8\x0f\x06\n\x1d\b\x17^\x83\xb2`\x87\x9f'W6&\xa4\x01!.. ! -P5+\x16\x05\a\n\n\n\x01\xe3\xfaE{\xbdn46\x01vL\x05\x03e\xa3V\x16\x1f\x13z\x04\xcf\x18\x1d\x1f\x0f\x17:\xfe\xf7\x89,SN/\x01\x01\x05\f\nM\x015M[\xfd\xa7\a\r\x01\x03\x10\t]\b\x13$\x8b\x1f[\xb1\x98^\xa7\x885\x80iC\x1c\x01\x17'2H&!(?]v`*\t\x02\x03\x01\xf5\xe2l\xe2\u008d\x13\t\xfe\x98b\xfe\xa2$\x039>\r\a\xbf\x00\x03\x00\x01\xff\x00\x06\u007f\x05\xfb\x00=\x00R\x00\x87\x00\x00\x012\x1f\x01\x16\x1f\x01\x16\a\x03\x0e\x01\a\r\x01#\"&5467%!\"&7>\x013-\x01.\x017>\x01;\x01\x05%.\x017>\x0132\x17\x05\x172\x16326/\x01.\x0176\a\x17/\x02\x03.\x01'&676\x16\x1f\x01\x0e\x01\a\x06\x16\x01\x13\x16\x0f\x01\x06\x0f\x016/\x01&/\x01&#\"\a\x03&676\x16\x17\t\x01&676\x16\x17\x13\x03&676\x16\x17\x13\x17\x1e\x016/\x01&672\x16\x03? \x1b\xde=1\x92(\vH\x06/ \xfd\xf1\xfe\xa0\t'96&\x01\x04\xfe@)9\x02\x02<'\x01\xba\xfd\xf7)2\x06\x069%\n\x01\xe1\xfe\xa1&0\x06\x066#\x06\x0e\x01\xc0\xd9\x01\x04\x01\x17\x0f\x14\xba#\x0e\x19\x1b\x15\xba\xda\x05$\xee\x01\x03\x01\x18\v \x1fJ\x1b\x8e\x02\x06\x01 \x12\x03\xa5\x0f\x04\x0f0\f7j\x02)\x925@\xde\"*3%\xeb\x19\x0e\"!M\x18\x01\n\xfe\xfa\x15\x15%#K\x14\xf1\x88\x0f\x15\"%N\x11\xc1e\b\x1e\x18\x01\f\x028)'8\x03_\x12\x94(9\xaa.<\xfec +\x048 8(%6\x05 <)'4\x01@\x05@)#-<^\n?%$-\x02`%\x01.\r}\x17Q!&\xca}%\x02&\x01\x06\x01\x05\x01\x1fN\x19\x17\v\x1c\x93\x01\x05\x02-l\x01\xa7\xfe\xf6IJ\xdb;\x1c6>/\xaa=*\x94\x17%\x018!Q\x17\x16\x10 \xfe\xa0\x01\xc7#P\x13\x12\x18\"\xfe\\\x01Q#N\x11\x13\x1a&\xfea\xc4\x0f\x05\x14\x10\xe0)<\x019\x00\x00\x04\x00\x00\xff\x1e\a\x00\x05b\x00R\x00]\x00m\x00p\x00\x00%\"'.\x01'&54>\x0676%&547632\x1f\x0163 \x00\x17\x16\x14\a\x0e\x01\a\x16\x15\x14\a\x06#\"/\x02\x017\x06\a\x16\x1a\x01\x15\x14\a\x06#\"'\x01\x06\a\x16\x00\x15\x14#\"&/\x01\x03\x06\a\x1e\x01\x17\x13\x14%\x17$\x13\x02%\x1e\x01\x15\x14\x06\x00\x14\x1632\x16\x15\x14\x162654&#\"%'\x17\x01O\x02\x04V\xa59\x15\x04\x04\n\a\x0e\x06\x12\x02\xb8\x01\fn\x11t\f\x12\n|\\d\x01\n\x01ϓ\x14\x14[\xff\x97n\x11t\v\x13\n|@\xfeD\a:)\x03\xf8\xee\t\r;9\x03\xfe8'+\x18\x01|\v\x0e\x89\x04j\xe0,\"\x02 \a\xb0\x0341\x01\x11\xb1\xb4\xfe\xe9CH^\xfen\x1c\x14Vz\x1c(\x1c\xb2~\x14\x01R\t\a\xb4\x029\xb0\\\x1e'\t\x14\x10\x14\f\x16\b\x17\x03\xfbr\xc6\r\x13\n@\x10\xe5\x13\xfe\xed\xe8\x1fL\x1f\x8e\xdf@\xc6\r\x14\t@\x10\xe5w\x034\a\x18\x17\x05\xfe6\xfeH\x03\a\x02\x03\a\x03I\x1c(+\xfdC\x04\n,\x06\xc5\x01\x9d55\x03,\f\xfe\xb9\nf[o\x01\x12\x01\x15p@\xa9\\j\xbd\x02;(\x1czV\x14\x1c\x1c\x14~\xb2\x11\x04\a\x00\x00\x00\x00\x04\x00\x00\xff\x97\x04\xfe\x05i\x00\x1f\x00/\x005\x00O\x00\x00\x01\x14\a\x06#\"'&54>\x0132\x17\x06\a&#\"\x06\x15\x14\x16 654'67\x16'\x14\x02\x0f\x01\"'>\x0454'\x16'\x15&'\x1e\x01\x13\"'6767\x0e\x01\a&546767>\x017\x16\x15\x14\a\x0e\x01\x04\x1a\x93\x94\xe6蒓\x88\xf2\x93`V \aBM\xa7\xe3\xe1\x01R\xe0 B9)̟\x9f\x0e\x1d!S\u007fH-\x0f\x0377I\x85Xm\xfdSM\xdaH\x13\x02*\xc3k#\"\x1a.o;^\x1bJ\x18 q\x01\xaeן\xa1\xa1\x9fד\xf7\x92\x1f>@\x1c\xf6\xa8\xaa\xed\xed\xaaYM\r$bK\xc0\xfe\xced\x01\x05 \x8d\xa8ү[E\"\xa0\xa2\x02\xd6\xe2;\xff\xfe\xb9Kx\u007f%\x13^\x91\x196;%T\x1a,\x1e\x10U:i\x94m=Mk\x00\x00\x00\x05\x00\x00\xff\x80\x06\x00\x05\x80\x00\x1a\x00)\x00.\x00D\x00T\x00\x00\x014'\x06\a\x16\x15\x14\x06\"&54632\x1767&#\"\x06\x10\x16 6\x03\x16\x15\x14\x0e\x03\a\x16;\x016\x114'.\x01'\x16\x054'\x06\a\x0e\x01\x15\x14\x17>\x017\x0e\x01\a\x1632676%\x11\x14\x06#!\"&5\x11463!2\x16\x04\x1a\x1c),\x16\x9a蛜s5-\x04\x17\x0254&#\"\x06#\"'654'.\x01#\"\a\x06\x15\x14\x17\x06#\"&#\"\x06\x15\x14\x1e\x02\x15\x14\a\x06\a\x06\x15\x14\x17\x1e\x0232632\x1e\x0232>\x0232\x1632>\x0176\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04\xff\x16Cf\x1d\a'/'%\x14\f(\v\x04\b\x05\x11$\x86U\xc7L\x11\x05\x04\n\f(\n\x15#'/'\a@\x86\x16\x89\x02\b\x0f\x10\f3\x0e#@,G)+H+@#\x0e3\r\x10\x0e\b\x02\x89\x01\x01\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01\x84\x16\x05\x0fX@\x13\x06\x0f\x16\f\x1d\x16\x13\x19\x10\x02_\x13O#NW\xa5#O\x13_\x02\x0f\x18\x14\x15\x1d\f\x16\x0f\x06\x13\x8a\x1d\x05\x16.\x16\x05*\x13\t\x1e#\x1e\x1e#\x1e\b\x14(\x05\x16\x01\xfb\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x01\x00\x0f\xff\x80\x06q\x05\x80\x00[\x00\x00\x016\x16\x17\x16\x15\x14\a\x1632632\x16\x15\x14\x0e\x02\x15\x14\x17\x1e\x01\x17\x16\x17\x16\x15\x14\a\x0e\x02#\"&#\"\a\x0e\x04#\".\x03'&#\"\x06#\".\x01'&54767>\x017654.\x0254632\x16327&547>\x01\x03P\x86\xd59\x1b\t\x0e\x0e\x12B\x12\x1d6?K?\f%\x83O\x1c4\x1c\xdb\a\b\x14\x17\x14T\x16%\x19 >6>Z64Y=6>\x1f\x1a%\x18S\x11\x19\x14\b\a\xdb\x1c4\x1cN\x85$\f?L?4\x1d\x0fB\x14\x12\x0e\t\x1b@\xd8\x05\x80\x01\x8b{:y/\x90\a\x1b$\x1c ,\x13'\x1c\x0f\x1cR\x88!\f\v\x06\x1dF!\v8%\r\x05\x05#)(\x1b\x1b()#\x05\x05\x0f%:\v!F\x1d\x06\v\f \x8aQ\x1c\x0f\x1c'\x14+\x1f\x1b%\x1a\a\x8e0z:\x89z\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00O\x00_\x00\x00\x014'.\x01'&54>\x0254&#\"\x06#\"'654'.\x01#\"\a\x06\x15\x14\x17\x06#\"&#\"\x06\x15\x14\x1e\x02\x15\x14\a\x06\a\x06\x15\x14\x17\x1e\x0232632\x1e\x0232>\x0232\x1632>\x0176\x01\x11\x14\x06#!\"&5\x11463!2\x16\x05\x00\x16Cf\x1d\a'.'%\x14\v(\f\x04\b\x05\x11$\x85V\xc6M\x12\x06\n\x05\v)\n\x14#'.'\a@\x86\x16\x8a\x02\b\x0e\x10\r3\r#A,G)+H+A#\r4\r\x0f\x0f\b\x01\x8a\x01\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x01\x84\x16\x05\x0eXA\x0e\v\x0f\x16\f\x1d\x16\x13\x19\x10\x02?4N$NW\xa5&M&L\x02\x10\x19\x14\x15\x1d\f\x16\x0f\v\x0e\x8a\x1d\x05\x16/\x16\x05*\x13\n\x1e#\x1e\x1e#\x1e\t\x13+\x03\x16\x03\v\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x00\x01\x00\x00\xff\x80\t\x00\x06\x00\x00O\x00\x00\x01\x0e\x05\a\x0e\x01\a\x0e\x03\a\x06\a$\x05\x06\a>\x01?\x01>\x0376\x052\x17\x1e\x01\a\x03\x06'&#\"\x04\a\x06.\x02/\x01454327\x12\x0032\x1e\x05\x177>\x047>\x03\t\x00EpB5\x16\x16\x03\n3\x17\x0fFAP\b/h\xfe\xab\xfe\xdf\\\xd3/N\x10\x0fG\xb8S\x85L\xba\x01\x17\x01\t\v\x06\x06\xc2\x0f \x80\xe2\x92\xfe\x00\x88R\x86P*\f\x01\x06\x8a\xe9\xc0\x01m\xc9\x05\x1395F84\x0ef\x02&3Ga4B|wB\x06\x00.\\FI*/\x06\x12\xed.\x1d?&,\x06\x1f\xc8\x0e\xac5~\x10\x1e\a\a\x1bK %\r\x1f&\x03\x06\x16\v\xfe\xa7\x1d\a\x18Y\x02\x01\x1c.\"\x11\x01\x01\x01\x067\x01n\x01<\x01\t\x0f\"-I.\xb1\x04M`{\x90ARwJ!\x00\x05\x00\x00\xff\x00\x06\x00\x06\x00\x00F\x00X\x00^\x00d\x00j\x00\x00\x01\x14\a'\x17\x06\a'\x17\x06\a'\x17\x06\a'\x17\x06\"'7\a&'7\a&'7\a&'7\a&547\x17'67\x17'67\x17'67\x17'632\x17\a7\x16\x17\a7\x16\x17\a7\x16\x17\a7\x16\x174\x02$#\"\x0e\x02\x15\x14\x1e\x0232$\x12\x13\x11\t\x01\x11\x01\x11\x01\x11\t\x01\x11\x01\x11\t\x01\x11\x01\x05*\x05\xec\xe0\x13'ֱ,?\x9dg=OO\x0e&L&\x0eNJBg\x9d;1\xb2\xd6'\x13\xe0\xed\x05\x05\xee\xe1\x13'ֱ.=\x9egCIM\r$'&&\x0eNJBg\x9e=.\xb1\xd5%\x15\xe0\xed\x05\x1e\x9d\xfe\xf3\x9ew\u061d\\\\\x9d\xd8w\x9e\x01\r\x9dI\xfdo\xfdo\x02\x91\x02\xc4\xfd<\xfd<\x05\xc4\xfd\x00\xfd\x00\x03\x00\x02\x80-\x1f\x0eNIDg\x9e=/\xb2\xd7%\x16\xe4\xf0\x06\x06\xee\xe2\x13(ײ+A\x9ehEHO\x0e*\"#*\x0eOICh\x9f=/\xb2\xd7'\x13\xe0\xec\x06\x06\xed\xe1\x13(ֲ/=\x9fh>ON\x0e\x1f.\xa0\x01\x0f\x9d]\x9d\xdaxwڝ]\x9d\x01\x0f\x02\x1e\xfd\x02\xfe\x81\x01\u007f\x02\xfe\x01\u007f\xf9\xcb\x01\x9c\x037\x01\x9b\xfee\xfc\xc9\x03[\xfc\x80\xfe@\x01\xc0\x03\x80\x01\xc0\x00\x00\x03\x00\x00\xff\x00\x06\x80\x06\x00\x00\x14\x00)\x006\x00\x00\x01!\a!\"\x06\x15\x11\x14\x16\x17\x163\x15#\"&5\x1146%3\x01\x0e\x06\a567654'\x013\x13\x01\x11!67!\x114&'7\x1e\x01\x01S\x02\xb3\x1a\xfdgn\x9dy]\x17K-\x8c\xc7\xc7\x03\xdf\xf7\xfe\x1e\x17#75LSl>\xa39\x14\x14\xfe\xe3\xe4\xbb\x03V\xfc\xe5%\b\x02\xa6cP\x19e}\x05&H\x9en\xfc\xfd_\x95\x13\x05HȌ\x03\x03\x8c\xc8\xda\xfa\xf2=UoLQ1!\x02\xc3\x1a\x9c4564\x02\xdd\xfd\xb7\x01\xf2\xfb\xa97\x12\x04\x0eU\x8c\x1dC\"\xb3\x00\x00\x00\x00\n\x00\x00\xff\x00\a\x00\x06\x00\x00\a\x00\x14\x00!\x00-\x009\x00[\x00n\x00x\x00\x90\x00\xe7\x00\x00\x00\x14\x06\"&462\x0354&\"\x06\x1d\x01\x14\x16326754&\"\x06\x1d\x01\x14\x16326754&\"\x06\x1d\x01\x14\x1626754&\"\x06\x1d\x01\x14\x1626\x01\x06\x04#\".\x02547\x06\x15\x14\x12\x17632\x17632\x1762\x17632\x16\x176\x12'4#\"\a\x06#\"547\x06\x15\x14\x163276\x014&\"\x06\x15\x14\x1626\x014.\x01#\"\x06\a\x06\x15\x14\x16327632\x16\x15\x14\a>\x01\x05\x14\x02\a\x06\x04\x0f\x01\x15\x14\x06#\"'\x06\"'\x06#\"'\x06#\"&5\x06#\"'67&'\x16327&'&54>\x0332\x1767>\x017>\x027>\x0132\x17632\x17\x16\x15\x14\x0e\x02\a\x1e\x01\x15\x14\a\x16\x17632\x17\x16\x03T\"8\"\"8\x82)<()\x1d\x1e)\xac(<))\x1e\x1d)\xae)<))<)\xae)<))<)\x01\fT\xfeد{ՐR\x15h\x82x\x1e=8\x1e 78\x1e n \x1e8\x1c1\rp\x82\x8eH\x11\x1e_6\xe2\x1eS\xb2\x92oc\r\xfeF@b@?d?\x02uK\x97bM\x9070[f5Y$\x1135\x04KU\x01\x17C<:\xfe\xee[\x04;+8\x1e n \x1e87 \x1e8/8Zlv]64qE 'YK\xc00\x18\x12-AlB;\x16\x13\x17\x02\x14\x03\n\x1a\x18\x10W\xf9\x88#\x1b;WS9\x05\f\r\x13\x01\x11&\x10\x9d(\x19#-7Z\x04\xe8://:/\xfaTr\x1e++\x1er\x1e,,\x1er\x1e++\x1er\x1e,,\x1er\x1e++\x1er\x1e,,\x1er\x1e++\x1er\x1e,,\x02ʠ\xc7g\xab\xe0xXV\xafע\xfe\xd4e9222222\x1f\x19^\x01\x13\xb3K\x06\x13\xf3Vv\u007f\x94\x96\xddF0\x02\xb22OO23OO\xfe\xe0`\xa6lF;\x9fmhj\x13\x0684\x1a\x14D\xc3ro\xfe\xebB@\x9d\x1a\x01r+@222222C0DP\x01\x13\x1f`\a.\xc0r8h9\x89\x9c~T4\x1d\x19\x03\x14\x06\x0f.&\x14o\x84\x04@9\x05\a\x05\x11\x0f\x13\x01\x06\x18\f\x06\x13\x8a\xf0\x1e1P\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x19\x00%\x001\x00\x00\x014'!\x153\x0e\x01#\"&4632\x177&#\"\x06\x10\x16326%35#5#\x15#\x153\x153\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x03\x95\x06\xfe\x96\xd9\f}Pc\x8c\x8cc]\x0132\x16\x06\x001\xae\xa4I\xfe\xe3U\xa4Π?L\x80\xb6\x80L?\xbe\x99cc\x0e\xc34MX\v\x8a\x14\x1a&\x04\x00\xfc\xb90\x0e4;0\xfe\xae\x05X\x19pD[\x80\x80[Dp\x19D,\x0f\x02)\x12\x02&&\x00\x00\x05\x00\x00\xffQ\t\x00\x05\x00\x00\x05\x009\x00V\x00\\\x00\x94\x00\x00\x1226&\"\x06\x05.\x05'\a\x06&'&6?\x01.\x02\x06#\"\x0f\x01#\x1126\x1e\x03\x17\x01\x16327\x1667\x167>\x01'\x1632>\x01&\x173\x11#'&+\x01\"\x0f\x01\x06\x14\x17\x1e\x01?\x016\x1e\x01\a\x1e\x01\x17\x1e\x01\x17\x16\x0426&\"\x06\x01\x11\x14\x06#!\x0e\x01\a\x0e\x01\a\x0e\x01'\x0e\x01.\x01'\x01!\"&5\x11463!>\x06;\x012\x176;\x012\x1e\x06\x17!2\x16\x98P P \x06\t\n9\x1a2#.\x16}S\xfbP9\x01:\xb1\x16:%L\v\\B\x9e\x9b\x05 \f\x1b\x0e\x15\b\x01)spN/9o\x11J5\x14 \x02\n!+D\x1f\a\x84`]\x9dBg\xa7Y9\xd1\x1c\x1b+\x86,\xc1\x199%\n\x10P\x14\x1dk\v4\x01\x00P P \x01\b&\x1a\xfeN\x1bnF!_7*}B<\x84{o0\xfe\xe1\xfe\x9a\x1a&&\x1a\x01\xa5\x0eB\x1d;*<@$ucRRc\xa7#@16#3\x1b7\x0e\x01c\x1a&\x01\x80@@@\x06\rJ\"@*4\x17\x8c^\x04`E\xb2D\xce\v\v\x01\x02B\x9e\xfd\xe0\x01\x01\x03\x06\v\b\xfe\xdco/\x1489\x062\x127\x17\n*@O\x18\x02\x00\xb4LC\xf3!T!3\x022\xda\x17\x033\x1f\x13X\x18$\x8b\x0fBJ@@@\x02\x00\xfd\x80\x1a&AS\n0C\f59\x04\"\v'D/\x01\x1a&\x1a\x02\xa0\x1a&\x0eD\x1c4\x17\x1c\v88\f\x11$\x1a5\x1fA\x10&\x00\x00\x00\x02\x00\x00\xff\x00\a\x00\x06\x00\x00%\x00O\x00\x00\x01\x11\x14\x06#!\"&5\x1147>\x067>\x032\x1e\x02\x17\x1e\x06\x17\x16\x01$7>\x01/\x01.\x01\a\x06\a\x0e\x03\".\x02'&'&\x06\x0f\x01\x06\x16\x17\x16\x05\x1e\x042>\x03\a\x00^B\xfa@B^\v\b>\x15FFz\xa5n\x05_0P:P2\\\x06n\xa5zFF\x15>\b\v\xfd\xcc\x01\aR\v\x03\b&\b\x1a\v\xe7p\x05^1P:P1^\x05\xba\x9d\v\x1a\b&\b\x03\vR\x01\a\nP2NMJMQ0R\x03r\xfc.B^^B\x03\xd2\x0f\t\a7\x11:5]yP\x04H!%%\"F\x05Py]5:\x117\a\t\xfd\xa8\xbf=\b\x19\v4\v\x03\b\xa9Q\x03H!%%!H\x03\x86t\b\x03\v4\v\x19\b=\xbf\b<\"-\x16\x16/ ?\x00\x00\x00\x00\x03\x00\x00\xff\x00\a\x00\x06\x00\x001\x00P\x00p\x00\x00\x01\x17\x16\x06\a\x0e\x02\a\x0e\x03+\x02\".\x02'.\x02'.\x01?\x01>\x01\x17\x16\x17\x1e\x03;\x022>\x027$76\x16\x13\x11&'&%.\x03+\x02\"\x0e\x02\a\x0e\x02\a\x06\a\x11\x14\x163!26\x13\x11\x14\x06#!\"&5\x11476\x007>\x03;\x022\x1e\x02\x17\x1e\x02\x17\x16\x05\xc2'\b\x03\n+\xa7~\x04'*OJ%\x01\x01%JN,&\x05x\xa7'\v\x03\b%\b\x1b\v^\xd4\x05M,E\x18\x01\x01\x18E,M\x05\x01\x027\v\x1a\xc6ZE[\xfe\xd6\x03P*F\x18\x01\x01\x18F*P\x03\xd7\xc9:5\x0e\a\x13\r\x05\xc0\r\x13\x80^B\xfa@B^){\x01\xc6\x06$.MK%\x01\x01%KM.$+\xe2\xe2X)\x02o3\v\x19\b\"\x81a\x03 2\x17\x172!\x1f\x04]\x81\x1e\b\x19\v4\v\x04\tI\xa3\x04>\x1f\"\"\x1f>\x04\xc6,\b\x03\xfd&\x03\xa0S8J\xe6\x02B\x1e##\x1eB\x02\xa6\x9f12\f\a\xfc`\r\x13\x13\x03\xad\xfc`B^^B\x03\xa08&r\x01a\x05\x1e#1\x18\x181#\x1e$\xac\xb6R&\x00\x00\x00\x00\v\x00\x15\xff\x00\x05\xeb\x06\x00\x00\x03\x00\a\x00\v\x00\x0f\x00\x1a\x00\x1e\x00\"\x00&\x00.\x002\x00v\x00\x00%\x17/\x01\x01%'\x05\x01\x17\x03'\x01%\x03\x05\x01\x17/\x01\x14\x16\x06\x0f\x01\x17\x16\x01\x05\x03%\x017\a\x17\x01%\x03\x05\x017'\a\x17\x16\x0f\x01%7\x0f\x02'\a\x14\x0f\x01\x06/\x01\x17\x14\a\x05\x06#&5'&\x03&?\x01&'\x03&?\x01&'\x03&7%2\x17\x05\x16\x15\x13\x14\x0f\x01\x17\x16\x15\x1776\x1f\x0174?\x016\x1f\x01\x1e\x01\x0e\x01\x15\x14\x0f\x01\x06\x01J\xca\"\xd8\x01\x12\x01\x12\v\xfe\xd4\xfe\xee\xe30\xf5\x01<\x01=\x0e\xfe\xa0\x01\x8d_\x02g\x02\x02\x04NU\a\xfd?\x01\x00D\xfe\xe9\x04f\x0f\xe6\x02\xfd\xe1\x01u\x13\xfeY\x03\x9a\x14\xe2\x02\x90\x06\x02\a\x01\x02\x1e\xb3\x14\x13G\b\x04\xea\a\ab\a\x04\xfe\xdb\x04\x02\b\xe4\x047\x02\a=^\x01H\x02\b^\x85\x02`\x02\t\x01\xb1\x05\x03\x01=\x06\x14\x06v~\x05\x05y\x05\x06T\x03\x05\xce\x06\x05\xf5\x04\x02\x0f\x14\x04\xbf\x06\x01\xd6\xec\xd5\xfe3\xda\xf5\xd7\x01\x86\xd5\x01G\xcc\xfd\xe2\xd6\x01D\xc8\xfe\xa3P\xefO\x01\x0f\t\x034F\x06\x02\x9e\xc8\x01ѭ\xfb\xb3\xea\xa4\xf0\x02q\xc2\x01\xb9\xa3\xfc\xbb\xe9\x8ei_\x04\x05w\\ހ\xe4!1u\x05\x03\xbb\x05\x05S\xa1\x05\x03\xea\x02\x02\x01\xf2\x04\x01\x11\a\x04%V\x06\x01_\a\x05-d\b\x01\xd2\n\x03\x87\x01\x99\x04\x05\xfe1\a\x03=U\x02\x06{J\x04\x048n\x06\x03~\x03\x03\x87\x04\x06r\x87\x03\x05\x02\x99\x05\x00\x00\x03\x00\x00\xff\x00\x06\x80\x06\x00\x00\x1d\x00'\x00U\x00\x00\x014.\x03#\x0e\x04\".\x03'\"\x0e\x03\x15\x14\x163!26\x034&\"\x06\x15\x14\x1626\x01\x15\x14\x06+\x01\x15\x14\x06#!\"&5\x11463!2\x16\x1d\x0132\x16\x1d\x01\x14\x06+\x01\x1532\x16\x1d\x01\x14\x06+\x01\x1532\x16\x04\xb1\v\x1f0P3\x067\x1e3/./3\x1e7\x063P0\x1f\vT=\x02@=T\xad\x99֙\x99֙\x02|\x12\x0e`^B\xfb@B^^B\x04\xc0B^`\x0e\x12\x12\x0e``\x0e\x12\x12\x0e``\x0e\x12\x01*9deG-\x04!\x10\x18\n\n\x18\x10!\x04-Ged9Iaa\x02\x9bl\x98\x98lk\x98\x98\xfeO\xc0\x0e\x12\xe0B^^B\x05\xc0B^^B\xe0\x12\x0e\xc0\x0e\x12\x80\x12\x0e\xc0\x0e\x12\x80\x12\x00\x00\x04\x00\x00\xff\x00\x06\x80\x06\x00\x00\t\x00+\x00Y\x00i\x00\x00\x01\x14\x06\"&5462\x16\x032\x1e\x04\x15\x14\x06#!\"&54>\x03;\x01\x1e\x052>\x04\x01\x14\x06+\x01\x1532\x16\x1d\x01\x14\x06+\x01\x1532\x16\x1d\x01\x14\x06+\x01\x15\x14\x06#!\"&5\x11463!2\x16\x1d\x0132\x16\x15\x01\x114&#!\"\x06\x15\x11\x14\x163!26\x04\x04\x99֙\x99֙0.I/ \x10\aOB\xfd\xc0BO\t\x1c-Q5\x05\a2\x15-\x1d)&)\x1d-\x152\x02\xb3\x13\r``\r\x13\x13\r``\r\x13\x13\r`^B\xfb@B^^B\x04\xc0B^`\r\x13\xff\x00\x13\r\xfb@\r\x13\x13\r\x04\xc0\r\x13\x03|k\x98\x98kl\x98\x98\xfe\xb8\"=IYL)CggC0[jM4\x04\x1f\v\x17\t\t\t\t\x17\v\x1f\x01\x04\r\x13\x80\x13\r\xc0\r\x13\x80\x13\r\xc0\r\x13\xe0B^^B\x05\xc0B^^B\xe0\x13\r\xfb@\x05\xc0\r\x13\x13\r\xfa@\r\x13\x13\x00\x00\x06\x00\x00\xff\x80\b\x00\x05\x80\x00\x19\x00!\x001\x00A\x00Q\x00u\x00\x00\x004.\x02#\x0e\x04\".\x03'\"\x0e\x02\x14\x163!2\x024&\"\x06\x14\x162\x0154&#!\"\x06\x1d\x01\x14\x163!26\x1154&#!\"\x06\x1d\x01\x14\x163!26\x1154&#!\"\x06\x1d\x01\x14\x163!26\x01\x11\x14\x06#!54&+\x01\"\x06\x1d\x01!54&+\x01\"\x06\x1d\x01!\"&5\x11463!2\x16\x04\x00\x12)P9\x060\x1b,***,\x1b0\x069P)\x12J6\x02\x006S\x85\xbc\x85\x85\xbc\x04\"\x12\x0e\xfd\xc0\x0e\x12\x12\x0e\x02@\x0e\x12\x15\x0f\xfd\xc8\x0f\x15\x15\x0f\x028\x0f\x15\x12\x0e\xfd\xc0\x0e\x12\x12\x0e\x02@\x0e\x12\x01\x00^B\xfe\xa0\x12\x0e@\x0e\x12\xfd\x00\x12\x0e@\x0e\x12\xfe\xa0B^^B\x06\xc0B^\x01U\x80kc9\x04\x1c\x0f\x14\t\t\x14\x0f\x1c\x049ck\x80U\x02?\xbc\x85\x85\xbc\x85\xfe\xe6@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x128\x0f\x15\x15\x0f8\x0f\x15\x15\x01\v@\x0e\x12\x12\x0e@\x0e\x12\x12\x01N\xfb@B^`\x0e\x12\x12\x0e``\x0e\x12\x12\x0e`^B\x04\xc0B^^\x00\x00\a\x00\x00\xff\x80\b\x00\x05\x80\x00\x19\x00!\x001\x00A\x00Q\x00u\x00\x85\x00\x00\x00\x14\x06#!\"&4>\x023\x1e\x042>\x0372\x1e\x01\x02\x14\x06\"&462\x01\x15\x14\x06#!\"&=\x01463!2\x165\x15\x14\x06#!\"&=\x01463!2\x165\x15\x14\x06#!\"&=\x01463!2\x16\x13\x114&#!\"\x06\x15\x11\x14\x163!546;\x012\x16\x1d\x01!546;\x012\x16\x1d\x01!26\x13\x11\x14\x06#!\"&5\x11463!2\x16\x04\x00J6\xfe\x006J\x12)P9\x060\x1b,***,\x1b0\x069P)\x8b\x85\xbc\x85\x85\xbc\x04\"\x12\x0e\xfd\xc0\x0e\x12\x12\x0e\x02@\x0e\x12\x15\x0f\xfd\xc8\x0f\x15\x15\x0f\x028\x0f\x15\x12\x0e\xfd\xc0\x0e\x12\x12\x0e\x02@\x0e\x12\x80\x13\r\xf9@\r\x13\x13\r\x01`\x12\x0e@\x0e\x12\x03\x00\x12\x0e@\x0e\x12\x01`\r\x13\x80^B\xf9@B^^B\x06\xc0B^\x01ՀUU\x80kc9\x04\x1c\x0f\x14\t\t\x14\x0f\x1c\x049c\x01\xbb\xbc\x85\x85\xbc\x85\xfd`@\x0e\x12\x12\x0e@\x0e\x12\x12\xee8\x0f\x15\x15\x0f8\x0f\x15\x15\xf5@\x0e\x12\x12\x0e@\x0e\x12\x12\xfc2\x04\xc0\r\x13\x13\r\xfb@\r\x13`\x0e\x12\x12\x0e``\x0e\x12\x12\x0e`\x13\x04\xcd\xfb@B^^B\x04\xc0B^^\x00\x00\x00\x00\x03\x00\x00\xff\x00\a\x00\x06\x00\x00\x0f\x00\x17\x00(\x00\x00%.\x01'\x0e\x01\"&'\x0e\x01\a\x16\x04 $\x02\x10& \x06\x10\x16 \x00\x10\x02\x06\x04#\"$&\x02\x10\x126$ \x04\x16\x05\xf3\x16\x83wC\xb9ιCw\x83\x16j\x01J\x01~\x01J\x89\xe1\xfe\xc2\xe1\xe1\x01>\x02\xe1\x8e\xef\xfe\xb4\xb7\xb6\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0ś\xcd\x10JSSJ\x10͛\x96\xaf\xaf\x02\xb2\x01>\xe1\xe1\xfe\xc2\xe1\x016\xfe\x94\xfe\xb5\xf1\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x8e\xf0\x00\x00\x03\x00\x00\xff\x00\a\x00\x06\x00\x00\x10\x00$\x00,\x00\x00\x00 \x04\x16\x12\x15\x14\x02\x06\x04 $&\x02\x10\x126\x01654\x02&$ \x04\x06\x02\x15\x14\x17\x123\x16 72&\x10& \x06\x10\x16 \x02\xca\x01l\x01L\xf0\x8e\x8d\xf0\xfe\xb4\xfe\x92\xfe\xb4\uf38e\xf0\x04m\x95z\xce\xfe\xe4\xfe\xc8\xfe\xe4\xcez\x95B\xf0\x83\x01l\x83\xf0\xa9\xe1\xfe\xc2\xe1\xe1\x01>\x06\x00\x8e\xf0\xfe\xb4\xb6\xb5\xfe\xb4\xf0\x8f\x8e\xf1\x01K\x01l\x01L\xf0\xfbG\xcd\xfa\x9c\x01\x1c\xcezz\xce\xfe\xe4\x9c\xfa\xcd\x01G\x80\x80\xa1\x01>\xe1\xe1\xfe\xc2\xe1\x00\x00\x00\x00\x03\x00\x00\xff\x00\x06\x00\x06\x00\x00\x1f\x00'\x007\x00\x00\x01\x1e\x04\x15\x14\x06#!\"&54>\x037&54>\x022\x1e\x02\x15\x14\x00 \x06\x10\x16 6\x10\x132654\x02'\x06 '\x06\x02\x15\x14\x163\x04\xb1/U]B,ȍ\xfc\xaa\x8d\xc8,B]U/OQ\x8a\xbdн\x8aQ\xfe\x9f\xfe\xc2\xe1\xe1\x01>\xe1+X}\x9d\x93\x91\xfe\x82\x91\x93\x9d}X\x02\xf0\x0e0b\x85Ӄ\x9a\xdbۚ\x83Ӆb0\x0e}\x93h\xbd\x8aQQ\x8a\xbdh\x93\x02\x13\xe1\xfe\xc2\xe1\xe1\x01>\xfa\xe1\x8ff\xef\x01\x14\a\u007f\u007f\a\xfe\xec\xeff\x8f\x00\x00\x00\x00\x04\x00\x00\xff\x00\x05\x00\x06\x00\x00\x11\x00\x19\x00#\x00=\x00\x00\x00\x14\x06#!\"&4>\x023\x16272\x1e\x01\x02\x14\x06\"&462\x01\x11!\x11\x14\x163!26\x13\x11\x14\x06#!\"&5\x11463!\x15\x14\x16;\x0126=\x01!2\x16\x04\x00J6\xfe\x006J\x12)Q8P\xd8P8Q)\x88\x87\xbe\x87\x87\xbe\x01\xa1\xfc\x00\x13\r\x03\xc0\r\x13\x80^B\xfc@B^^B\x01`\x12\x0e\xc0\x0e\x12\x01`B^\x01V\x80VV\x80ld9KK9d\x01\xb9\xbc\x85\x85\xbc\x85\xfb\xa0\x05`\xfa\xa0\r\x13\x13\x05\xcd\xfa@B^^B\x05\xc0B^`\x0e\x12\x12\x0e`^\x00\x00\b\x00\x00\xff\x80\b\x00\x05\x80\x00\x13\x00\x1b\x00+\x00;\x00K\x00[\x00e\x00u\x00\x00\x014.\x02#\x06\"'\"\x0e\x02\x15\x14\x163!26\x024&\"\x06\x14\x162\x0154&#!\"\x06\x1d\x01\x14\x163!26\x0154&#!\"\x06\x1d\x01\x14\x163!26%54&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&#!\"\x06\x1d\x01\x14\x163!26\x01!54&#!\"\x06\x15!\x11\x14\x06#!\"&5\x11463!2\x16\x03\x80\x0f\"D/@\xb8@/D\"\x0f?,\x01\xaa,?\x80p\xa0pp\xa0\x04p\x12\x0e\xfd@\x0e\x12\x12\x0e\x02\xc0\x0e\x12\xfe\x80\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\x01\x80\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x0e\xfd@\x0e\x12\x12\x0e\x02\xc0\x0e\x12\xf9\x80\a\x00\x12\x0e\xf9@\x0e\x12\a\x80^B\xf9@B^^B\x06\xc0B^\x01D6]W2@@2W]67MM\x01\xa3\xa0pp\xa0p\xfe\xe0@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01n`\x0e\x12\x12\x0e\xfb@B^^B\x04\xc0B^^\x00\b\x00\x00\xff\x80\b\x00\x05\x80\x00\x13\x00\x1b\x00+\x00;\x00K\x00[\x00e\x00u\x00\x00\x01\x14\x06#!\"&54>\x023\x16272\x1e\x02\x02\x14\x06\"&462\x01\x15\x14\x06#!\"&=\x01463!2\x16%\x15\x14\x06#!\"&=\x01463!2\x16\x05\x15\x14\x06+\x01\"&=\x0146;\x012\x165\x15\x14\x06#!\"&=\x01463!2\x16\x13\x11!\x11\x14\x163!26\x13\x11\x14\x06#!\"&5\x11463!2\x16\x03\x80?,\xfeV,?\x0f\"D/@\xb8@/D\"\x0f\x80p\xa0pp\xa0\x04p\x12\x0e\xfd@\x0e\x12\x12\x0e\x02\xc0\x0e\x12\xfe\x80\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\x01\x80\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x0e\xfd@\x0e\x12\x12\x0e\x02\xc0\x0e\x12\x80\xf9\x00\x13\r\x06\xc0\r\x13\x80^B\xf9@B^^B\x06\xc0B^\x01D7MM76]W2@@2W]\x01֠pp\xa0p\xfd\xa0@\x0e\x12\x12\x0e@\x0e\x12\x12\xf2@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\xf2@\x0e\x12\x12\x0e@\x0e\x12\x12\xfc\xb2\x04`\xfb\xa0\r\x13\x13\x04\xcd\xfb@B^^B\x04\xc0B^^\x00\x02\x00\x1d\xff\x00\x06\xe2\x06\x00\x00\x1a\x00A\x00\x00\x01\x10\x02#\"\x02\x11\x10\x12327.\x04#\"\a'632\x16\x176\x013\x16\x0e\x03#\".\x02'\x06#\"$&\x0254\x126$32\x1e\x03\x15\x14\x02\a\x1e\x01326\x04\xe7\xd2\xe1\xde\xd0\xd0\xdeJ9\x16\"65I).!1i\xab\x84\xa7CC\x01\x86u\x03\n+I\x8d\\Gw\\B!al\x96\xfe\xe3݇\x87\xde\x01\x1d\x95y\xebǙV\xa1\x8a/]:=B\x02\xed\x01>\x019\xfe\xc6\xfe\xc3\xfe\xc4\xfe\xc9\x11+\x0132\x16\x15\x14\a\x06\a\x06\x15\x10\x17\x16\x17\x1e\x04%\x14\x06#!\"&5463!2\x16\x03\x14\a\x0e\x01\a\x06#\"&54>\x0254'&#\"\x15\x14\x16\x15\x14\x06#\"54654'.\x01#\"\x0e\x01\x15\x14\x16\x15\x14\x0e\x03\x15\x14\x17\x16\x17\x16\x17\x16\x15\x14#\"'.\x0154>\x0354'&'&5432\x17\x1e\x04\x17\x14\x1e\x0532654&432\x17\x1e\x01\x05\x10\a\x0e\x03#\"&54>\x0176\x114&'&'.\x0554632\x17\x16\x12\x17\x16\x01\xc5 \x15\x01\f?c\xe1\xd5'p&\x13 ?b1w{2V\x02\x19\x0e\x14\t\x05?#\x1d\xfb\xc7\x1a&#\x1d\x049\x1a&\xd7C\x19Y'\x10\v\a\x10&.&#\x1d\x11\x03\x0f+\x17B\x03\n\r:\x16\x05\x04\x03 &65&*\x1d2\x10\x01\x01\x12\x06\x1bw\x981GF1\x19\x1d\x1b\x13)2<)<'\x1c\x10\b\x06\x03\b\n\f\x11\n\x17\x1c(\n\x1bBH=\x02ӊ\x13:NT \x10\x1e:O\t\xb7)4:i\x02\x16\v\x13\v\b \x13F~b`\f\x02e\x15!\x03\x0f}\x01\x1c\x01\x88\x01U\x01\x113i\x1b\x13\x1b?fR\xc7\xfa\xfe\xe7\xd2UX\x03\x1a\x10\x19\x16|\x1d'&\x1a\x1d'&\x02I\x86c&Q\x14\n\f\x06\t*2U.L6*\x05\f/\r\x16\x1aL\x0f:\x0f\x19\x15\x199\x01\x04\x04\x020\x1e%>..>%b>+\x14\x05\x05\x02\x03\x10\v+\xc1z7ymlw45)0\x10\t\f\x14\x1d\x1333J@0\x01!\x11!\x15\x16\v\x1c\x17\x19T\x14FL\xa0\x87\xfe\xee\xe5 P]=\x1f\x10\x0fGS\v\xe6\x01-\x83\xd0kwm\x03\x15\f\x17\x11\x14\t\x13!\xa9\x83\xfe\xe4\xac*\x00\x00\x02\x00\x00\xff\x00\a\x00\x06\x00\x00\x18\x00(\x00\x00%\x136&\a\x01\x0e\x01\x16\x1f\x01\x016\x17\x16\a\x019\x01\a2?\x01\x17\x16\x00\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x04\xa5\x93\t' \xfc\xa0\x1d\x15\x10\x18\xdd\x02\x01\x15\v\a\v\xfea\x10\x17\x16l\xe0@\x02l\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\xe5\x02\xb5,&\f\xfe\xb3\v\x1c\x19\aE\x01C\x0e\b\x05\n\xfe\x89\xe4\x16h\xa5$\x02\x9b\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x8e\xf0\x00\x00\x06\x00\x00\xff\x00\x04\x00\x06\x00\x00\r\x00\x1f\x00/\x003\x007\x00;\x00\x00%\x14\x06\"&5467\x113\x11\x1e\x01\x174&'\x114&\"\x06\x15\x11\x0e\x01\x15\x14\x16 67\x14\x00 \x00547\x1146 \x16\x15\x11\x16\x13\x15#5\x13\x15#5\x13\x15#5\x02\x80p\xa0pF:\x80:F\x80D\x00F\x00N\x00V\x00^\x00f\x00n\x00v\x00~\x00\x86\x00\x8e\x00\x96\x00\x9e\x00\x00\x01\x16\x14\a\x01\x06\"/\x01&4?\x01.\x017&#\"\x06\x15\x11!\x114>\x0232\x16\x176\x16\x17762\x17\x022\x16\x14\x06\"&4\x04\"&462\x16\x1462\x16\x14\x06\"&4\x042\x16\x14\x06\"&4\x04462\x16\x14\x06\"$2\x16\x14\x06\"&4\x042\x16\x14\x06\"&4\x04\"&462\x16\x1462\x16\x14\x06\"&4\x04\"&462\x16\x1462\x16\x14\x06\"&4\x042\x16\x14\x06\"&4$2\x16\x14\x06\"&4\x062\x16\x14\x06\"&4\x062\x16\x14\x06\"&4\x05\x99\n\n\xfd\x8e\n\x1a\nR\n\n,H\x138Jfj\x96\xff\x00Q\x8a\xbdhj\xbeG^\xceR,\n\x1a\n!4&&4&\x01Z4&&4&\xa64&&4&\xfd\xa64&&4&\x01\x00&4&&4\x01\x004&&4&\xfd\xa64&&4&\x01Z4&&4&\xa64&&4&\xfe\xda4&&4&\xa64&&4&\xfe\xa64&&4&\x01&4&&4&Z4&&4&Z4&&4&\x05\a\n\x1a\n\xfd\x8e\n\nR\n\x1a\n,[\xe8cG\x96j\xfb\x00\x05\x00h\xbd\x8aQRJ'\x1dA,\n\n\xfe\xa7&4&&4Z&4&&4Z&4&&4Z&4&&444&&4&\x80&4&&4Z&4&&4Z&4&&4Z&4&&4\xda&4&&4Z&4&&4Z&4&&4&&4&&4Z&4&&4Z&4&&4\x00\x11\x00\x00\xff\x00\a\x00\x06\x00\x00\x1d\x00%\x00-\x005\x00=\x00E\x00M\x00}\x00\x85\x00\x8d\x00\x95\x00\x9d\x00\xa5\x00\xad\x00\xb5\x00\xbd\x00\xc5\x00\x00\x01\x15\x14\a\x15\x14\x06+\x01\"&=\x01\x06#!\"'\x15\x14\x06+\x01\"&=\x01&=\x01\x00\x14\x06\"&4626\x14\x06\"&462&\x14\x06\"&462\x16\x14\x06\"&462&\x14\x06\"&462&\x14\x06\"&462\x01\x15\x14\x06#!\"&=\x0146;\x01\x114632\x176\x16\x1776\x1f\x01\x16\a\x01\x06/\x01&?\x01.\x017&#\"\x06\x15\x11!2\x16\x00\x14\x06\"&462&\x14\x06\"&462&\x14\x06\"&462\x16\x14\x06\"&462&\x14\x06\"&462&\x14\x06\"&462\x16\x14\x06\"&462&\x14\x06\"&462\x16\x14\x06\"&462\x06\x80\x80\x12\x0e@\x0e\x12?A\xfd\x00A?\x13\r@\r\x13\x80\x02@\x12\x1c\x12\x12\x1cR\x12\x1c\x12\x12\x1c.\x12\x1c\x12\x12\x1c\x92\x12\x1c\x12\x12\x1c.\x12\x1c\x12\x12\x1c.\x12\x1c\x12\x12\x1c\x04R\x12\x0e\xf9@\x0e\x12\x12\x0e`\x96jlL.h)\x16\v\v*\v\v\xfe\xc6\v\v*\v\v\x16$\t\x1c%35K\x05\xe0\x0e\x12\xfc\x80\x12\x1c\x12\x12\x1c.\x12\x1c\x12\x12\x1c.\x12\x1c\x12\x12\x1c\xd2\x12\x1c\x12\x12\x1c.\x12\x1c\x12\x12\x1c.\x12\x1c\x12\x12\x1c\xd2\x12\x1c\x12\x12\x1c.\x12\x1c\x12\x12\x1c\x92\x12\x1c\x12\x12\x1c\x01\xc0\xc0\xa9u\xc2\x0e\x12\x12\x0ev\x16\x16n\x11\x17\x17\x11\xbau\xa9\xc0\x01\xae\x1c\x12\x12\x1c\x12.\x1c\x12\x12\x1c\x12.\x1c\x12\x12\x1c\x12\x12\x1c\x12\x12\x1c\x12.\x1c\x12\x12\x1c\x12.\x1c\x12\x12\x1c\x12\xfd\xe0@\x0e\x12\x12\x0e@\x0e\x12\x02\x80j\x96N\x13\x0e \x16\v\v*\v\v\xfe\xc6\v\v*\v\v\x16.t2#K5\xfd\x80\x12\x01\xc0\x1c\x12\x12\x1c\x12.\x1c\x12\x12\x1c\x12.\x1c\x12\x12\x1c\x12R\x1c\x12\x12\x1c\x12.\x1c\x12\x12\x1c\x12.\x1c\x12\x12\x1c\x12R\x1c\x12\x12\x1c\x12.\x1c\x12\x12\x1c\x12\x12\x1c\x12\x12\x1c\x12\x00\x00\x00\x04\x00\x01\xff\x00\x06\x00\x05\xfe\x00\r\x00@\x00H\x00q\x00\x00\x01\x14\a\x06\a\x06 '&'&54 \x01\x14\x00\a\x06&76767676\x1254\x02$\a\x0e\x03\x17\x16\x12\x17\x16\x17\x16\x17\x1e\x01\x17\x16\x06'.\x01\x0276\x126$76\x04\x16\x12\x04\x14\x06\"&462\x01\x14\x06\a\x06&'&'&7>\x0154.\x01\a\x0e\x01\a\x06\x16\x17\x16\a\x06\a\x0e\x01'.\x017>\x0276\x1e\x01\x03\xe2\x11\x1f\x18\x16\xfe\xfc\x16\x18\x1f\x11\x01\xc0\x02\x1e\xfe\xf4\xd8\b\x0e\x01\a\x03\x04\x02\x01\b\x9f\xc1\xb6\xfeȵ|\xe2\xa1_\x01\x01ğ\a\x02\x03\x03\x01\b\x02\x01\x0f\b\x94\xe2y\b\av\xbf\x01\x03\x8f\xa4\x01/ۃ\xfd\u20fa\x83\x83\xba\x01\xa3k]\b\x10\x02\x06\x17\a\n:Bu\xc6q\x85\xc0\r\nCA\n\a\x18\x05\x02\x10\b_k\x02\x03\x84ނ\x90\xf8\x91\x01XVo\xd7bZZb\xd7nW\xa8\x01\x00\xf0\xfe|V\x03\f\t0\x12 \x0f\t\x03Q\x012\xb8\xb4\x01-\xa8\n\al\xad\xe7}\xb8\xfe\xcfO\x03\t\x15\x18\t/\f\t\f\x04:\xdf\x011\xa7\x8f\x01\x05\xc1z\t\nq\xd0\xfe\xdb%\xba\x83\x83\xba\x83\xff\x00z\xd5G\x06\b\n4(\n\n6\x92Ro\xbaa\f\x0fą\\\xa8<\n\n)4\t\b\x06J\xda}\x83\xe2\x89\x06\a\x86\xf1\x00\x02\x00\x00\xff\x80\a\x00\x05\x80\x00\x03\x00\x13\x00\x00%!\x11!\x01\x11\x14\x06#!\"&5\x11463!2\x16\x01\x00\x05\x00\xfb\x00\x06\x00^B\xfa@B^^B\x05\xc0B^\x80\x03\x00\x01`\xfb@B^^B\x04\xc0B^^\x00\x01\x00\x00\xff\x80\a\x00\x01\x80\x00\x0f\x00\x00%\x15\x14\x06#!\"&=\x01463!2\x16\a\x00^B\xfa@B^^B\x05\xc0B^\xe0\xc0B^^B\xc0B^^\x00\x00\x00\x03\x00\x00\xff\x00\b\x00\x06\x00\x00\x03\x00\f\x00&\x00\x00)\x01\x11)\x02\x11!\x1132\x16\x15\x01\x11\x14\x06#!\x11\x14\x06#!\"&5\x11463!\x11463!2\x16\x01\x00\x03\x00\xfd\x00\x04\x00\x02\x00\xfd\x00`B^\x03\x00^B\xfd\xa0^B\xfc@B^^B\x02`^B\x03\xc0B^\x02\x00\x03\x00\xff\x00^B\x02\x00\xfc@B^\xfe\xa0B^^B\x03\xc0B^\x01`B^^\x00\x00\x00\x02\x00\x00\xff\x80\a\x00\x05\x80\x00#\x003\x00\x00%764/\x01764/\x01&\"\x0f\x01'&\"\x0f\x01\x06\x14\x1f\x01\a\x06\x14\x1f\x01\x162?\x01\x17\x162\x01\x11\x14\x06#!\"&5\x11463!2\x16\x04\x97\x92\n\n\xe9\xe9\n\n\x92\n\x1a\n\xe9\xe9\n\x1a\n\x92\n\n\xe9\xe9\n\n\x92\n\x1a\n\xe9\xe9\n\x1a\x02s^B\xfa@B^^B\x05\xc0B^ג\n\x1a\n\xe9\xe9\n\x1a\n\x92\n\n\xe9\xe9\n\n\x92\n\x1a\n\xe9\xe9\n\x1a\n\x92\n\n\xe9\xe9\n\x04\x13\xfb@B^^B\x04\xc0B^^\x00\x03\x00\x00\xff\x80\a\x00\x05\x80\x00#\x00'\x007\x00\x00\x01\a\x06\"/\x01\a\x06\"/\x01&4?\x01'&4?\x0162\x1f\x01762\x1f\x01\x16\x14\x0f\x01\x17\x16\x14\x01!\x11!%\x11\x14\x06#!\"&5\x11463!2\x16\x04\xe9\x92\n\x1a\n\xa9\xa9\n\x1a\n\x92\n\n\xa9\xa9\n\n\x92\n\x1a\n\xa9\xa9\n\x1a\n\x92\n\n\xa9\xa9\n\xfc\r\x05\x00\xfb\x00\x06\x00^B\xfa@B^^B\x05\xc0B^\x01\xa9\x92\n\n\xa9\xa9\n\n\x92\n\x1a\n\xa9\xa9\n\x1a\n\x92\n\n\xa9\xa9\n\n\x92\n\x1a\n\xa9\xa9\n\x1a\xfe\xcd\x04\x00`\xfb@B^^B\x04\xc0B^^\x00\x02\x00\x00\xff\x00\a\x00\x06\x00\x00\x03\x00\x13\x00\x00\t\x01!\x01\x00\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x04.\x012\xfdr\xfe\xce\x05`\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x01f\x024\xfd\xcc\x01\xd0\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x8e\xf0\x00\x00\a\x00\x00\xff\x00\a\x02\x06\x00\x00\a\x00\x13\x00#\x00.\x00C\x00\xc4\x00\xd4\x00\x00\x01&\x0e\x01\x17\x16>\x01\x05\x06\"'&4762\x17\x16\x14\x17\a\x06\"/\x01&4?\x0162\x1f\x01\x16\x14'\x06\"'&4762\x16\x14%\x0e\x01'.\x01>\x02\x16\x17\x1e\a\x0e\x01\x136.\x02'.\x01\a>\x01\x1f\x016'>\x01/\x01>\x0176&'&\x06\a\x0e\x01\x1e\x01\x17.\x01'&7&'\"\a>\x01?\x014'.\x01\x06\a67\x06\x1e\x01\x17\x06\a\x0e\x01\x0f\x01\x0e\x01\x17\x16\x17\x06\a\x06\x14\x167>\x017.\x02\a>\x043\x167654'\x16\a\x0e\x01\x0f\x01\x0e\x05\x16\x17&'\x0e\x04\x16\x17\x166\x127>\x017\x16\x17\x1676\x12\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x05\v\x0f(\f\v\x0e4\x10\xfeZ\b\x17\a\b\b\a\x17\b\a\x9e#\f#\r&\f\f#\f#\r&\fy\a\x17\b\a\a\b\x16\x10\x01\x8b\"\x936&.\x04JM@&\x02\x16\a\x13\x06\x0e\x03\x05\x03\a\xc3\x03\x17 \"\x06(XE\x13*\f\f\x02$\x06\x01\x03\x03+8\x06\njT\x01?\x013\x03\x13#'.\x01'&!\x11\x14\x163!2>\x04?\x013\x06\x02\a.\x01'#!\x0557>\x017\x13\x12'.\x01/\x015\x05!27\x0e\x01\x0f\x01#'.\x01#!\"\x06\x02\x06g\xb1%%D-\x11!g\x0e\ag\x1d\x0f<6W\xfe\xf7WZ\x01e#1=/2*\x12]Y\x063\x05\x92\xeb-,\xfd\x8c\xfe\x88\u007fC1\x01\b\x03\v\x02/D\u007f\x01x\x02\xbe\x8b\xeb\x06\x10\x04\x05] \x1fVF\xfd\xdc\x1c\x0f\x05I\xfdq\x01\x05\x03\x03\x02-H\x8e\xfe\xbe\xfe\xc1\u007fD2\x01\b\xfd\xd4NK\x04\v\x19'>*\xd8%\xfeR=\x05\x06\x01\ff\x19\r07\x02\x83\x01\x92\xf3=.\r\x18f\f\x1bD\xfd]\\|yu\x11\x00\x00\a\x00\x00\xff\x80\x06\x00\x05\x80\x00\x11\x00,\x000\x00>\x00S\x00e\x00u\x00\x00\x01\x15\x14\x16\x0e\x04#\x112\x1e\x03\x1c\x01\x05\x15\x14\x16\x0e\x02#\"'&5<\x03>\x0232\x1e\x03\x1c\x01\x053\x11#\x013\x11#\a&'#\x113\x11\x133\x13\x054'.\x05\"#\"+\x01\x1123\x166'&\x0554.\x02#\"\a5#\x1137\x16326\x13\x11\x14\x06#!\"&5\x11463!2\x16\x03\x9a\x01\x01\x02\x05\b\x0e\t\t\x0e\b\x05\x02\x01<\x01\x01\x04\v\b\t\x05\x04\x03\x04\x06\x05\x06\b\x05\x03\x01\xfb\xdezz\x01\xb2j\x9f\x1c\x14\f\x9ek-L+\x01\xa9\x05\x03\x10\x12 \x15)\x11\x15\b\x04[\x14$\xa98\x03\x01\x01=\x04\x0f\"\x1d.\x1fun\a\x1e/2 \xb4^B\xfb@B^^B\x04\xc0B^\x02\xe3\xb6\x04\x16\b\x10\a\b\x03\x015\x02\b\x03\x10\x05\x16cy\x01\x17\b\x0f\x06\t\n\x9b\x02\n\a\v\x06\b\x03\x03\x06\x06\v\x05\x0e\xee\x01\xd8\xfe(\x01\xd8ݔI\xfe(\x018\xfe\xc8\x01?\x0eC\x17\x10\x19\x10\f\x05\x03\xfe(\x013\x9b>\x9f\x85\x1d #\x0f\"\x9a\xfe(\x1e$=\x03\x12\xfb@B^^B\x04\xc0B^^\x00\x00\x00\x00\x05\x000\xff\x02\bK\x05\xf8\x00\f\x00\x15\x00\x1a\x00S\x00\x8f\x00\x00\x05&'.\x04'&'\x16\x00\x01\x17.\x01/\x01\x06\a\x16\x13\x06\a67\x014\x02&$#\"\x04\a\x06\a>\x03\x1f\x01\x1e\x03\a&\x0e\x02\a\x1e\x02\x17\x16>\x02?\x01>\x01\x16\x17\x16\a\x06\x05\x06'\x1e\x03\x1f\x01\x1676\x12\x13\x06\a\x06\x02\a\x06\a\x06'\x06# \x00\x03\"&#\x06\x1e\x02\x1f\x01\x16\x17.\x03/\x01.\x06'\x1e\x02\x177676767>\x0176$\x04\x17\x16\x12\x04w\x06\x05\r.~ku\x1f\x11\x9eB\x01R\xfe]\xa8\x19 \x03\x04T%\x05z+\",\x1e\x05\xa0|\xd3\xfeޟ\x93\xfe\xf4j\x1e\x0f<\xa6\x97\x87)(!(\t\x04\x03~ˣzF\x04\x0f8\"{\xf9\xb4\x91%%\x16#\x1a\x04\x0e5\xd0\xfe\xfd\x87\xb6)\x8a\x88}''\x8fx\xc3\xeeJ\x0e\x1aF\xdf\xcf0\"H[$%\xfe\xe5\xfeEJ\x01\x06\x02\x06\x11#%\r\x0e\b.Gk2\x1d\x03\x02\x059(B13\"\b\x13?\xa3@\x02\vS)\x87\x1c5\x0f\" \x9e\x01#\x019\x96\xdc\xe2\xc5\x01\x03\b\x1edm\xabW\x03\"\xd5\xfe\xd6\x02;\x1cL\xb765R\x8eA\x020@T.\x16\xfe\x9e\xa1\x01$\xd4}i`:f3A\x15\x06\x04\x03\x01\x1d%%\n\v\x15BM<$q\xf3:\x06)BD\x19\x18\x10\t\x13\x19a\x18a%\x14\x04`\xa1]A\v\f\x17&c\x01|\x01\t\x87M\xd0\xfe\xebs!\v\x1a\n\x03\x01Z\x01\r\x012}i[\x1a\x1a\fF&\x89\x8f\x83**\x02\x15\x0f\x1a\x18\x1b\x1b\f\n\x1f<\b \x95\x8dʣsc\x1c\"\x0fJ<&Ns\xfeF\x00\x05\x00%\xff\f\x06\xd8\x05\xf4\x00\x17\x000\x00@\x00W\x00m\x00\x00\x016&'.\x01\x06\a\x06\x16\x17\x1e\x02\x17\x1e\a6\x01\x0e\x02\x04$.\x01\x027>\x037\x06\x1a\x01\f\x01$76\a\x14\x02\x14\x0e\x02\".\x024>\x022\x1e\x01\x05.\x01,\x01\f\x01\x06\x02\x17&\x02>\x04\x1e\x02\x17\x1e\x01\x036\x00'\"'&7\x1e\x04\x0e\x03\a>\x03\x05=\x1dGV:\x87e\x12\f\x0f#\x17\x1f:\x1b$?+%\x18\x14\r\v\n\x01q4\xc1\xec\xfe\xf2\xfe\xfa\xf0\xb4g\x05\x01\x0f\n&\x043h\xf2\x01T\x01`\x01Zt\x14\x02\xf3Q\x88\xbcм\x88QQ\x88\xbcм\x88\x01pA\xe7\xfe\xed\xfe\xcb\xfe\xdb\xfe\xfe\xb6P\x1e1\x05L\x8e\xbd\xe1\xef\xf6\xe2\xceK!:<\f\xfe\xd7\xf8\b\x02\x02\x1a}҈`\x15\x17d\x91\xe1\x88l\xbb\xa1b\x02\xf0,\xab9'\x1d\x14\x1b\x17\n\x05\x03\x04\x0f\n\r%%($!\x18\r\x01\xfd\xcb\u007f\xbaa\x183\x83\xc0\x01\x17\xa4)W)x\r\xd0\xfe\x86\xfe\xfe\x9a\f\xa1\xa4\x1b\r\x04\x02\x1fо\x8aQQ\x8a\xbeо\x8aQQ\x8a\x06\x93\xd0c\bQ\xb1\xf6\xfe\xa4ǡ\x01-\xf4җe)\x17U\xa4s2\x8e\xfe\x81\xf4\x01XD\x05\x05\x03\x04\\\x94\xbd\xd1ϼ\x92Y\x02\x1ed\x92\xcf\x00\x00\x00\x00\v\x00\x00\xff\x80\x06\x00\x06\x00\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00o\x00\u007f\x00\x8f\x00\x9f\x00\xaf\x00\x00\x13\x15#\"=\x01#\"=\x014;\x01543\x13\x15#\"=\x01#\"=\x014;\x01543\x13\x15#\"=\x01#\"=\x014;\x01543\x13\x15#\"=\x01#\"=\x014;\x01543\x13\x15#\"=\x01#\"=\x014;\x01543%\x11\x14\x06#!\"&5\x11463!2\x16\x01\x15\x14+\x01\x15\x14+\x01532\x1d\x01325\x15\x14+\x01\x15\x14+\x01532\x1d\x01325\x15\x14+\x01\x15\x14+\x01532\x1d\x01325\x15\x14+\x01\x15\x14+\x01532\x1d\x01325\x15\x14+\x01\x15\x14+\x01532\x1d\x0132\xc0p\x100\x10\x100\x10pp\x100\x10\x100\x10pp\x100\x10\x100\x10pp\x100\x10\x100\x10pp\x100\x10\x100\x10\x04\xb08(\xfc\xc0(88(\x03@(8\x01\x00\x100\x10pp\x100\x10\x100\x10pp\x100\x10\x100\x10pp\x100\x10\x100\x10pp\x100\x10\x100\x10pp\x100\x10\x01\x00\x80\x10\x10\x10 \x10\x10\x10\x01\x00\x80\x10\x10\x10 \x10\x10\x10\x01\x00\x80\x10\x10\x10 \x10\x10\x10\x01\x00\x80\x10\x10\x10 \x10\x10\x10\x01\x00\x80\x10\x10\x10 \x10\x10\x10\xa0\xfa@(88(\x05\xc0(88\xfb\b \x10\x10\x10\x80\x10\x10\xf0 \x10\x10\x10\x80\x10\x10\xf0 \x10\x10\x10\x80\x10\x10\xf0 \x10\x10\x10\x80\x10\x10\xf0 \x10\x10\x10\x80\x10\x10\x00\x00\x00\x00\x01\x00/\xff\x00\x06Q\x06\x00\x00\x90\x00\x00\x01\a\x17\x1e\x01\a\x0e\x01/\x01\x17\x16\x06&'\x03%\x11\x17\x1e\x01\x0e\x01&/\x01\x15\x14\x06\"&=\x01\a\x0e\x01.\x016?\x01\x11\x05\x03\x0e\x01&?\x01\a\x06&'&6?\x01'.\x01>\x01\x17\x05-\x01\x05\x06#\".\x016?\x01'.\x01>\x01\x1f\x01'&6\x16\x17\x13\x05\x11'.\x01>\x01\x16\x1f\x015462\x16\x1d\x017>\x01\x1e\x01\x06\x0f\x01\x11%\x13>\x01\x16\x0f\x0176\x16\x17\x16\x06\x0f\x01\x17\x1e\x01\x0e\x01#\"'%\r\x01%6\x1e\x01\x06\x06\x1e\xa7\xba\x17\r\r\x0e2\x17\xba7\r2G\rf\xfe\xf1\xd0\x10\x02\x18!)\x10p&4&p\x10)!\x18\x02\x10\xd0\xfe\xf1f\rG2\r7\xba\x172\x0e\r\r\x17\xba\xa7\x1d\x1a\t*\x1d\x016\x01\x0f\xfe\xf1\xfe\xca\x04\t\x1b\"\x04\x1a\x1b\xa7\xba\x17\r\x1a4\x16\xba7\r2G\rf\x01\x0f\xd0\x10\x02\x18!)\x10p&4&p\x10)!\x18\x02\x10\xd0\x01\x0ff\rG2\r7\xba\x172\x0e\r\r\x17\xba\xa7\x1b\x1a\x04\"\x1b\t\x04\xfe\xca\xfe\xf1\x01\x0f\x016\x1d*\t\x1a\x01\xa3!k\r3\x17\x17\r\rj\xa0&3\n%\x01,\x9c\xfe\xc7\xee\x12*\x1f\x13\b\x12\x80\xd6\x1a&&\x1aր\x12\b\x13\x1f*\x12\xee\x019\x9c\xfe\xd4%\n3&\xa0j\r\r\x17\x173\rk!\x06./!\x06>\x9d\x9d>\x01$,*\x05!k\r3.\x0e\x0ej\xa0&3\n%\xfeԜ\x019\xee\x12*\x1f\x13\b\x12\x80\xd6\x1a&&\x1aր\x12\b\x13\x1f*\x12\xee\xfeǜ\x01,%\n3&\xa0j\r\r\x17\x173\rk!\x05*,$\x01>\x9d\x9d>\x06!/.\x00\x00\x00\x00\x02\x00\x00\xff\x00\a\x00\x06\x00\x00\x12\x00&\x00\x00\x016.\x02'&\x0e\x02\a\x06\x1e\x02\x17\x16$\x12\t\x01\x16\x12\a\x06\x02\x04\a\x05\x01&\x0276\x12$76$\x05\xc1\aP\x92\xd0utۥi\a\aP\x92\xd1u\x9b\x01\x14\xac\x01G\xfe\xa3xy\n\v\xb6\xfeԶ\xfc\x19\x01[xy\n\v\xb6\x01-\xb6\xa7\x02\x9a\x02_v١e\a\aN\x8f\xcfuv١e\a\t\x88\x00\xff\x04=\xfe\xa4u\xfeʦ\xb7\xfe\xc8\xc7\x19\x84\x01[t\x017\xa6\xb8\x018\xc7\x19\x16X\x00\x06\x00\x00\xff\x00\a\x00\x06\x00\x00\n\x00\x0e\x00\x12\x00\x16\x00&\x006\x00\x00\x01\x13#\v\x01#\x13'7\x17\a\x01\x05\x03-\x01\x17\a'%\x17\a'\x04\x10\x02&$ \x04\x06\x02\x10\x12\x16\x04 $6\x12\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x03\xb4\xa33\xaf\xab1\xb3N\x15\xf0\x15\xfeE\x010\x82\xfe\xd0\x01\xda\xf0g\xef\x01\u007f\xbfR\xbe\x02=|\xd3\xfe\xde\xfe\xc2\xfe\xde\xd3||\xd3\x01\"\x01>\x01\"\xd3\xec\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x01\xfc\xfe\xb7\x01^\xfe\xa2\x01v!1f2\x02i\x82\xfeЂwg\xeffZQ\xbeQ^\x01>\x01\"\xd3||\xd3\xfe\xde\xfe\xc2\xfe\xde\xd3||\xd3\x02w\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x8e\xf0\x00\f\x00&\xff\x01\aZ\x05\xff\x00X\x00b\x00l\x00w\x00\x81\x00\xab\x00\xb7\x00\xc2\x00\xcd\x00\xd8\x00\xe4\x00\xee\x00\x00\x01.\x03'&>\x01'&'&\x0f\x01\x0e\x03\".\x01'.\x06'&\x06\a\x0e\x03&'&'&\x06\a\x0e\x03\x15\x06\x167>\x0176\x127>\x01\x17\x16\a\x0e\x01\a\x06\x1667>\x0276\x172\a\x06\x02\a\x06\x16\x17\x1e\x026\x04\x16\x06\a\x06&'&>\x01\x01\x16\x0e\x01&'&>\x01\x16\x00\x0e\x01'.\x017>\x01\x17\x16\x01\x16\x0e\x01.\x01676\x16\x13\x16\x02\a\x06'\x0e\x01&'\x06\a\x06&'&'.\x0267.\x01>\x017>\x02\x16\x176\x1e\x03\a\x1e\x02\x06\x01\x16\x06\a\x06&'&676\x16\x13\x16\x0e\x01&'&676\x16\x01\x16\x06\a\x06.\x01676\x16\x01\x16\x06\a\x06&'&>\x01\x16\x01\x16\x06\a\x06&'&676\x16'\x16\x06\a\x06.\x01>\x01\x16\x056\x04/4-\x03\x05LJ\x05\x0eg-\x1e\x03\x04\x02\a\x03\a\x05\a\x03\x03\f\x06\v\b\v\v\x06\x1e$\x1b\x01\x10\t\x15\f\v6\x1e)j\x17\x102%+\x16QF\x1e)\x12\a\x90\x05\x06\x1f\x0e\x1b\x06\x02b\x01\x063F\x14\x04SP\x06\x14\x15\x1d\x04\x02\u007f\a\f21\x11DK2\xfcA\x06\x10\x0f\x0e\x19\x03\x03\x10\x1c\x02W\f\a\")\f\v\a\")\xfd\x15$?\x1a\x1a\f\x12\x12?\x1a\x1a\x05\x04\x13\f8A&\f\x1b\x1cA\x84E5lZm\x14\x81\x9e=\f\x01g\xf4G2\x03Sw*&>$\x045jD \x86\x9f\xb1GH\x88yX/\x064F\x15 \xfbr\x0e\t\x14\x131\r\x0e\t\x14\x131\xac\x04\x12\"\x1c\x04\x03\x13\x10\x11\x1c\x04\xa5\x04\x15\x14\x13\"\b\x15\x14\x14!\xfdl\x10\x0f\x1c\x1b=\x10\x10\x0f6>\x02\xfa\x04\x10\x0f\x0f\x19\x03\x03\x10\x0f\x0e\x19\xbc\x0f\t\x16\x166\x1e\n,5\x01.\x18\x14\x01\x18\x1a/\xb9\xb1'e\x02\x01\x11\x02\x02\x01\x03\x01\x03\x04\x03\x02\r\x05\n\x05\x06\x03\x01\x05\x10\x17\x01\x0f\a\r\x02\x02\x1b\r\x12.*\x1c\x8d|\x90\x01Ed\x04\x02\x1a!\r\x01u\b\v\x0e\a\x0f&\x12\xf3\v&%\x17&\b\xa8\x9f\t\x1d\x01&\x10\xfe\xf9\x1c5d\x18\t\r\x03\x1f\xa8\x1e\x19\x03\x03\x10\x0f\x0e\x1a\x06\xfe\xda\x11)\x18\b\x11\x11)\x18\b\x0366\f\x13\x12@\x1a\x1b\f\x12\x13\xfd\x01\x1cC&\f8B\x14\x13\f\x02@q\xfe\xf9L?\x03P^\x057\t\x01G-hI[\x0eq\x8f\xa1:<\x88rS\tU~9\x177\x15\aA_\x87I\x10R`g\x02p\x141\x0e\x0e\t\x14\x141\x0e\x0e\t\x01\x05\x10\x1d\b\x13\x11\x11\x1c\x04\x04\x13\xfc;\x14\"\x04\x04\x15(\"\x05\x04\x17\x03j\x1b?\x10\x10\x0f\x1b\x1c>\"\x10\xfdT\x0f\x19\x04\x03\x11\x0e\x0f\x1a\x03\x03\x10\xe2\x166\x10\x0f\n,6 \n\x00\x00\x00\x18\x01&\x00\x01\x00\x00\x00\x00\x00\x00\x00/\x00`\x00\x01\x00\x00\x00\x00\x00\x01\x00\v\x00\xa8\x00\x01\x00\x00\x00\x00\x00\x02\x00\a\x00\xc4\x00\x01\x00\x00\x00\x00\x00\x03\x00\x11\x00\xf0\x00\x01\x00\x00\x00\x00\x00\x04\x00\v\x01\x1a\x00\x01\x00\x00\x00\x00\x00\x05\x00\x12\x01L\x00\x01\x00\x00\x00\x00\x00\x06\x00\v\x01w\x00\x01\x00\x00\x00\x00\x00\a\x00Q\x02'\x00\x01\x00\x00\x00\x00\x00\b\x00\f\x02\x93\x00\x01\x00\x00\x00\x00\x00\t\x00\n\x02\xb6\x00\x01\x00\x00\x00\x00\x00\v\x00\x15\x02\xed\x00\x01\x00\x00\x00\x00\x00\x0e\x00\x1e\x03A\x00\x03\x00\x01\x04\t\x00\x00\x00^\x00\x00\x00\x03\x00\x01\x04\t\x00\x01\x00\x16\x00\x90\x00\x03\x00\x01\x04\t\x00\x02\x00\x0e\x00\xb4\x00\x03\x00\x01\x04\t\x00\x03\x00\"\x00\xcc\x00\x03\x00\x01\x04\t\x00\x04\x00\x16\x01\x02\x00\x03\x00\x01\x04\t\x00\x05\x00$\x01&\x00\x03\x00\x01\x04\t\x00\x06\x00\x16\x01_\x00\x03\x00\x01\x04\t\x00\a\x00\xa2\x01\x83\x00\x03\x00\x01\x04\t\x00\b\x00\x18\x02y\x00\x03\x00\x01\x04\t\x00\t\x00\x14\x02\xa0\x00\x03\x00\x01\x04\t\x00\v\x00*\x02\xc1\x00\x03\x00\x01\x04\t\x00\x0e\x00<\x03\x03\x00C\x00o\x00p\x00y\x00r\x00i\x00g\x00h\x00t\x00 \x00D\x00a\x00v\x00e\x00 \x00G\x00a\x00n\x00d\x00y\x00 \x002\x000\x001\x006\x00.\x00 \x00A\x00l\x00l\x00 \x00r\x00i\x00g\x00h\x00t\x00s\x00 \x00r\x00e\x00s\x00e\x00r\x00v\x00e\x00d\x00.\x00\x00Copyright Dave Gandy 2016. All rights reserved.\x00\x00F\x00o\x00n\x00t\x00A\x00w\x00e\x00s\x00o\x00m\x00e\x00\x00FontAwesome\x00\x00R\x00e\x00g\x00u\x00l\x00a\x00r\x00\x00Regular\x00\x00F\x00O\x00N\x00T\x00L\x00A\x00B\x00:\x00O\x00T\x00F\x00E\x00X\x00P\x00O\x00R\x00T\x00\x00FONTLAB:OTFEXPORT\x00\x00F\x00o\x00n\x00t\x00A\x00w\x00e\x00s\x00o\x00m\x00e\x00\x00FontAwesome\x00\x00V\x00e\x00r\x00s\x00i\x00o\x00n\x00 \x004\x00.\x007\x00.\x000\x00 \x002\x000\x001\x006\x00\x00Version 4.7.0 2016\x00\x00F\x00o\x00n\x00t\x00A\x00w\x00e\x00s\x00o\x00m\x00e\x00\x00FontAwesome\x00\x00P\x00l\x00e\x00a\x00s\x00e\x00 \x00r\x00e\x00f\x00e\x00r\x00 \x00t\x00o\x00 \x00t\x00h\x00e\x00 \x00C\x00o\x00p\x00y\x00r\x00i\x00g\x00h\x00t\x00 \x00s\x00e\x00c\x00t\x00i\x00o\x00n\x00 \x00f\x00o\x00r\x00 \x00t\x00h\x00e\x00 \x00f\x00o\x00n\x00t\x00 \x00t\x00r\x00a\x00d\x00e\x00m\x00a\x00r\x00k\x00 \x00a\x00t\x00t\x00r\x00i\x00b\x00u\x00t\x00i\x00o\x00n\x00 \x00n\x00o\x00t\x00i\x00c\x00e\x00s\x00.\x00\x00Please refer to the Copyright section for the font trademark attribution notices.\x00\x00F\x00o\x00r\x00t\x00 \x00A\x00w\x00e\x00s\x00o\x00m\x00e\x00\x00Fort Awesome\x00\x00D\x00a\x00v\x00e\x00 \x00G\x00a\x00n\x00d\x00y\x00\x00Dave Gandy\x00\x00h\x00t\x00t\x00p\x00:\x00/\x00/\x00f\x00o\x00n\x00t\x00a\x00w\x00e\x00s\x00o\x00m\x00e\x00.\x00i\x00o\x00\x00http://fontawesome.io\x00\x00h\x00t\x00t\x00p\x00:\x00/\x00/\x00f\x00o\x00n\x00t\x00a\x00w\x00e\x00s\x00o\x00m\x00e\x00.\x00i\x00o\x00/\x00l\x00i\x00c\x00e\x00n\x00s\x00e\x00/\x00\x00http://fontawesome.io/license/\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xc3\x00\x00\x00\x01\x00\x02\x00\x03\x00\x8e\x00\x8b\x00\x8a\x00\x8d\x00\x90\x00\x91\x00\x8c\x00\x92\x00\x8f\x01\x02\x01\x03\x01\x04\x01\x05\x01\x06\x01\a\x01\b\x01\t\x01\n\x01\v\x01\f\x01\r\x01\x0e\x01\x0f\x01\x10\x01\x11\x01\x12\x01\x13\x01\x14\x01\x15\x01\x16\x01\x17\x01\x18\x01\x19\x01\x1a\x01\x1b\x01\x1c\x01\x1d\x01\x1e\x01\x1f\x01 \x01!\x01\"\x01#\x01$\x01%\x01&\x01'\x01(\x01)\x01*\x01+\x01,\x01-\x01.\x01/\x010\x011\x012\x013\x014\x015\x016\x017\x018\x019\x01:\x01;\x01<\x01=\x01>\x01?\x01@\x01A\x01B\x01C\x01D\x01E\x01F\x01G\x01H\x01I\x01J\x01K\x01L\x01M\x01N\x01O\x01P\x01Q\x01R\x01S\x01T\x01U\x01V\x01W\x01X\x01Y\x01Z\x01[\x01\\\x01]\x01^\x01_\x01`\x01a\x01b\x00\x0e\x00\xef\x00\r\x01c\x01d\x01e\x01f\x01g\x01h\x01i\x01j\x01k\x01l\x01m\x01n\x01o\x01p\x01q\x01r\x01s\x01t\x01u\x01v\x01w\x01x\x01y\x01z\x01{\x01|\x01}\x01~\x01\u007f\x01\x80\x01\x81\x01\x82\x01\x83\x01\x84\x01\x85\x01\x86\x01\x87\x01\x88\x01\x89\x01\x8a\x01\x8b\x01\x8c\x01\x8d\x01\x8e\x01\x8f\x01\x90\x01\x91\x01\x92\x01\x93\x01\x94\x01\x95\x01\x96\x01\x97\x01\x98\x01\x99\x01\x9a\x01\x9b\x01\x9c\x01\x9d\x01\x9e\x01\x9f\x01\xa0\x01\xa1\x01\xa2\x01\xa3\x01\xa4\x01\xa5\x01\xa6\x01\xa7\x01\xa8\x01\xa9\x01\xaa\x01\xab\x01\xac\x01\xad\x01\xae\x01\xaf\x01\xb0\x01\xb1\x01\xb2\x01\xb3\x01\xb4\x01\xb5\x01\xb6\x01\xb7\x01\xb8\x01\xb9\x01\xba\x01\xbb\x01\xbc\x01\xbd\x01\xbe\x01\xbf\x01\xc0\x01\xc1\x01\xc2\x01\xc3\x01\xc4\x01\xc5\x01\xc6\x01\xc7\x01\xc8\x01\xc9\x01\xca\x01\xcb\x01\xcc\x01\xcd\x01\xce\x01\xcf\x01\xd0\x01\xd1\x01\xd2\x01\xd3\x01\xd4\x01\xd5\x01\xd6\x01\xd7\x01\xd8\x01\xd9\x01\xda\x01\xdb\x01\xdc\x01\xdd\x01\xde\x01\xdf\x01\xe0\x01\xe1\x01\xe2\x01\xe3\x01\xe4\x01\xe5\x01\xe6\x01\xe7\x01\xe8\x01\xe9\x01\xea\x01\xeb\x01\xec\x01\xed\x01\xee\x01\xef\x01\xf0\x01\xf1\x01\xf2\x01\xf3\x01\xf4\x01\xf5\x01\xf6\x01\xf7\x01\xf8\x01\xf9\x01\xfa\x01\xfb\x01\xfc\x01\xfd\x01\xfe\x01\xff\x02\x00\x02\x01\x02\x02\x02\x03\x02\x04\x02\x05\x02\x06\x02\a\x02\b\x00\"\x02\t\x02\n\x02\v\x02\f\x02\r\x02\x0e\x02\x0f\x02\x10\x02\x11\x02\x12\x02\x13\x02\x14\x02\x15\x02\x16\x02\x17\x02\x18\x02\x19\x02\x1a\x02\x1b\x02\x1c\x02\x1d\x02\x1e\x02\x1f\x02 \x02!\x02\"\x02#\x02$\x02%\x02&\x02'\x02(\x02)\x02*\x02+\x02,\x02-\x02.\x02/\x020\x021\x022\x023\x024\x025\x026\x027\x028\x029\x02:\x02;\x02<\x02=\x02>\x02?\x02@\x02A\x02B\x02C\x02D\x02E\x02F\x02G\x02H\x02I\x02J\x02K\x02L\x02M\x02N\x02O\x02P\x02Q\x02R\x02S\x00\xd2\x02T\x02U\x02V\x02W\x02X\x02Y\x02Z\x02[\x02\\\x02]\x02^\x02_\x02`\x02a\x02b\x02c\x02d\x02e\x02f\x02g\x02h\x02i\x02j\x02k\x02l\x02m\x02n\x02o\x02p\x02q\x02r\x02s\x02t\x02u\x02v\x02w\x02x\x02y\x02z\x02{\x02|\x02}\x02~\x02\u007f\x02\x80\x02\x81\x02\x82\x02\x83\x02\x84\x02\x85\x02\x86\x02\x87\x02\x88\x02\x89\x02\x8a\x02\x8b\x02\x8c\x02\x8d\x02\x8e\x02\x8f\x02\x90\x02\x91\x02\x92\x02\x93\x02\x94\x02\x95\x02\x96\x02\x97\x02\x98\x02\x99\x02\x9a\x02\x9b\x02\x9c\x02\x9d\x02\x9e\x02\x9f\x02\xa0\x02\xa1\x02\xa2\x02\xa3\x02\xa4\x02\xa5\x02\xa6\x02\xa7\x02\xa8\x02\xa9\x02\xaa\x02\xab\x02\xac\x02\xad\x02\xae\x02\xaf\x02\xb0\x02\xb1\x02\xb2\x02\xb3\x02\xb4\x02\xb5\x02\xb6\x02\xb7\x02\xb8\x02\xb9\x02\xba\x02\xbb\x02\xbc\x02\xbd\x02\xbe\x02\xbf\x02\xc0\x02\xc1\x02\xc2\x02\xc3\x02\xc4\x02\xc5\x02\xc6\x02\xc7\x02\xc8\x02\xc9\x02\xca\x02\xcb\x02\xcc\x02\xcd\x02\xce\x02\xcf\x02\xd0\x02\xd1\x02\xd2\x02\xd3\x02\xd4\x02\xd5\x02\xd6\x02\xd7\x02\xd8\x02\xd9\x02\xda\x02\xdb\x02\xdc\x02\xdd\x02\xde\x02\xdf\x02\xe0\x02\xe1\x02\xe2\x02\xe3\x02\xe4\x02\xe5\x02\xe6\x02\xe7\x02\xe8\x02\xe9\x02\xea\x02\xeb\x02\xec\x02\xed\x02\xee\x02\xef\x02\xf0\x02\xf1\x02\xf2\x02\xf3\x02\xf4\x02\xf5\x02\xf6\x02\xf7\x02\xf8\x02\xf9\x02\xfa\x02\xfb\x02\xfc\x02\xfd\x02\xfe\x02\xff\x03\x00\x03\x01\x03\x02\x03\x03\x03\x04\x03\x05\x03\x06\x03\a\x03\b\x03\t\x03\n\x03\v\x03\f\x03\r\x03\x0e\x03\x0f\x03\x10\x03\x11\x03\x12\x03\x13\x03\x14\x03\x15\x03\x16\x03\x17\x03\x18\x03\x19\x03\x1a\x03\x1b\x03\x1c\x03\x1d\x03\x1e\x03\x1f\x03 \x03!\x03\"\x03#\x03$\x03%\x03&\x03'\x03(\x03)\x03*\x03+\x03,\x03-\x03.\x03/\x030\x031\x032\x033\x034\x035\x036\x037\x038\x039\x03:\x03;\x03<\x03=\x03>\x03?\x03@\x03A\x03B\x03C\x03D\x03E\x03F\x03G\x03H\x03I\x03J\x03K\x03L\x03M\x03N\x03O\x03P\x03Q\x03R\x03S\x03T\x03U\x03V\x03W\x03X\x03Y\x03Z\x03[\x03\\\x03]\x03^\x03_\x03`\x03a\x03b\x03c\x03d\x03e\x03f\x03g\x03h\x03i\x03j\x03k\x03l\x03m\x03n\x03o\x03p\x03q\x03r\x03s\x03t\x03u\x03v\x03w\x03x\x03y\x03z\x03{\x03|\x03}\x03~\x03\u007f\x03\x80\x03\x81\x03\x82\x03\x83\x03\x84\x03\x85\x03\x86\x03\x87\x03\x88\x03\x89\x03\x8a\x03\x8b\x03\x8c\x03\x8d\x03\x8e\x03\x8f\x03\x90\x03\x91\x03\x92\x03\x93\x03\x94\x03\x95\x03\x96\x03\x97\x03\x98\x03\x99\x03\x9a\x03\x9b\x03\x9c\x03\x9d\x03\x9e\x03\x9f\x03\xa0\x03\xa1\x03\xa2\x03\xa3\x03\xa4\x03\xa5\x03\xa6\x03\xa7\x03\xa8\x03\xa9\x03\xaa\x03\xab\x03\xac\x03\xad\x03\xae\x03\xaf\x03\xb0\x03\xb1\x00\x94\x05glass\x05music\x06search\benvelope\x05heart\x04star\nstar_empty\x04user\x04film\bth_large\x02th\ath_list\x02ok\x06remove\azoom_in\bzoom_out\x03off\x06signal\x03cog\x05trash\x04home\bfile_alt\x04time\x04road\fdownload_alt\bdownload\x06upload\x05inbox\vplay_circle\x06repeat\arefresh\blist_alt\x04lock\x04flag\nheadphones\nvolume_off\vvolume_down\tvolume_up\x06qrcode\abarcode\x03tag\x04tags\x04book\bbookmark\x05print\x06camera\x04font\x04bold\x06italic\vtext_height\ntext_width\nalign_left\falign_center\valign_right\ralign_justify\x04list\vindent_left\findent_right\x0efacetime_video\apicture\x06pencil\nmap_marker\x06adjust\x04tint\x04edit\x05share\x05check\x04move\rstep_backward\rfast_backward\bbackward\x04play\x05pause\x04stop\aforward\ffast_forward\fstep_forward\x05eject\fchevron_left\rchevron_right\tplus_sign\nminus_sign\vremove_sign\aok_sign\rquestion_sign\tinfo_sign\nscreenshot\rremove_circle\tok_circle\nban_circle\narrow_left\varrow_right\barrow_up\narrow_down\tshare_alt\vresize_full\fresize_small\x10exclamation_sign\x04gift\x04leaf\x04fire\beye_open\teye_close\fwarning_sign\x05plane\bcalendar\x06random\acomment\x06magnet\nchevron_up\fchevron_down\aretweet\rshopping_cart\ffolder_close\vfolder_open\x0fresize_vertical\x11resize_horizontal\tbar_chart\ftwitter_sign\rfacebook_sign\fcamera_retro\x03key\x04cogs\bcomments\rthumbs_up_alt\x0fthumbs_down_alt\tstar_half\vheart_empty\asignout\rlinkedin_sign\apushpin\rexternal_link\x06signin\x06trophy\vgithub_sign\nupload_alt\x05lemon\x05phone\vcheck_empty\x0ebookmark_empty\nphone_sign\atwitter\bfacebook\x06github\x06unlock\vcredit_card\x03rss\x03hdd\bbullhorn\x04bell\vcertificate\nhand_right\thand_left\ahand_up\thand_down\x11circle_arrow_left\x12circle_arrow_right\x0fcircle_arrow_up\x11circle_arrow_down\x05globe\x06wrench\x05tasks\x06filter\tbriefcase\nfullscreen\x05group\x04link\x05cloud\x06beaker\x03cut\x04copy\npaper_clip\x04save\nsign_blank\areorder\x02ul\x02ol\rstrikethrough\tunderline\x05table\x05magic\x05truck\tpinterest\x0epinterest_sign\x10google_plus_sign\vgoogle_plus\x05money\ncaret_down\bcaret_up\ncaret_left\vcaret_right\acolumns\x04sort\tsort_down\asort_up\fenvelope_alt\blinkedin\x04undo\x05legal\tdashboard\vcomment_alt\fcomments_alt\x04bolt\asitemap\bumbrella\x05paste\nlight_bulb\bexchange\x0ecloud_download\fcloud_upload\auser_md\vstethoscope\bsuitcase\bbell_alt\x06coffee\x04food\rfile_text_alt\bbuilding\bhospital\tambulance\x06medkit\vfighter_jet\x04beer\x06h_sign\x04f0fe\x11double_angle_left\x12double_angle_right\x0fdouble_angle_up\x11double_angle_down\nangle_left\vangle_right\bangle_up\nangle_down\adesktop\x06laptop\x06tablet\fmobile_phone\fcircle_blank\nquote_left\vquote_right\aspinner\x06circle\x05reply\ngithub_alt\x10folder_close_alt\x0ffolder_open_alt\nexpand_alt\fcollapse_alt\x05smile\x05frown\x03meh\agamepad\bkeyboard\bflag_alt\x0eflag_checkered\bterminal\x04code\treply_all\x0fstar_half_empty\x0elocation_arrow\x04crop\tcode_fork\x06unlink\x04_279\vexclamation\vsuperscript\tsubscript\x04_283\fpuzzle_piece\nmicrophone\x0emicrophone_off\x06shield\x0ecalendar_empty\x11fire_extinguisher\x06rocket\x06maxcdn\x11chevron_sign_left\x12chevron_sign_right\x0fchevron_sign_up\x11chevron_sign_down\x05html5\x04css3\x06anchor\nunlock_alt\bbullseye\x13ellipsis_horizontal\x11ellipsis_vertical\x04_303\tplay_sign\x06ticket\x0eminus_sign_alt\vcheck_minus\blevel_up\nlevel_down\ncheck_sign\tedit_sign\x04_312\nshare_sign\acompass\bcollapse\fcollapse_top\x04_317\x03eur\x03gbp\x03usd\x03inr\x03jpy\x03rub\x03krw\x03btc\x04file\tfile_text\x10sort_by_alphabet\x04_329\x12sort_by_attributes\x16sort_by_attributes_alt\rsort_by_order\x11sort_by_order_alt\x04_334\x04_335\fyoutube_sign\ayoutube\x04xing\txing_sign\fyoutube_play\adropbox\rstackexchange\tinstagram\x06flickr\x03adn\x04f171\x0ebitbucket_sign\x06tumblr\vtumblr_sign\x0flong_arrow_down\rlong_arrow_up\x0flong_arrow_left\x10long_arrow_right\awindows\aandroid\x05linux\adribble\x05skype\nfoursquare\x06trello\x06female\x04male\x06gittip\x03sun\x04_366\aarchive\x03bug\x02vk\x05weibo\x06renren\x04_372\x0estack_exchange\x04_374\x15arrow_circle_alt_left\x04_376\x0edot_circle_alt\x04_378\fvimeo_square\x04_380\rplus_square_o\x04_382\x04_383\x04_384\x04_385\x04_386\x04_387\x04_388\x04_389\auniF1A0\x04f1a1\x04_392\x04_393\x04f1a4\x04_395\x04_396\x04_397\x04_398\x04_399\x04_400\x04f1ab\x04_402\x04_403\x04_404\auniF1B1\x04_406\x04_407\x04_408\x04_409\x04_410\x04_411\x04_412\x04_413\x04_414\x04_415\x04_416\x04_417\x04_418\x04_419\auniF1C0\auniF1C1\x04_422\x04_423\x04_424\x04_425\x04_426\x04_427\x04_428\x04_429\x04_430\x04_431\x04_432\x04_433\x04_434\auniF1D0\auniF1D1\auniF1D2\x04_438\x04_439\auniF1D5\auniF1D6\auniF1D7\x04_443\x04_444\x04_445\x04_446\x04_447\x04_448\x04_449\auniF1E0\x04_451\x04_452\x04_453\x04_454\x04_455\x04_456\x04_457\x04_458\x04_459\x04_460\x04_461\x04_462\x04_463\x04_464\auniF1F0\x04_466\x04_467\x04f1f3\x04_469\x04_470\x04_471\x04_472\x04_473\x04_474\x04_475\x04_476\x04f1fc\x04_478\x04_479\x04_480\x04_481\x04_482\x04_483\x04_484\x04_485\x04_486\x04_487\x04_488\x04_489\x04_490\x04_491\x04_492\x04_493\x04_494\x04f210\x04_496\x04f212\x04_498\x04_499\x04_500\x04_501\x04_502\x04_503\x04_504\x04_505\x04_506\x04_507\x04_508\x04_509\x05venus\x04_511\x04_512\x04_513\x04_514\x04_515\x04_516\x04_517\x04_518\x04_519\x04_520\x04_521\x04_522\x04_523\x04_524\x04_525\x04_526\x04_527\x04_528\x04_529\x04_530\x04_531\x04_532\x04_533\x04_534\x04_535\x04_536\x04_537\x04_538\x04_539\x04_540\x04_541\x04_542\x04_543\x04_544\x04_545\x04_546\x04_547\x04_548\x04_549\x04_550\x04_551\x04_552\x04_553\x04_554\x04_555\x04_556\x04_557\x04_558\x04_559\x04_560\x04_561\x04_562\x04_563\x04_564\x04_565\x04_566\x04_567\x04_568\x04_569\x04f260\x04f261\x04_572\x04f263\x04_574\x04_575\x04_576\x04_577\x04_578\x04_579\x04_580\x04_581\x04_582\x04_583\x04_584\x04_585\x04_586\x04_587\x04_588\x04_589\x04_590\x04_591\x04_592\x04_593\x04_594\x04_595\x04_596\x04_597\x04_598\x04f27e\auniF280\auniF281\x04_602\x04_603\x04_604\auniF285\auniF286\x04_607\x04_608\x04_609\x04_610\x04_611\x04_612\x04_613\x04_614\x04_615\x04_616\x04_617\x04_618\x04_619\x04_620\x04_621\x04_622\x04_623\x04_624\x04_625\x04_626\x04_627\x04_628\x04_629\auniF2A0\auniF2A1\auniF2A2\auniF2A3\auniF2A4\auniF2A5\auniF2A6\auniF2A7\auniF2A8\auniF2A9\auniF2AA\auniF2AB\auniF2AC\auniF2AD\auniF2AE\auniF2B0\auniF2B1\auniF2B2\auniF2B3\auniF2B4\auniF2B5\auniF2B6\auniF2B7\auniF2B8\auniF2B9\auniF2BA\auniF2BB\auniF2BC\auniF2BD\auniF2BE\auniF2C0\auniF2C1\auniF2C2\auniF2C3\auniF2C4\auniF2C5\auniF2C6\auniF2C7\auniF2C8\auniF2C9\auniF2CA\auniF2CB\auniF2CC\auniF2CD\auniF2CE\auniF2D0\auniF2D1\auniF2D2\auniF2D3\auniF2D4\auniF2D5\auniF2D6\auniF2D7\auniF2D8\auniF2D9\auniF2DA\auniF2DB\auniF2DC\auniF2DD\auniF2DE\auniF2E0\auniF2E1\auniF2E2\auniF2E3\auniF2E4\auniF2E5\auniF2E6\auniF2E7\x04_698\auniF2E9\auniF2EA\auniF2EB\auniF2EC\auniF2ED\auniF2EE\x00\x00\x00\x00\x00\x00\x01\xff\xff\x00\x02\x00\x01\x00\x00\x00\x0e\x00\x00\x00\x18\x00\x00\x00\x00\x00\x02\x00\x01\x00\x01\x02\xc2\x00\x01\x00\x04\x00\x00\x00\x02\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\xcc=\xa2\xcf\x00\x00\x00\x00\xcbO<0\x00\x00\x00\x00\xd41h\xb9"), + } + file6 := &embedded.EmbeddedFile{ + Filename: "7e367be02cd17a96d513ab74846bafb3.woff2", + FileModTime: time.Unix(1576651902, 0), + + Content: string("wOF2\x00\x01\x00\x00\x00\x008\xf8\x00\x12\x00\x00\x00\x00\x80\x80\x00\x008\x93\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1aL\x1b\x9a\x0e\x1c\x81\b\x06`\x00\x868\bL\t\x83<\x11\f\n\x81\xc6\x1c\x81\xafi\x12\x81h\x016\x02$\x03\x86v\v\x83>\x00\x04 \x05\x82\x10\a \f\x81[\x1bYr\x15l\\e\x86\x8d\x03\x80\x05\x9f\xedx\x14\xe2q\x00{\xd4;\x8a`\xe3\x00\x02i\xee\xce\xfe\xff\x96\xdc\x18\x03{\xc0\xfc\x1b\xaa\x04\xbbH\xe2\xb0\x03\xa3w7\xed\xcdF\xbc\x05\a2\xdb.5\xfc\x14I\xe9\"P\xdd!S\n-z}n;\u05ff\x90\xac\u0097=w\x8dM\n\xe7\x8b\x0e\xfd4ijJD'8c\xe3\xc3[\x05\a.\xfc\xaf\x1e\x92\x14M\x9e\u007f\xf2O\xf8_gfn\xf2\x00\xe4A\xe8dv\x80>\xa4JTEf\x0f\xcfϭ\xf7\xb7\x01#\x1d\x1b\xa2\x82\x01\xe80\x89\x94\xac!=\xa2rT\b=rԨ\x92\x1a\x82\fz\xa3C\xa4D\xa5\xcfSP̆\xe7\xfb\xfd\xfe\xb7\xb6\x9e{\xbeXv\xd4\x12CR\x8d\xbcF\xa5QIn)\xa9fJ\xa3\x04\x1ao\xf6}\xd3|gwg[\x91V\xa5\x9et\x92}\xf2/\xad\x00\x96\xc7\r`\x00\r`\x01Є\x86\x19\xc0\x0fa\xae\xd7廫;\xddٻ\xd2)@T#u@\x0f\x0e\xfcM\xa4\x00\v6\xa0gw\x92=\xe9\xb1K\x9f\xea\xa7'(\x05\x86\x00\xb7i\xf0,M\x80\x05+\xeb\xfbmj,\xaf\xac\xdc\xc3.\x8f\xbe\xa3s%\x9dK\xf8\xba\xaa8\xf5qx\xd3\xcb\xe9\x0ed\xa9\xd08$F/\xfdI\xae\x92a\x1c\x8a\xf3X7\u05cf\x8c\x8e\x05\x18ߚ\xef\xf2\xdd\x1e$\x13\xdeХ\xc4Sb\xf7\xbd\xafBU\x85\xaa\n\x9f\a\x1e\x88\xaf\xb1\xdf}\x11\xc1D\x12\x95\n\xa9Sþ\x9d\x9b\x9f2\xd0?^\xf6\xcb\xee^i\r#~b#\x90\x00\xf3\x83\xff\xf7\xf7{\xb3]9E\xb9\x85,\xc2M\x1a\xff\x8d\xac\x92\xaf\xafxsKt\v\xaa\n\x15\x82p\x15\xaa\xba\x92\x84\x02\x054\xc8\x12\xe2'\xa3Lj\x89\x1f?\xf3\xa9\xfa[\xef\xec\x94\xdf(\x16}dce\xd8\\\xa0\x0f\v\xcbȘ\xbb\x93N\x91\xceJ\xd1)\x84\xb8$\xfd\xb7\xe2\xd0B՝\xfcA'\u007fx\x92L\x89M\xf37\xbd\x8e\xa5\xf6\r\x96\x8d\xc7\xc8T\xea\xfcOs\xf6&ku;ƌ\x91,\xdd\xe1L\xfeO\xee\xae?\xb94Mw\xae3w\xac\xdf\xfd{\xc7hw\x8e\x15\xe6\xd0\b\vn\xe7\xae+eݱv\n[\xb5U\xadp<$\x12\ajY\x8c\xc1\xba\x16\x87\x83@װ\xa7\xfe\xfcP@T\x99\xc96\xff\u007f\xa8{\xee\xc35Rc>]\x1c\x8a\xf4\x85 E\xe4\xe4DZ☓L\xcdS\x823~l\xf8\xb8\xb5\xe3\r\x12\bК\x80D\xdc.U\x80UTW7,\xb0\x94@4كDN\x04\x97 H\x92 \xa9\x82\xa4\xff\x0f!\x99\xb2AjԂi\xb6\x03\x02\x01Vb*\x04\xe2\xd0\xc3\xf5L\x01\xcf%\x91\x04_ x\x05\xc1\xcd\a\x88_\xeb\x14\xe2\x0f\x94 \x00\xf2\x8f\x02\x16\x99P&,\v~\x86k.#\xf8\x03\x9ef\x1aP\xf5\x04\x02,\xcce\x1cm\xc6^\r\x13\x90\xc4ݱ\x83\x8b\x98W\xfa[9UQ\xdd\xd5R\b\x99\x90\xb9\xd9U\xdc\xc2'jeZ\xf4r\xaf\xcf\xe2[\xb7\x92\xa2\xeag\x0e\xd1w\xfb쁯\xf0mE^w/\xddk\x1f\x9a\xfd\u007fc \n\x18\xb1\xc2\xc0\xba\xea\x9a\xebn\x10!J\x82$\x19r\xe4)R\x82\xa3K\x8f1\x13x\xe6\xac\xd9)P\xa8H\xb1f\x14-\xeek\xd5\xe6\x81vT\x1d:u\xa1\xa1\x1b0hȸy\v\x16-Y\xb5f݆M\x8fm\xf7\xc0M\x98\xf0\x011\xcf\v\x10\x9b\x8c5o^\x0f\xc6\x12\x87\x84TCBd\x8byz\xd8d\x86߲\x1f\xc4\xe4\x9a\xf5]\xf4\xa5&Gzj!\xb0㢊\x93y\x0e9\xc1\x18\x9c\x82\x8dׁ#\xe0\xd4\xff\u0b00f\bNw\x9d%q689\v\xb0^t9\x13,\xf3\x8eM\xf6\xb8\xf9y\x91\x9f\xcf\xcdF'\xcc9y\xcb&\xaf@\x12\x1cs\x1cXr\x18l\x82#\x0f\x03\xae\xd7\xcd+\xe6\xd9b\xa9\xd2࿂_\x1e\x88ɒ\x84\xd4H͘\xf4\x8c*\xcd\x1aHa\xa8 \xba\xd8A\xceB\x00\xe6n\x10\xa5\xe6w\xa1\xe5\x8a(\x01a\x82\xc0\xe6\x06)Ҕ\xe9\x82\xc8d\v\x82\x1c.\xf2\xd0\x14q\x1b\xaf+\vC\x85\x1b\xf4\x93acNx\xf9\x9d\f.\x9a٥\x9d\xd7t\x048\xee\x80\xc7̵\xca+\xd69b\xe7f\xe75r\xb8))\xa4\xc4\\\v\xf7i\xa5\x8d\a\x85\x13\xd95\xc9\x14\xd3\xcc0\xeb玘g\x81E\x96X\xf3\xeb`\x83M\x1e\x17n\xe5\x95'<\xe5Y\xe1v\x8e\xec<\t\x03\x99l\x90\xcbs\xf29\xa1\x98\x1d\xe3\xc2#,P\xfd\x1b\x83\x95\xf5+\x18\t\xe7-Yb\x98\x11F\x19\xab̉\x11\nk\xa1v\x8e\xe8\x80\xe3N0\xcb+QX\x00\xa5\x90\"\x8a\v\xe7rd\x9e\x05\x16Y\xfar\x10.\b\xc0D\x80\x11o1\x8a@\x18\x18\xb2d\xc3A!V\xda9\xa1#\xc0q\a3\xb2\x99c\x9e\x05\x16Y\x8a\x8c\xf0\x925\xd6\xd9\xf0\x9b\xe0qe\x04T\x92\xa1!S\x92JN8\xe1\x84\x13N֟`\xa1\x87\x8f!0Z\x8fO<\x8b\xe4ZS~\x1dl\xb0\xc9\xe3\u007fv\xd8t\x11\x02\x98>ې\x9cw\x16\xc8r\xbeԻ\x10\xf3\xb9\x06r7_`\v%u\xaa<\x9e\xff\x9b;\xe2(s\\\xe7?\xf5\xe8<\x87\xc6\x19z\xf2U\x06\aj\ue032\x1cS\xf3n\xe7\x85zro\x00\xeb\xe4\x9d#\xfa\r\xf7\x98\xfe<\u007f\xb1J\xa7\xa0R\x9bI(\xda\xd9\x01D\xd0\xf2\xbb\xa6+g\xab \uf2d4\xac\xa0\x00\xd9\xcaA\xda-\x8e#'2J\u007f_\x89\xceH\xe6\x97T\x00\x12\xb4|S\xeb@\x8c\xc3\tF\xe5\xac\xee\xa3|\xa2\xf3IX\x0e\x96\x83\xff^\xec\xdc|C\xaa\x9b1_X\xbeA\xa9ǒ\xc6\xf6\xebz\xe1oȏ\xa9\x9c1%D\x1e\x95\x88b\xef\xe5\xc5!\x88\\=\xc5\xc3\by\x00\x9a\xae\xecZ\xdd\xd7\xc8\tWI\xb9m\xa5e\xcb!\xa7&-\x81)7\r\x1d'\x12r&\xf4n\xe2q\xcfT\x84&Y\x0e\xf5\x10b\xae\x9ai0\x18'\x02V\x16\x04%\x18\xf4\x9b\xc0a]\x87p\x8b$f2\x94\xa0i\xd2v\x0eN\xe8<=\xf7\x02c\xa6.2\x97\x00k\xf72[\xf6\xae\xc8x\x96\xab\n\x94\xb8\xa6\xd9\x12a\xab\x1e3}\x164g\rF*\xa2\xf1\x18\x8f\xf1F^\x82$\xc8U!\\\x13\xdcu\x97\xc1-B`\x84\xc5BDLD]$1\xe2`$\xa6\xe0$\xd3L\x88\x91\xacXȉ\x95\xbc8(\x88\x8d\xa2\xd8)\xe9\x14M\xa1h\tM;p\xe6e\x98|.ޤ\xf1x\xd2i\xa6\x01\x9d\xa3\x9d\x81;\xa1\xb3\xec\xc4\xcd>\x9c\xcb7\x1fm\xa6\x10\x0f2\x02\xef\xf3\xc5ȣ\x04\xe2\xd5\xec\xe1HD\x04*\xd63\xe8\xd6\x0f\x86\xb6\xbb\x1en\xd8\x18\x16\xe3䲛0\ve\xce\xe54o\t\xc6\xeab.k\x1e;]<\xb8M\xd2\x10\x86\x88\x1c8ahq\xc0\x06\xb6\x12F\x98\x9bh-[8S\xa4\xb4\xf4\xc9*\x98ہ\xabT\xc6dpc1Fc\xcfd\xf5\xa7\xe5\f\x0e\xca\x1d\n\xa8\xf2\x18\xc6\x18\"\x86\x19\x84b\x91\xf0V\b\xc8R\x19d\x9c\x06\x05\xe6QK\x84\xc9\"\xc1d/\xa0\xe4\xc9/\x9e!\x8c\xc3\x10\x91C\x13\x16\xa3Q<\xc0V\xc2ֲ\x19\xcc\xe0\xc6\xcai\xbf$ӂ\x19f1\x83-\xcf \xa9}$4w\x8b\x0ehܳ\x1e\x89\x05t\xeai&|\xd4>\xfai\x1f\xf9,\x86]{\x95\x87\x13\xe0hVp\x03\x9a\x91\rPdķ\xbb\x1d(H\x90[\xeax\x84\x1a0\xfa\xd6<4\xb5\xc1\xc8\xf3yt\xc1\xc7\xdd\xca\xc5\x00L/\x9b$\x00\xb59-\xf4o\xe0\xde.\xa7\xb5\xfa.?\xc7\x12#\xfcw\x01`\v\x80#N0\xd4\x06*@\xfe$\xf8\v\\>/k\x80\x0f\xf4j\x80q`P\xf1\xe1k\xdb\xdd\xeb\x85M\xc0A\xear\x16\xa0.\x84\xa8\xa3\x80}S\xdf\xcc\rXU\x9c\x9a1ͷ\x1c1\xed\xa1\x17\xde\xf9\a\xbd\x10|\x9b֧\xba\xbdʵ\x0e\xebi\xdd֏\xebo\xbe\x10\xbe\xd6\r\xfd\xff?\xf8\xe4\xf3ɯu\xde\x03\xa3f\xacx\xe9\xbd\xc81)Ĭ\xdd:e~\xf8\x11\x95\xaf\xf5\x1cc\xc6\xf3\xb3ƀ\x1c\x019\x04b\x1d\xb9\xf1\xec\xb8\xe7O\xf7~\x1c\x91K\xac\x18\xbbu\xef\xe3\xee\xd3\xfe\xd8[\xfd\x01\xdb\x03\xf6\x04\x9cK\xec\x1b\xab\x1dMЬ\u007f\x9c\xf6\xf7\x13%\x196bԘq\xc9RL\x984eڌY\xa9\xd2\xc6o\xb7\x13\xa5\xdb\xf2\xc4S\xcfl˰32\xef\xa9ǀ\x03۪\x86ʣuZ\xdf\xdd\x01\v\xc0\x9d\x80\x01x\x8d\xb8\xfbM\x80\xd7\x02\xde\x01\xb8\x04\xf0N\xf1lo\x06\xbc\v\xf01\xc0\r\x80\x8f\x03>\x93\xc5\x14\xf0Y$\xee\x02>\a\xf8\x1a\xe0݀\xaf\xe3\xe7\xbf\x05\xf0\r\xc0w\x01\xef\a|\x0f\xf0}\xc0\xbd\x80\x1f\x00~\x02\xf8(ী\x9f\x01\xee\a\xfc\x1c\xf0\x1b\xc0\xa7\x00\xbf\x15w?\b\xf8\x1d\xe0\x8f\x80/\x00\xfe$>\xfc!\xc0\x9f\x01\xff\x00|\x13\xf0O\xc0\xbf\x00\x0f\x03\xfe\r\xf8\u007f\xac\xee%J\x1f\x05\xa4\xe4'@\xed\xf1\x1c\x1e\x03\xead\xa0N\x01<\x0e\xb4ϊ\x1a\x9e\x04\xda\x0fkx\nh?\xae\xe4i`\xb1\xb6\xbb\x0e\x00\xcf\x00\x8b\r܍\x00x\x0eXl\xd2x3\x00^\x04,\xb6\xac\xe4\xa5\xc0\xe2\x80\xc6\a\x02\xf02`qh\r\xaf\x00\x16\xb7\xd6\xf0J`\xf1\x8e\x1a^\x05l\xb9V\xe8\x82W\xbba\xff\xe2\xf12DX\xe7ʀ\xb54\x8e\xccI6\x05\x06M\x02\xd6Y:\xfa\x86\xad\x1c_\xe7\x87u\x1c\x80kdCMT\\\xb3\xb3\x9c\xaeF\x9c\xb2\xf2\xf73ȟ\x96\xf4\f\xfaE\xaeErF\x8d\xd4]\xbf\xb0\xee\xe6p\xc8 ;\x88\xdc\xdbB.g\xd0\x1d\x90m&\x83\xed\xa0\n\xb6\xb1\x9aq\"\xa4\xf9\xb2\xa7n\xbaZ\xd1\xeb|\x83oTh\xe5\x8b\xdcuT\x10\x98\xf3\xbb\xb9\xf4\x82\r\x0e\x8a?o\xbc\x8b\x94\x19\xbc\x8b\xacO\xe8\xc8\x14}Zg?h\xeb\x14\xffL\xec\xe8\u007fP\xdb4\xe1)\xe3\x86\xf5qЊo\f9\xfc\x9ep\x1b\xb5s\x9fH\x86L\x0f\xa9\xda\xf7\xed%\n\xdaDn\x1b\xe5\xc1\xfb\x15挃>\x10}\xa4\xadI\fn\xa8\xfa\x9a<=.\xf2\xbbk#l\x17\x1cD\xd9\xefr\x8dܸh\x1d\xbd\xd1m_\x8e\x8c\x91Dɽ\x88\xd8\f}G\u007f\xcen\x1b\x9a턚[\xaf\xaf4W`\xe1\xf5\as\xb7\xde\x1c\x10q\x91\xf1ט\xa6\x02\b.\xefG\x02\xe2\xa9s-\xb8ҏ\xae\xc6K\xdd;\xde\xc7G\xfc\x0f\x05L\x9cἿ\xf5\xfa\xfb\xfem\xf8\x80\xf5\x99\x1dX\xa0\xb11\r\xb0\xfd\xe8hB\x00\x02\x83\x04˿\xf1\xca\xff\xffS\x80\xfa0\xe0\x97\xc0*o\x03\xd6\xfe\x02\x00\xfdi\xa0\xed\f\xd8\xf5_\x80\xe1\x19\x15\x9eT!\f\xf7\xb9R\x84a\n\xd76<\xbc\xf1\xe6\x9a\x03\xf9\x85\xe1\x1c\xe91\r\xf4&1\xd7i\x1d\xf4\xa3GV\x9d\x02\x1a\xd3(\x9d,v\xee\xecB2\xd6\x0eH/H\x89W\xd8`+۴\a'\x85\"\xe8\x01\x12\xa5\xb2\xbd;\x17/D\xbb\x18\x8f\xb6(\xe7\xd4}\xaaW\xf1,\xdf2\xa6\x19\xaf\x9cKo\x04ۘ0\x9c\x05\xf54\x1e'0\x90D\x8b\x96\x87\x10ǦmщE\x86\x86\x80\x1cS\x89PП\x97\xed\x10\x05* <\xa7\xcf\x05q%\xe2\x84+\x82c5T2\xea\x97h\x88\x8eK\x84\xcc\xc9\xe1\xf7=\x0e\n\x88\x04/\x1b\xd13\xd8L\v\xb0.\x80(\xab\x8d\xeei\x00\xd0d\xea\x9a\xcaz\xa52\x9bww\x17\x92\x17\xcav]-\x06\xff\xf7\xb8\xe4©\xd5\xf5\xd1X\xed%\x8dV\xad9I\n{\xa4Lw:C\xe7O\x8cm\x8e\x8feծLy\xbc\xa6\x97'j:6\x12B\xe0Qo\xa8\x81\x1eO̐\xe4\x02\x93]\xce\x12\x86\x83\xcd\xedh\x12\x96=K\xa5\x9f\xe2~\xe0\xcaML{\xf9\xca\xebu\xaf6\xa2\xf9e|\x85\xcf?\a\xe3\x9e\x04\x80\\\xf3\x1d/\xd7#\xe1\x13\xde\xfd\xc2=\x1a\x86P\x85\a5\x91\xc0\xed\x84!a ,\x8cF(\x9c\x86\xfe\x1dKK\x11\x8c\xc6]G\x12\x14\xed\xaeg\xc3\xcdu}P\tO\nP\x8d\xea\x02\xf9C\xdc\xff\xaf-\xe0\x93\x03\xd0:HJr\x0e\x9e+-A\xf2w%)\x97\xb2\x80\xb9\x8d\xcfY'Ur=W\xdf\x007\x10\xaa\x9e\a{\xed2!w\xb2:\xbe\x1c\xe4q\xd3\xf8%\xc8Q\x00-\xd7G\xdd\xd7\xeb\x98A\x8a[]g\xed\xb8\xa7w\xd2\x00\xaa\x86\xb1x\xa1\xba\x8f\f\xef\xfcl\xbbӳ>\xbdPSN\xe7\xf4\xbf\xa0,\x8fT}\xfc\xe7\x9e\xef\x19\xfd3w\x95\x93\xd9\xe9)\xed\x02\xd5qZSW\xbex\xf6#\xf8H\x19\x8dI8\xa3\xb7\xc3E\x96\x90\x88\n\xed\xf6\xc3\x17\xdf~\xbcZEvL\x81\xd4\u007f\xd0\xc1\xaf\x87\x0eFį\xa6\x96\xa9\xb4\x00\x85C\x04k>du\xac\xa1\xb0\u007f\xa8|\x8e\xab\x80輑Q?\x82s\xe4\\\x18yѿ\x02m\x01\x14\xd0\x17dh\vj\x84j:\x89K;F\xd1\xe2\x85^\x80\x91\x90\u007f\x1b\xc1\xfd\xc8\xe7\xf0o\x99\xf0\x1c\x9dY\xae\xfam\xa2\xbc\vM\x12~3\xa35\xd4>\x96\xac\xff\x84\xbf\x94R~\xa6\x91\"\x94\xcf=)\xd9#\x9f:\x19ߓ\xb3ݐ\x1a\xfb\x06\xe2\xf8/S-s\x06Ę\xe8f\xabA<\x06\xeaC\xe0#\xe0k\x83O\xc8=\xf9g\xbb\xf1\xb9_\xb8\x88\x19\xf2\x1c\xadI\x14\x93\noA\xe6\xc63Y\xda4\x1d[[G_\xe4\x88\xee4\xf8D%֊\xd4\xd1\x11\x9c\x03G/\xf9Z\xdb\"\xba\b\xab\x0ev\xdcz\x19\x0f\nh\x00\x8e\xd5\xc6\xd0>\xc2\f\x9di\x11\xf7\xb5m\x1a\rE\x0fJjp%\x0f\xbaL0\xd5\xff\x03\x9b'n\xac:\\\xfan\v\xed1k\f9\"\xaem\xb7Gt\xc1\xf5\xf9e\xe9\x0f\x8cu\x01\x91:\x0f\xf9\v\xb1h\byJ\x8b\x85I\b\xf22\xaf\x95\xb1\x96\x9c1\x96\u007foc\xb5j\xa0\x00\xad\xf2\x82\x9a\xcaq\xe0\x8d]\xebζ\x10\x02\xf0K\x16\xfe\x9e\xd9\xe5\x89\xde]|H>K\x01J\xba\x8fM\x8b\xd6\u007f\xb8m\x8b\xd6\xd0\xe9PU`\xb0\xbby\xb95\xf5\x0e\xbb\xa7\x951\x11\xb9\xb1\xb57\x9d\n\x11\xc8DÙ\xbc\xe4˅\xfb\xf3\xb09E\xe7\xff\"S\x8ďuX\x18檞|\xdaw.\x8b\xcc\xe8\xea\x94\r\x84\xcb{\x85Z\xad\xe4v\xa4v\xed\x95gK9w\xa9\x9ee\xa1Ƹ\xda,\xadx4\xb4\xeb60\xe8\xe5\x86@\x9f\xae\x87\xd6\x18\xee\xbe]\x82d\x84\x91\xb8ЭT\xb2\x16\xe2DA^\x1c\x9b\x90\x85d\x84[g\x9c\xb7\xdd`\x87ި\xaaB!T\xd4\xdb\x17+`\xb1G\xe0\xe2b\xeb$\xfd\x86$\xd26\x8c\xdb\xe1\x91D>Ƙ\xb6sa\xb6\x14\x1c\xf0\U0001a9b6i\xf4\v\xee\xc6\xc6\xe4+\\\xe3\xd0G\x1a\xe0̨\xa4\xfe\xe1\xa9+\x0e=\xae醝\xa7=\x83e#Ԋ\x9c3uu\x9f\xf8\\\x18M\"\x18\x9d\x89\xf2pq\xb6\xb5i7\xb6\xf4\xfa\x86\xda\\w\x14\x17ъl\xdb{}\teY5\x93\xb4P\xe2\xe7\x1aT\xe6tڸ\x8ce\xf1\xc2JR\x10e\x96e\xd2\x0f\xbf̆4?r,\x10\xc6\xf7c\xef\xb5?\x101\xd2\xc9z\xffnv\xa0kֆxô\x81\xbc\x86\x03\xa6\x9a\xfb\xca*y\x81\xd1\xf9$\xb6\xb2ֱ\x1c{F\xc7\x1dU\xe4\xabV\x03\xe8\x9a\xdbh\xe5\xe9u_\n(l\x13z\x06\xf1u\x92\x8a\x83\xadw\xa9\x16\x1c\x1d\xef\xa1a\x06\xed\x9f\x15*\x8e\tj^rz\xfb\x87\xba\x1eC\xb6\xd2>4\xb2yrN\x0f\xaaOLυ\r\xe3\xdb\x11x\xfc\rie\xe6c9\xb6\x13vP\x93\x88\xd3M\xf6e\f\xa7{x\x12\x106e8c\xed\xa9sRѲ\xeb\x847\xc0#!\xe7\xf6lT>IVpjz\xcak[R\xe6DB\xce\xe2\x1acO\xcf\xdb$\x1d&\x8e֍7h\x13\xb7X6`\x9d\x04\xa2\xc1\x88\x96\xa0\x97\xc4oJ\xc8\xf8;\xf7\xf4/O\xa9\x82W\x86\x04R\xb6\x8b\xe7bO\xb2\x80\x8b(\x03vق\xa7\xcbp\xf4\xebf\x19\x85\x82\xbc\x1f\x91\"\xad\x85\xad\x01\xdf` \fL\xcc\xebܻ\x85\xad\xbe\xc6\x0f\xc0\xe4\xa5\xc0\xdb\xd8\xec\x03\x91\x17\xde\xf25\xf8\x9fo{\x1b\v\xe0\x0f\xcf\xdd{\xe2\xed\xff9\xf9\xdb\xc7@-\x1c\xb2#b\xeb\x13Ã\xac˚\xc0\xfa\xe9q62^\xc8\xd77\xc6:\xca\xd7[\x84\xd3,\xe2\x82[\x00x\x93Ş\xa6\x1a\x9f\xfb]\x8a4,%\xb9һtf\r'X\xe6\x05\xe3jRX\x90\x96\xdcm\x163_j8\x1d\xa4\xff\xfaS\x95[)\x80|F\r\x92$\x95\x10n\x1b\x1f[\"\xbe\xae2\xbeR[?\xfc\xa8\x11\xf3\x8c\xbc\xdd\xc4M\u007f\xbdԟ\x9d\xd2@\b\x8f\x8d\xf2wO\x8e\x10un\t3\xaa\xf4\xa6\xcc/\xf5\xa2G\nGh\xa8\xd5\x17Ӵ\xcc\x94\x19!\xe3t<_m\xa0\x06\xdbQ1\xa4\xb8\xb0\x84\xfc\xf6\xf2\xfc*jr\xa4\x86$\x93\x93䗎J\x81\xc7\xf0\u007f\xdf\xf2>!if\xf8\x90u\xfd\xe03\xfb\xf2#\xb8\xca\x1f\xed|\xf3f\x13\xc4#\x92Cu\xd0E3\x8d\xee\xdag\x91\xb19}\xe4\xa2\xdc~\x0353\x1dl\x8f\xce8\x96|\x96\xabdK\\iRҏ@q\x12\t\x12M\x1e\b\x1f\xfa\xbb\xb7\xb2\xfa{\u007f0,~\x88Y\x8e\"\x01\x14\xdf\xfe\u05cf\xc7FO\x1e3\a;D\x95\x95\xfe,*\xfe\x9e\x9f\x9d\x94X\x90\xc3\xe9\xca㗚\x1a\x12\x90L\xdc=\x1b*\xe9\x99N\x12\x87\xf1\xb2\x1a5x\xc78z\xb4\xdb>1\xdf\xffx!\x9a\xb8\xf5]\xed\x8c4\xc50\xd5\x04q\xa5\xe2\xeas\xf8\x97\x17\x9c?\xec*\x82.\xe3u{+\xff\x8b\x8c*\xa0\x97\x92sF-Q(\xa6\xa4\xa0ߓ\x12\xfc\xd1\xf9-\xe6\xa8In\xc5{\xc2j\xb5j*j5jX\xb1ΌBذ\x94ST~\xbc\xd1\xe8Qn\xd7R(L,]\x0f\x9f\x98\x8a\xb7\xf7\xf3\xf2\v\xf3r\x8f\xf6\xb1\xa1A\xb5\x87ӽC\xab\xf3\x1d\xed\xb5\x14_\x1f\x1d\xa3\x92Q\x85[\xef\x04e\xec[\xfb\x95\xf5\xc3\xe33=\x03\x92MR\xa6\x19&\xba9y/ы\x1c\xf5\x11\xb0\xe1\x02/\xe3\xbb7\f\x95$\xae\xa3_\x14\x04e\xee1t\xa1\x93\xb5\x8a\r\xe6nOw\x85\xb3|a\xfdF\xf2\x15\x1c}d\xdd}\xb3\xf3\nasQ\xcc\xeb\xa7\xc7~g#+\x0f+z\xa77\xfa\xed\xbb\x1f.{m\r*\a\x81\xec\xd9FŖ\n\xfen\x97\xed\x91B_cTBK\xdex*<\x8aq&FO\vLQ\x9b\x056\xa8S\x9d\xe7\xde}k֢\x00\x06\xea\xf6\x9b\xb7\x13\xa3\xee\xc1\x15.7B\xdf\"\x1c9\xf1\x93\u007f\xf6\x8ed\x9a\xd9\x14S\xcb2\xa2\x98.*\x97\n\xc4\x15\xc5\xfaFd\xfa\x92Λ\xe9',\xf3\xbc\xb8\xf8\xf3-L:H:k!W\x82\xb9\xbe\xfd\xe8\f\x8c\xfb\xf9\xd8ٶ\xc6\xf2\xa2\xfe\x95S\xbf\xb2\xdfL\x9d\xe9\xaci\xc9\xe5\xed\xd2\xec\xf6\n\xe5×\x9b\xaa\xa4\xc0\xac\xdd\xf2\xf1P\x82\r\x13\x10\xbb\x14:t~\xf7+\xe6\x9f\xd9\xf7#\xf4\x06$\xab\x04\xab\rG\xecTV\xae\xa7[P\xb5\xb6\x1en\xa00\x9e\xe4\x924\xba\xfcaS\xab\xa6?\xba\xa8菎༐\x9e\xd4NLc\x91\x044\u007f\x17'\xee\xc5\xfd\xfc\xf4\xd1ōQ)>\x81\xb1i\x0e\x00\x92/{|#\xbe\xb5\":\xda\xc6\x15(g\xa3x0V\xbb[\xdb:x\x94\xb0K\x183\v\x9f?\xe6\x05\xd1\x1e\xea\x18ӣ\x9f\xaf\x1f=\xf9\xb03;\x1aK\xccL\f\xcf'\x83Ta\x9e\xfa\x8e\xfe\x93\x8b\rWR\x1f\x1e)$\n\xde\x13z\x11\xe2U\xd1Y\x19l6\x1b\xbb\xc6s\x9aza\xb2\xfe\x8c\xfbA\x91os\xba\\x^^pa\xbd\x04\xedx\xbb\x05guY\xd5B\xeb\xce\xcec\xcc\x0f*\xf4\xd9\xc3cD\xcf(\x9f\xb2IRbj\xa2\xb627\xe7\xcb@K^\xaby\xaa,-\xad\xed,\xcd$\x95\x8da\b\xfe\x90k\xa0w\x85\v\xf6\xc5\xe7\xd7\xeaE\x1a}\x81\x03\xf6[\xd6SV.\xd07\xe3\xdc;\x8eOs\xeb\xc8\xe7\xdf\xcc+\xac\xca\xee\xe5\xa6'\xde+ρ\xb9\xea\x1b\xa1)k)\xa2\x11f\xf0\x85\xc4\b\xf1OڜF\x9dF\xa7\xb2PHJ\x1b#\x00Z\xe4\x1e\xee\x11\xfe\x9f+\x97B\xb6\xaa\xf5\x87\xf5\xcc\xf5\x93\x1a\xe6\x87_\x91{\x9b\xc4\xfc\xb9D13/\xb6\xe5\xbc㫤悘\xb4\x1aR1\x10t2#~\xd5\xda_.iE\xefo\x17\xbd\n\x8e_\x88\x1cKn**ͩ\x8a\t\xb0*\x8a\xf2v[\x8cr\xbe\x17ЁY\u007fY\x04'd\xcd\xdc\x1dK\x1e/\xb9WR\x1b\xbdI\x0eq\u0085\xa2\xd7\x01\x03z\xa4\x1ebkU\xeeº\r\xd4]\xb0\x04\x18\x9e\x9d\xe2\u007f\xc7\vA\a\xfb\xc3O\xab\xda\x1e\xd4\xdekm\xabz\xa6\x90\xf1\x97\aѱ\xca?Em\xe1\xef\xa1>\x929\x9c\xe7\x1d\xb9֊\x86\u007f\xaf\xe3,\xf8~\xb5\xfd\xe2\x04\xc7\xe5\xe7cܧ\xa9\xed\xe8I,\xb7\u007fbL\b\xb6\x9d\xfb\xda6\xc1\xea\x9az\xa2\xad\xd0\xe1£͝\xe7n\xb7=n\xff\xf7xg\xf1с\x8f\xebz\xf4ӧ\x97\\\xf2.\x8d^j\xcc\xd8\x16\x93\xa9P\xad\xbc\x92+\xf6<\x91\xb3\xea[\xb6\x06_\xcf\xd1\b`$\x8e\x94D\x02\xa6\xfeH\x01X\n\x95z\xe7JP1\xa0(>ʐ\xa3J\xc6\x1c\xb1\x8cay\xea\a\x86\x0eZol\u07bd\xbey\xff\xaal|qaN\x88\xbc\x17귪!\xec\xde\xe5k\xff\x98\x8d\xe3S\xbaj\x16\xbb3)\x80~\xdcm\xe6\x14L\brIqѦ\x1b\x13\x8a&-\xc2\x06\xd6\xe8\xf0{\x1f\xc9X\v\xd4\xe7,\x8br+\x01\xed\xdd<\xd3\x19\x8b`\xa7H5\x18\xe7\xf7\xffn\x8d.\x05\xe4\"cZ\x00#\xa0)\x06dd\xec_\x87\xf7#\x86\xf2\x96\xd2\xfb\f)릔\ue502%W\xc5D\x97\x82p&\xabv\x84mhӤ\x8b\xff\x0eB\x10\\\xaa\n\xfe\xb2\x95V\xd8\xfb\xfe\tS[;\x93gN\xaaWv\xd9\xfc\xe8\xe5\x81\xd29\x9c=\xf6\xc7k\xe1\x91a\xff\x04IZ\x87\xa3\xa0\x05\x19\xec\x9f6=x\"\U0007d7f1\xbf\xf8a*ը\xf2\x83II+\xb1\xf8\x91\xab\x1ef\x1b\xc3\xf7Q\xa06\xea\xf7vN\xc2\xda\xf1i\xb8\xfe\x0e\xbc\xbas2\xc39\xcdP\\5\xd0\"m\x05\x1d<\x1fX\\Ǚ\u007f\x91\x83)+\xad\xcc\xeb\xe5\xfd\xfb\xa4\xfb\x01\x0fhC-*\xfb\xcc\xe4#)k'Og\xc2Kҷ\x91\xe6\xe2\x80\xfds|cl\xda?\x13\x19N\xe1[\xfd\xfea5t\xcfE\xce\xdc\xc1?,\xbf5\xad\xa88\xc3\xce\xff\xee\xe8\xf0+1\xda\xc7>\xf2JZ\xbbq\xd5[Ӳ\x96\xb4\xe2GI\\\xf8\xbe\xa8\xa2)\vX\xe2\x02m\x11\x84x\x06\x04X\xa79`\xf5\xe1\x9by$\xfa\xbb\x9f\x89^\xb1\x96\xd2`\x9e\x87\xb6ȩK\xad\\\xf7\xb9\x1e\\X$֫R\x06hrݰ\x18\xeb\xdc&\xe9!-Q\xfeKw\x02M\xce\xca\xd7\xe3\r\x82\x8dR\xf6\xfb\xda\xfb\x9f\x0f\x15\xd2\xf5\xe2\xfd\x9c݂,\xb4սԹ\x14\uf6d9DX\xe4\xbd|@K\x9c\xb1\t\xacw\xa4!l3|\t^q\xa6NgCU\x18\xe7I\xf3ժR*\xaa|\xd1E:\x18͘XrF\xf5\x14i\x8a\xd1A<\xde\xc7'\xeeQ[\xf7,\x98\x1c\xa5\r|\x9d]\u05ec\xc4\xd0\xe4\xa8\xf8\xf7?Q\x13\xcaCg5\xe4\xb2\xcf&\xcb\r\xc9h\xd4\xfc\v\xe1\xf2\xb4b5+B\x05K\xa2\xe0\x92E%\x8e\xad\x9f\x1d\u007f\xe3\xd4\xc4\r\xb2\xe3\xd7\a\xef2\xb6\x9c\xb8}\x056\u007f\x14f\xf6㓞U\x9b\xf87\x1c\xbf\xc7\xdc\xcdi^\xc9\x03W\xf6m\x01\r\xb6\"\x8c\xbd\xe7\x1d~\xd7k~g\xaf\b\xcf\xe3d\x8b\"\x8bm\x88X\xfc9\xbdR\xc9$\x8dp?\xaaX\xe7\xf3\xc1\x99O\xeby\xeb\x1fW\xa0\xde\a\xfb\x9d\xe2X\u008a\x1a\xcf\xfc\u007f\x8d\x96\x8dV\xff/\xc3\xd0K\xaab\xea\xecd\xc08LƠ\u007fΫ02o\xbf\xec\xc6w\x1b\x1f/\xf0\xac\xa8a\tT\xb1\x8e}п\xfa\xce\xf7}|\x9a\x1f\xec>x &f\xf0\x89\xb9\x8a\xbe\x95\xaesW\xb2\xb9\x00w\xf9\x86\x01\xde۾\x06\xaa\xe9[\xca\xd4\xcbTn\xaf\xf91\xa6g\x1f\xec\xa0F\xb9\xdf\fֹ\xc2qs\x8e\x9e\xd0}%\xe2\xb8Dׂ\b&\xcbv\x86ةYҹcګN\xfe\x19\xde\xed\xcb\xebs\xe7\xa9|\x87\xb4=2\xf7\xc8\x1a\x03Y\xfd\xc6`ٜɨ\x1fӳ2E\xeb\x1dP\x81\xacԏ\x10K\x84\x1c\x90L\xdb\r\x955H\xf8\xcc\xe77\xb3\xc3;k\x1d#>q\xd1\x01^\t\xa5\xb1H\xb8re\x8c\xc6\xfb\xc0\xaa\xa4G\x0f\xab\x12R\xd2\x12R3\xb2<\xca\xe7\x97\x03\xea\xf2\x8b\x12\xd2\xf2ɕ\xe1\x13\x93U\x11\x85\xc5IĢR\xbf\xba\x85I\xb7\xaa\x1cRR\x9a\x1c,:\x9a\xb06\x11y8\x11\x15\xb8\x1a\xfd{\xfc\x9a\x8c\b\f\x9a\b'\xac)\v\xbap\xf8\xd4>\xab}(\x13\x1b\xdf\x10\x1f\x13\xaf6\xa6\x16\x15\x13\xd5\x10\x15+[\xfbp\xdb'\x9f\xfd\f\xfd\xcc,\xfd+\xfd\xacv^\xfb\x10\xcdTCT;͵\x19>\xfd\xcc\xc6\xe4\x91\xcf&\xd9\xc6\\\xa5͉\xb1\xd1wU\"\xc5@\xa9\xa29\x03*o\x8d\xc6wʁ\x00o\xbf[\xa1\rY\xa8J\xe3\xf4\x15\\3(\x92X~\x95\xfb\xfbr\"\xaf\x8cz\x16\x96{{\xe6\x97yy\xe7\x93=\xbd\xc8俧\xa5qZ\xb2r8]\xe9ۺ\x06\xbe\xba8\x91k\x05\xe6\xbežUMU\t\xc5\t\x95M\\\\\x9f\xd4KԵZ\xca,|o\x9e\xf3u\xd3\x14\xfb\xadpG\xeb\x8el%\xa1\xb1\x00Y\x1a\xe7\xef\xe9\xed\x8d7h\xcf%\x99\xa2\n\xddLu\xb5\x15D\x85\x8e\xb5duůW:\xd7EŤ\x97Gx\xdeִV=[x\x8d\xe4M\x89!&7\xc4\xfaT\t\x19ȫk\xe9\xc8K\x04\x95C\x96阩\xbf\xfb\xacX\xf2\xe5Ӓr\x91\xa0νF\xba\xed͂\x18\xf7\xfa쪿D:\x84UTq\xf9\xec\x94uY\x9d\xe8\xe6\xdf\x18\x88E\x153b}(\x80\x0f\xb2V\x8e\x8cǐ{\xe8a\x84=S\xf0\xcc3l,n\x9c\xe9\xc5\u007fhY:y\xb6\xa5\r\n\x9cΩ.\x8a\x88n\xff>i\xc0B\x83f\xb1\xb2\xfc\x8a\xde=\xd9Y\x1d{w^SB\xd7~\x80d\x96\xa6W=\xdf\xd1k\xdc}\xd3\xe6F٩ԛR>\x81v&\x928\x87\xc1|\xf3tc\xab\x8ceS{\x0fo˧X/\x83}.\x86\xb4.\x15\xb3\x03\xbb즁\xd6\xe2\xcaö\x9d=3\x1f\xbf(O\xafL?\xe3>4\xe9C\xf7@p\xbb\x89\x98\x89\x92A\x9b\xb9\xd7\xeaKp\x1c\xbc\xc5\xd8\xde6L.\x8c\xb8\xf3V9\xad2B9\xb0H\xa7\x12w\xfa\xcd\xf3\x10(\xd3\x0f\xaf\xefe+\x05\x97\f.lAe\xf0\\JNɟ\x96\xd0<\xfd\x9d\xa9Ԯ*\xe4\xf7cRjڳ\xf8\x88\xbdԂ\x80\xa3億{\x11A\"\xe3YYO\nt\x9cG\x12\x93\xac{Ee\xaa\xdeJ=\xc8\x18\x8c\xd7qaLb?Ö\xa1c\x9bW;ܔ\xd58\x91\x18\xe8\xee\xa0\xdfTm\xd5\xf2E\xff\v\aY\xa9\x00sU\x1e\xb6E\xc2\xf2\x81\f|\xe7w\x1d\xf5{?\x83\xe4ow]\xa7 \xc6mq\xbcT\xa5*\xfa\xcf\x1e1\xd7\xd3L\x00W\x18\xe32\xbfX\xd8/=\xee\xe8o\u07b3\xa7\x93\xd1\xf4ĭ\xbb\xd7\xdc\x1f\xdf\uea56\xd9\xf8\x94\xe6\xa2F\xf0\xa7g\xcbTC\x93\x0eL\x1a/\x1e\xd5Ռ.G\xbf\x10\x98\v\x8c:\xb8\bu\u007fș\x1c\xa0E\xaa5\x03\xf5\xa7\xa8.\x86\x82њ/\xa0\xca\xd9\xc3(\xd0V\xe1\rrc\xcf\xf1\xe5\xf0m\x1b{\x0e-ˮ\x8d\xbf\xcas\x14\xac\x89\xf8\U000d4613>\x1b\xa2\xe0\xa2\xe26A\b|x\xfc\xe7u\xc82#\xe5\xded\xea`\xb8\x0f.\x96\x98\xf4%m1@\xc9E\xd1y:0u\x9bI\xe4o?\xb2\xaf\xfaqfz\xf5\xe6ro\xcdVFZ\xed\x86\xdaʦ\v\xb9\xeet:\a\x8f\a%\x17\x89\xba\xbee)%S\n)\xa5l_N\x05J\n\x84\xc6[D\x87\xd8\xd8F\x85\xb6FE\xf6\xd7a\xaek&\xa2\xa6.&\xaa\xaeꬦ!&\xae\xaayC\xe2\xffmߨ\x14\xdb\xeb]\x8e\x8a\xad\xe7\xafW\x89E3\xfaDd\xda]\x0ev\x90\xe5\xbftSF]H\t\xf5\x02\xe3\xa5m\x1b\a\xcb'\xf6\x87\xb8;\xce\xf03\x17r{j\xdb&\xc0H\xb9}\x89\xc0\xc5q\x9a?\x8b\xc7S\xc7:\x0e\x96\x17Fs]:\xb8\xfeŬ[\x9e\xda\xd6DX\t\x8dV\xef뼺\xad\xbc\xf7\x02\xe9\xf5>\x8e+\xa2\xc8{\b\v\xff\x00[\x9b _;\xac\x85\x9f\x9f\xbd\x9d\xbf\xbf%\xf7\x05,\x94\x95-\x98\x84\x11L\xceFq\x04\xf7\f\xb0m\x99\x03eC9\xa8:?\x8f\x05\x17\xba\u007fhf\x8c\x14\xfaB<|\xbc\xebQC\x88\x1b?\xa6:\xfcB\xc4\xf7\xf3W\x18X;c:\xd3;c;\x99\x19\xce_\xfc\xe4\x9dz\x11S\xeb+\xe0_O\x9dg\x18\xb8\x1b\x1b\x9f\x1e\x9f\xa6ԙ\xa9^\xac\xce;\x1f>\xc6k۳<7\x14آp\xb1\xb4F\xd2\xe7\x98[\x96k\xaa\xe4N\xf7\xf6þ\x80TF\xa5\x9az\x15\xb0 \xb2V\xeb\x9b\xfdz\x83\x86_\xa5\x86\xf4\xa1\x95\x91>Ga\x82\xb7I\xbbPz\x8d4\xa5\x0f%\x95>'*\t\xde\td\v\x83rc\xc1\x14\x05\x89\xdc*MJF\xa3i\x0f@Ӿ\x06\xad\xf2e)\xa0Իx\xed\x82l\x00\xfef\xa6\x82,\xb4t\x8d\xa6\x9dD\x82\xb7ς\"\xcbN\xf4jR\xbe\x8d\xa2\v\x9a\x10]\xb5\xec\x19\xcd\xf5G\x95\xb9W\xf7\x19\xa7{\xab\xe2/ \xf9\x82U\xd0.\xb1]ى\xe3\xa7X\x02\x0e\xa2\xa9\x06\x02kη&x˱gVj<\xf1o1+tcX\xdc\xc3\x04\xeb\x98ƛ\xc3k\x92\x9a\xed\"\x01\x1f\xd1\xfeЉ\x17\xed\t@s\xe5\xd1a\xb9\x97\xf2\x13\xbc\x95\bV\xde\xda\x19\x8d&\x9a\x03@s\xa15\xc1[\xae`\xc7\x11y%\xad\xdc\xfb4\xf0IT\xb6\x8a0\x9c\x02.\x19\xd0\xf5\b\xa3\xff\xa4\xe6\x8b\xf8\r\rח\xbbb\xa6VtW\xdc]{\x17Q\xd2#z\x8f\xb6\xc4\xf4\xcc\xd4\xc6\b\xd6/X\x03\xae\xfc\xfb\x18P\xd72Gv\x17 7\xa6NsƞCL\af\x18\x14\x06\xb7\xa6\xce\x00\xd8\xf7\xb6\xf49\rL\r\xb0풲\xebG\xe7\x81i\xd3&\t\xa7\xb4C\xa00\u007f\xe9\x9f.O\xf8R÷b\x12\n0\x0e\x9f\xab\xc0\xa9F2\xd5>P\xf7\xd86Q\x81v\x92\xa99\x06.)\x9bȾ\x00\xe4H\xd3\n\xa1qXN&\xe6Xa\x94s\xbfcCj\x8eɒFKja\xe0\x90\x06\xc0\xa7\x80\xf1!\x9b\xc5\xef\f\xfdU\xfc\xa5\xc2\x04p\x9e8\xa7\xf4l\xd8.5\xec\xc4\r\xd8\t\U00109ae6\xc2\x04\xd4\xdfTM\x03u\xc5\xf4\x87\"\xa0퇫\xe1\x83w\x8e\u007f\xff\xbe\x03\x1dV\n\x9c\x05\xf4\x9f\x85\xb6\xd8HC\xd2W-\v\x13\xe8nל)\x88S\xfb\xb6\x9a\n\x13\x109\x05\xf7\xf2\x8eQ\x89\xa5m\xa7\xae\xa6:\f\x06\xc3'6\x1f\xa0-\xbb\xb0\xeb\xabz%8:\x13\xe5J\xd0\xdd\xfb\xef\x92\x15\xa6\x00\x14љW\x81\\:\xa4]\x85\x84\xe9\xa43\xec\xfe\xfc\xa0\x88\xd0\xe9R,\x98\xd5ڬ\x81\x88\xd3\xf2\xb3\xb5\xe5\u007f.I\xb1\xe7\xa2\U0007aacc\xd2&ۿ\x06\x91\x82\x01\xa5\x10\xd0\r9\x98\xc6\xd2\x12\t>\b8d\x06w\ueebc\xda\x1f3炏4\x01\xb1\xf9j\xa3\x06\xd8\x1eK\xd5\x05;-\b\x02(\x81b\x15\x034\xa3\x80u\xc6\xf8iS\xa0\x1e\xd2p\xb3\xb7K\xcc\xd1\x13\x8d\x064p\x92\x994g\xb6\xc1{(쵝\x1bXD\x99˴\x0f\xac4\x02dC\f\xeep\xc7%\xb9\x86\x11\x86\x16\xa1\x9b\x1e\x06;ma\a\xf3\x86[\x9c\xc6|\xb8j\xdb\f_\xc8\xea7'\xcb\xdc\xf0\x86\xbe\xf3\xbfY\xfbw\xcc\fNS\x13Na\a\xbb\x8a\xdb\xeej.\xfa0\xdf\xffi\xecı\x96.l\x97\x8b\x15\xe5|q\xb9\xa7\\3Y\xda\xc7\x04\x97\x1c\x97\x9f\x0f\x83k+\xe9\x8b+\x8e\xff\x0f\x06#\xd6\xfb\xcc\x10\x9c\xe2\r\x81\xc8p\x13\xd7h\x89\n\x9c\xa3\x15\xd0\xd85\xd9i\xc1\x9d\x0e\x8b\x1a&\xeb\x9c\x18\xcd%\x10\xf0\n\xa0\xf5WJ\x88\x0f%\x93\\U\xe3q\x95rMo\x84f̐\x8c\xf0\r\x83\a\x1aXX&\xc9ۀ\xbc\x05W\xb9\x8d\x86\xdf\x0f\xa4\x8cZu\xea{U\x91+\x81Y+\xdc\n\xdbN\xc90\x83ѓ\xa0>e'\xf1\xec\xb5^\xf5!A?\xe4a\x9f\xe99\xf4<{\v\xa0\u007f\xa0\x80w`\xab϶ඳ\xe1\x89˼-\xe9\x01x\xc16\x97Ϥ\x03\xe8\xc1\xa4\xd2\xcf\xf9`I#\xfcD`Q\x92\xbb&=\x84R\xe8\x8bB\x10\xa5]R\xa5\x99\xb9!WP(\x90\f\x112\x12\x04\xee\a\x81\x88\x8b&{\xef\x91t8\xa2\xf1\xea\xbaÃBe̪3[\xaa\x11\x85\x0e\xa18\xc4\x01R\x83\xc0\xa0)5Qn\x82\x13\xc7I\xbf\x11考Յ\x00롚\x90\f\x83ʑ\x0f\x9d\x81c\xf2\xcf\xc1\x13\xff\x98rls\xb0b<\xbb\xaca>\xc2?\xb8\x1an\xf8\x10\xe3L\x01\xcc0/\xc8f\xad\xaf\xf8\x85\x83ߪ\x99<\xa28\xb7e\xd9K\xe8\x94Rލ\x9a\u007f\x9f\x90\x01\x81:T\xda\x0e\x1agjO\xe0\x83\x9f\x8b\xa2s\xc1\xf5\x00oϩ\x14pͬ\xa1\xd1\xe5\xe4`ۿ{\"\x92b\f\x19\xbe\x8f\xafPmTh`2^\xaf7i\x88\x94\xd7+p?\x05?8\xc2>\x8e\xf0\x12\x8e\xef\xb6+\xf0Pu\x1dݿ?h\x84\xdfc(>{&ukPd\xc4&\x1d\x12h\xbaܭ&\x84\x16\xf8l\x023r\x0fڼ\xa8\xa9\xf1\xa9\a`\x1a}K\xc2@Q0LӶÂ\xa82i)\rJ\xbfwۙ\xd4+\xdcհ{p\x00}\xc7d\xe8r\v\xa1\xd90\xa8VF\x92\b{qϡ\xb2$\xee\xafv\x1dU1\xa2\x1bTС)c\xef=)ϋ\x9f\x98㰱^$\u007f\x1b\xbe\xab\x9b\xe0U\xd0\xc2\xfb\xf9\xef\xb4m>\xcb\x0e\x01\x82#1\x8a\"ز\x11m\xc4\x00AT8g\x82-\x17\xf1\x91\xc1\x12k\x86{.8+\xf6\x11?\a\xbaijW\xae\xe4%\xef\xf9J\x8d\x1f\\IEĸ\xf4\xcf0\x92\xae\xfe\xab\xe6U\xf7jX55\x9f\xe6\xeb\xfc\x98\x19\x8eEC\xbf\xc4Q\x88\xe3\xf5\x91JPf3\xb8$N'c\x15\x04 J\xaf&Y\xc6\xe8\xb2IBD\xf1\xf3V\xf3\t\xc0\xdd\x01\x94\xe4\x1bL\xfd!d\x85C|\xff\xd05M1\xacT\x06\t\xbb\x1e%(\xdaTG\u05c9\\z\x9e\xf9\x95\x9a/ƹ\x00p\xf8\xb7*\x11\xd4\x15\x1f\xe2\xa2f\x89\xac\r\x90٨\x82\x15ف\xd5P\x05G8V%\xf5̛\xf1*\x89\x9a6\u061d\\9\x96\xa9\xf26\xc5N\xa8\xad\x90\xfa'8<\x00\x06-{\xebn\xb7\xb6t\xa9\xe4\xe0B\xaaׂ\xe6*\x18\xad P\xce\xd6!\x94#'\x91\xc7\xc4k\x8b\xfd\x8a\x9c\xba\xe14\xde\x19\xb5f\xed\x84\xc4\x16\x1d\x84n\x91o\x91\xd3a\x88V\xa9\xe9\x979\x1c\xadHMX\x17\xccaS\x9b\x14;7\xaa\xd4\xedg\x84 \xac\xa3+\x91\x0e4\xf97+ۥ63^`\xb9\xcab\xd6\x1d\x138\xabLx\x85c8\x184H\x12\xa4$\x19Z\x94E\x1b=1\x87\xde\xfc\x8e:\xc1\xcf\xe58\x96\xae\xb1K\x81\xebb&\xc3\xe8PD\x16\xac\x800eS\xdb>l\x8a߹\x84_9\x84\xec\x8c8\xfcx\xe3:\xc3EX!A7\x84\x99v\xdc\u007fa\xc78Q\xe9\xbc%0|:\xf6\x94B\xf0m\xe6m\x8d\xdd>OؾT\x8e\xfeU\n4W\xee\xdf\x01s\x124\xeb&\v+m\x9d\x16Ω\x98{\xfc87\xbc\x1fo\xe1\x9aA\x02O\x13G0\xe8\ue643\xaf\x0f\x12\xc0\xac\x04\xf5\xb2xf\x92\xbdh\x00$\r\x80k\xab\xe7\xc1\x92\x1a\x06\r\xf4\x8a\xf6\xb6\x0e8e\xe3\xfc\x9d\x1as\xb8\a!\x82py\x0f\xf5\xa0\xf6\xf6\xf1\a\x9e\x98\\\xa8\xcc\xe6\x96\xfb\x02\x89\x19t\xa99w6<\xf2\xab\x89\xdd\xcdJ\xb7\xa5:\xb0\x9d\b'\xfaۖ\xff+\xc3Ș\xad\xbd\u007fc\xc9p\xab\u007fw\"\xb4\xd0K\xbb9\xdc\xfdF+x&<#\x1b\xfc\xe2\xa6z7\x8e\xfa,߄S\xed\xa4\x9a\x1bj\xd94\xa5\xd3C\xb6\xd5\xc8ra\xe0_\x02\xd9\xc4G\xbb\xb2\x8d\xb7\xcal\x92\xa9h7\x94l\xbb\x98\xba\xb2\xe6 ٸ\xf5#otdpLu\x8a\x85U\x98j\xb5\xec>\xc6]C\a\x11\x1d\xc9#aP\x83u\x17|\xa4\xc5\xdf\xf6\xbe\x0f\xf0\xf8\xcdغ\x88fI\xdc#\xf9$\xd4°\xac5\xa3\xdc\xd3:xa\x0e\xab֓U\x93\xa7\xddkĨ\xeb\x1c\x96B\\P\x86\x82R\xfd\xf7\xb7\x1dU\xcax\x8dM\x14b\xd0+\xe6\x9c~\xd5@⫧B\xd6\xf3 \x1e7.\x89R\x02r\x89E\xe6ŝ'\x8bT\x01\x8bJ\n\xb3\xacٖlF\x87\xc9\u007f\xbbQ\xadO\aKW\xf5\xe8>İ\aE8;\x11\va0.\x88t$\xd4\x18 \x86֛\x83B\x15B\xd7)N\xb2\xcd9\xfa\xf8\x0e\x96\x9fO\x96\x15\x91\xd3I^h<^﷽\xdc\u007frՄ\xf8P\\2\xf1\xba\x9dt7\x9b\xfa\xc16r㩽\xa7\x04\x01\x83\xee*\np\x84\xd2LN\nAR6\x9aQ\a\x99\xd9\x05\x05\x12y\x92\xbe\xe1~\v\x99\xbe\x15ŭ\xfb\xf9\x82{Q\xd9\xf29\xc1ř\x1dM\xbd\xf9D\x1e?h\xb29\xb1\x17\xd5z^PO\xb1p\xe7\x95[\xaaF\xbfI\xb7\x15\xa1\x87\xdf/x\xa2d\xb9\xa5\xd7\x1d9V\xaf\x9aȻ<\xc8\xe1\x8b-\xc19\x87h\x89J\xferD\\@Nb\xf7q\xc4b\n\xbdc\xb5w\xfb\xadr\x8eT\x91\x98\xa5\x933@Y\n\xf1R\xfd\xaa\xc7Wr'\xd6\x03Q0:\x98P\xb5\xb7\x10A۰\x8f*O\xfd$\x18\xaa\xf2\xacyi\x9cgi\"\xce\x13\xee%Q\xe0!\xf8c@FB\xd2\xc5\x18\xeb[I,\\ֳ\xacx\xe8\xc4\xed:&\xf1\xb2\xcd\x18F\x91\x9e'}\bJ\xab\xfe\xfe\xa5]PVa\xe8\xb0}zTX1\"\xc8X-\xa0As!\xf3~\x0f\xbeg:\x8f\xeeB\x10\x8c)\xfa\xde\b\x0e\xee@c\xfbT\r\x95`9\xc5\xc2E\\\xc0\xa2\xc5Z탛g\xd3\x03\"\xf5N\xf1l\x84\x93ROȧ뻾TɮA\xdc=÷j\xc0E\xd7\\o\xbc\x8d\x14\xfe\x01\xde\x15@u\xf2\xa7\xff\xc4)\f\xef\xfa\xf5\x1f\x19\xfc'\uf7cd.:\x04\x03V\xfc#\xfa\u07fe\x80\xf9\xb5K6\x00V<\xea?\xbc\u007fu\xbb诲\xef\xfdI\xcf\xe2\xba\xe4\xd5\u007f럵\xadNM#!\x8e7\x84\x8f8\xfe\xd36^\xe3\an\xe5ƣ\rJi\xb3\bv\x82\xf3#\x9dA\xe5\xbbФ\xc06^r\xbb\x1e4\xd7\n\x06l\x81v\xd0\x1eJ\xc12\x98\f\xf5a\xe0\x8f\xedZ\xefI\xad\x0e\xd7\a':\xc3U\xc9\x10&\xb5\xcfpg.\x82\xf7$\xc3\xf9\xf1\v\xca$E\xf8\xa4\fed\t\xe0\xfb!\xa6`QS7J\x13\xa2ox\x93\x9a\x106`01\xfb\rc\xd5\x14/lbS\x96_\xda?^\xf3\x18a4\xa6\x11\x9bDɚ\xcep~~\x0e\xc5\t\x81\xecX\xe6\xd4\xf8\x83y\xbbD~\xd7q\r/\xc6\xdc/Q\xe9\x15\x10\xed\x9a˲\xf6\xfd0\xb1\xb2\x86(\xb6#\x89\xc3PĮ͠`\xbe\x99\xe3\xf0\x94U\x1fȮ\xe3\x1a\x19\x1cr\xed\a*\xe6p2\x877\xb7\x9a\xcb\xc6gG\x16\x87\xd6C\x90\xef\xc3Vb\x1eW\x10\xfb>\xfc387\xfb7\xae\xf79\xb8\x85e\xe9.\xc7*\xf5\x89v`\xcc\x14$i\xd1*\u05f9\xc5h^\xc8\xfb\xe2-\x81J\xe8\xfbN\x9d7\xfd\x01W@\xa1\x00\x00"), + } + file7 := &embedded.EmbeddedFile{ + Filename: "912ec66d7572ff821749319396470bde.svg", + FileModTime: time.Unix(1576651902, 0), + + Content: string("\n\n\n\nCreated by FontForge 20120731 at Mon Oct 24 17:37:40 2016\n By ,,,\nCopyright Dave Gandy 2016. All rights reserved.\n\n\n\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n"), + } + file8 := &embedded.EmbeddedFile{ + Filename: "9f916e330c478bbfa2a0dd6614042046.eot", + FileModTime: time.Unix(1576651902, 0), + + Content: string("c?\x00\x00\x99>\x00\x00\x02\x00\x02\x00\x04\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x90\x01\x00\x00\x00\x00LP\xff\n\x00\xe0\u007f!\x00P!\x00\x00\x00\x00\x00\x00\x00\x9f\x01\x00 \x00\x00\x00\x00\xaeQ\x1b0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\f\x00R\x00o\x00b\x00o\x00t\x00o\x00\x00\x00\x0e\x00R\x00e\x00g\x00u\x00l\x00a\x00r\x00\x00\x00,\x00V\x00e\x00r\x00s\x00i\x00o\x00n\x00 \x002\x00.\x000\x000\x001\x001\x000\x001\x00;\x00 \x002\x000\x001\x004\x00\x00\x00\f\x00R\x00o\x00b\x00o\x00t\x00o\x00\x00\x00\x00\x00BSGP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00`d\x00/\x1c\x00/\xdc\x00\"2\x12\xcd\xe9\x8a\xc8c\xdaW\th1\xb97\xb88\x91\x12\x9d2\x16+\x96\x17sǷ\xa7\xe1\xc1n\x8d\x01\"\v\x16$@6\xa4\x95\xa7Y\xb0\x95G`^4\xb6\"G\xbb\xa9\xa2\xe3\xa6#&\xd7\x1fpJ\x8fl43\xe7o\x8e/i\xbb\x1fH\xb2I1>|6<\xa7\x9d\xb1\x8ey\xe2\b\xe3]\xd9\x1f\x1e~\x91\xad\xc58\xe7\xb4\xeb\x14\xe5\xfa\tU\x04wI\xba\xb8`Ԕᬀ\xb6\xb4\xea\r\v\xb2\x18\xf7J\x91\xe14X\xa3uβ\xb3\xbf2\xaeQ\xa0am\"ֱH\x14\x19\xb4\xd8d\xed\x8ce\x10H\xb7'_\x9b*\xf1v\x90\xb8\xf9\xe3;\xa6~\x9fyV\xa3ƌ>\x99\x97\xb2\x00\x01N̫'m\x0f\"\x9aM\xcbw\xc2\x1f\xef\xc2\xf8( o\xf0\x95\x03s\x8f\x10nr\xac\v\xce(\x82\xd8ʖ\xc2XŽ\xa87\x81Am\av\x00jIPGG\xa7\xe8\xbc\xda<\xb0\x1a\xef\x94X\x97Õ\x9a\x1b\xeb{\x81\x94\x9f\v\x10\x0fׂ\xe4Γ߆=\xa6\xae\xb9\xc3\t9s\x18\xe06/\xbc=2\x8c\xef\xa2\xee\x11\xac\xdf\xc9#\x80π\x89,r\xf5o:\xbf\xb8\x02\"\x8c,\a\xd7s\x9bd\x92Bp\x86\xef\xb0T(\xb0G\x17\x18\x80\x9e`-\xb5\xb0\x1b\x18M\x83[\x02E\x8e`\xda\xda\xd1P\xdcuX\x8bNS\xf95\x85\x19`\xdd\x18FX\xd1є$\xc2\xee\xeav\x02\x1f\xa1\xbe>\x1a\x1d T\xd8\x0f \xb1\x8dP\bq\x1e\xc4>{\x90\xf7Df!\xcfM!\xcd\x1c!\xa6\x80\x98\x8cޜ\f=\xb0\x04\xbc\xb1\xe5\xac\a\xb4\x89\xcc\x1a\xec\xc1F\xbc5\x92ږֽ\xa5\xed\x9dh\xebgh1\x88֏|r\xe7.=y\xf3Ϙ|\xd3\xde\x14\xec\x87\"\x1c\xeeZ\xe5\xe9ax\xed\xb0̸P\xa9\xf8\u007f\a\xb2\xfd\xe7w\xae\x1a\x05\xfb\x1d@TƸZAf\xa44\x99\x1a]\x8a\x9b\x83\x8a/\xb4\xc1/\xe9\"`i\xf3.\x9a\xc0\xace\b\x9e\x17(\xacU]\xc0\a!\xa7\x1b\xf9\v3\x9dT|\xab/U\xa7\x13\x8cDL\xcfW2ar\xb6\x9f\x88\"/m\uee93H\x05'W\x8b1@\xbe\x15\x92\xe0#\xe3\xf2J\xb0\xa1\x86*}.\xcbk\x01\x97\xfcdd\xea\xe3}]\xd1&W\\\xb1ܺF\x17\xd5\xf2\xf6\xbcC\xae\xcb\xfc!\xc3\xfc\x80\x99\xa6\xa1\x96\xc64iEfߴv\xf5H\x89]\x9a\x1az\x1d\xe1\xa2\xd0'b\x14\x17aCa~\xcf0\xf4\xc4\x14\xd5ir\xff\vv\xbe\xbfп\xedh\xd1:d\xf4\xfdt\xcbEhH\xc1\xd7<\x1d^{\x9cL\x88\xc5\xd7Ҥ\n\xfaA\x16\x90\xc3ܣ(\xb2\x8e\rs^\x15\xa2\xe02\xdcU\x83\x91c\xad\xac\xc1l\xcb٢M\x10T\x1a\xd9\xed\x12sE\xae`\xf91P\x90\x89 \xef\x11h\x9c\xe2\v\xb3\xbff\b\x8b7\x95\xa5.\x1fؑR\xeblb,b\xc0\xa4\\\x85\xd1\x06\\\xc0i\xc8#\x04\x11\x90\x8a\x0f \xdf\x1b\xe3`\xe9\xe1\xd7÷\x97~_\xf8\xfa\xf1\xf7\x83\xf2\xc7\xed\x89*\x16\xbe\xd6>\xf6.\xec@P¢\xc6\xe6p\xc0,28\x8cq\aa\xe9\xaa\xdbPM^v\x1e;\x9e'q\xbe1\xa0\xf3\x18\xa6?\x9c&u2\x89c}d\x1fg\xf5\x9f\xb61\xc9\x02d\"R\x98\xd2\x02Ȭ\x91\xd9$\xb3\x87,\x9dHȡ\xf0\xa4mH━C\xb9N\xf5\x00\bQ!\x04\xbal\x89\xfd-\xd9\xef\xb3c\xa2M\xe2+\x10\x84O\nAۚ\x1b\xae-g)\xa1\x81M\x01\xe0a@ʙJr(\x1dS1L\xd43\x90Q#\x12\xba\xf8w\xa3 \x02E1\x002\x00\x84\x1aZRrZ@[(\"RA\xdb\x06\xccQ\x18\xb23\xc4c\x11\x8eC\x18\x8c\x92o=\xe0\xb4>B\x8a馵\x93\xddS\x95\xf1\xb5He\x13X\rp#\xc7ێnt\x94/J\xee\ny\"\xdb-\x12\x85\\Qo\xab\x1a\xa3\x15\xbc\xa5ޜ=c\xbc\x06)\x19\xde\xe2\xba#\x82\xa2\a2^\xd7Rtԓ\xe4\v\xf1\xa8)\xe6\xa2@ۙ\x1d\xb5m;\x1e`\x92\x8aP\x8a(r7\xad\xb2\xbf\x03\x0e\n\u007f\xa0\xd4\xebhwK\x96A\xfaՒ\x1eh\xfe\x8b\x1d\x80\x81h\x12C϶\xe5\x06\x15\x9d\xa4\xb4U0\xa0\xe9+)5\x16\xbeE*24\xb5\xfc\x84LVBx\xe0\xcaP\xd0H%ڑ%\xc9\xe2\xbb\b\xb5\xdex\xf9(!\xb9Qs\xc2\\\xc8^\x8a\x97\xee\fZ^\xc6\x10\xd4^\xb8\x95,\x92\xabp\xec\xdf\x02\x9f>\xb3\xbcI\xf6\xccC9f\v\x9aI\t\x17\x03kH\xc5\b`\x10\xee\x13&\x1a\xe0,\xa8\x032\x13$\x04\x8f\xed#\x8c\x96\x1a\x147\x975\xe2\x8e\x04\xde\xee\x861\x03\xb4\x9aN\xacp\\\xc8\\\x9b\x95Lf\x91uE\xfd\u05cb!\xcaE\x00\f\xeeڸ\fH\xc2?\xb4\xe1\x97\x00\xd0\x06n]\xccj\x83\x01\x88\nvM4\xafB\x03u\xbe\x05\x9dNT\xb8%/0\xe6cZ!\x95Z\xc6\x1c\xd1\xdbq\xc1\xa9\\\x87\x8c\xf4\\\xfaZU\xdf\x0f\x84\xc88\x98\x1e\xddC%>\xab,\x0e\x03B\x03\xe9\xd0\x1cF\xdau:\x1f$\xe9ʃA\x92\xcdv\xc1\xc0\x8a\x12\b,\vk>j+\xe8+\x86\xb1)\xa2\xa5ߵO\xe1;\x8f\xc9\xd5\xf1\xa8 \xaf \x8c\x02\xd4|\x8dz\u007fj\x00\x85^\x86\xbb=\xf5\x89\xeb\\\xe4:\xc8-\v\x96\v\vٺ\xabΤHCGIr\xa2w\x96M\xeaX\f;\x94g\x8cg\xd3C#\xe9\xa4M\xca1\xb4E嫌\xady\x94e>\xc5\xd1@\fL\xcb\xcc\xfflww\xd9\xfa\x89\x94z\x03iTi@6x\xeff\xf21\x10\xef^B\xb6\xecG\xfeًb\xaam\x9b\xe54\x8d\xd4ͦ\x8e\xdbS\x05i\x15\x8a\xc3\x12\xa1ZO\fw?B\xc2\xf4\x8e\xbcc\xa8\xb1y\x8e>\xf9SL\xa6\xc3\xdcw\xad3\xb9N?\xd3\x1c\xa7\x14P\xdc\xd5R\xefWN\x94\xc3aq\xa5\xa7\x19H\xe6]N\u007f\xa4̟\x87i\x0eO\x85U6'\xda\xea\x80;ݶ\x11\xde\x05\xb0\xae\xe2M\xb4\xff;\x8d2<\xefm\xb2<-l\x8f_\xca\x12\xd5Y\x16\xde\xebF@\xf9ΝlĂ\x8a\x9cIBtL\xef\xe3m\xe0\xbeOL\xd5\x1cG>\x9a\xee\x1c\xfb\xa5!(\x98\xdd0-\xba\x88\f\x93\xa7\x849\xd3\xc3r+n\xa1\xbb\xebn\xb6:h`iGƆ\x16\xebz\xbf+)]\xd2\xca\xe4\xe6匔\xa7̲=\xb3pB\u00811K\x02`\xde´,\xbfϏ\xa6]\xf5-\xa53MZ\x1dL\xaf:\"\xe0$Z\xa9o\r\xfa\xfa\xe8\x1e\xd2\n\xf4E\x05\xb8zA\x16\x9c\a\x91(\x1b\x90<(#\xc3\xc0K\xdaT\xce\xfd+\xe5\xfaVK\xe2W\xb5\xe2WG\x92VM\xf6\"Q\xa5\x13\xf3\xa8\x05f@\xf7}\xa2s\xee(\xfffh\x99\x01\xde\x1c\x89N\xb0\xe0\xc4gx0T\xfc\u0083U\xe1M&!A\v\x80P;\xe9P\xc1\xa4ju\x0392\x83\fINR\xf5 \x1c\xa6\xbc=\xd1 q\x1a\x84?\x1a\x9dpa\x92\x8d\x95\xa3\xcf\xe3\xb8\xc6\x03\xd8\xc6\x1f\xe9\x88\az\xc0\x03\x9d\x10\x86p\x02\xa60\x19\xf2\xf0\v\x88\xbe\x12\x1a\xea)\xc0\xa8\xf5\x06\x9f\xc2\no\xc7\x03j\x96n\x13\xa0\xe6\x17R\v\x16*,\x81'c\xa3\x04\xe0f\x82w!\x9eOޒ\xb6]m\xbeQ\vZ\xb4Nf\r؈-L\xe3T\xf3\xbaH\x14\x1b\xacc)\xacD;kJ%\x11\xcd\u05ed\xc9\xe5s&E\x80\x91\x00\xc2D\x99\x8al\x8e\xf3\xb9\xb5('.\x9f\xc1\t\xc8P<\xe533\xb7\x0e\xb4J~5\x06\xb4h\x13`\xd2%\x88\b\xe5)\x00WE\xf7^\xc4\x15\"\xdc\xeez\x86q\xea\xacu\xa9czB\xb8\x8ceN\x93:\xf7L˞jD\x04(cR\x18\x11\xf5\xd25\x19\x82c+\x1aU\x8e\b \x9dq0~X\xec\xccʮ\x934\x95]\x966K\x90\xf4\xd3\xe3ֆ͘@\xd1\xd3G\x8f\xb2m3\xbc4\xf1A\xb0\x00l\x8d-dڙ\xab\bA\xbc\xa7\x8c5xٳ\x12\x10n\x95\xe0\\\xf3\v\x9bJ1\xba@\xf2\xdb!+\xea\x04\xed I3f\xa6><3\x85IZXV3o4\x98\x03\xbb\x1d\xe1\x9cu\x8dp58י\xa3\x9ax\xda\xdc\x12\\\xb7\r\x1e\x17_\xcaUL\x85m\n\xfe\xde\xe5Jȁ\x10\x11\xac\xedQ\xcab\x11\x02\x9c\xcdvQ\x04\xdb_'\xecU8\x94\xf6\xf0ftg\xa3\t\xd1\xd1\x05\xf3dl\xec\x01\xc4s\xcf\r\t\xd0=)y\x14\xaa\xdbS\xa3\n\x85\xd8M\xb3r\x1f\xe9\xe4LsE\xe8\xc9Q\x93 R\xfc\xe5G+#\xaf\x95wJ)\x84\xe4ȱ\x9ev>̼̹^\xe5u\x8a\xbf+0h\xf8kᇫ\xfc\xaa\x15^\xfa\xb0ʾz\xddX\xb2\xb0\xaa\xa7u\u007fպV\xf9P\rI\x92\x88u\x10j~T|\xa0\x03c\x83\x10\xe1 \xf4AOC\xa11C\u0603\xe9\x0e\xe3=\x1c\xf2'B&2!r\"\xc2K\x81&1/D\x89\xe2|W\x04/\xd9q\x1d\xe10\xb0\xebaVlM]\xd2\x11\xc8\xc8H\x92\x86\x0f\xe9\xcd8\xa5\xb9\x82\"2fS\x98&\xe1\x8a`\xbc\xa1\xb8,\xff,Ib\x04V3\xd4O\x12\x01\xbcg\xb4O)\x03r.^\x17\x90\"\x91p\xa1\x17\x04\b\xb8\xb5\x9e܁(\x17\x93\xb7 B\xe2\xc1\x1br\x04\xdb8\xc4ۯ v\x10\r\"\xbe+)DXV\xdb\x1b\xdd\x00$\x93Td\\<\x85\b\x1f\xaa\xa8y\xa1\xea\xdb~>\xd7f\xac%Fk\xbe\x11\xd8}\xd1\a\xe1\x89B\xe3h\xdeb_\x81k\xba\xa3,\xa4j?\x00\xb3\xdblϴ\x05jD\x80\x92V\xb5_?\xb7\x123\x98~\x96\x00\v!\"+\xd6\b\xbb\xc5\xecR\xeb\xcae\xcd{71ڏ\xed\xdd\xf5\xc1\x90\v\xe2\xee\xac\x0e\xa9C\xea\xb9uw)ء\xf2\x97\x0eG`\xbdQ\x89\xe6\x01\x98\a\xc1g\t\xcf́9\xe6aE陷'F\xc0\x18:\xa2\x8cӲ^Ɨ\xbe\xff\xe4k\x14\xa6Dś\xdd\xd4\xe1\xb1\x19_\u007f\x9d`\xe3\u007f\xfb\xad\xcf\x18Fz\xe7pyq)\xcdI\xba\xc59\x9a\xa7\x1f\xd50&Y\x9c$\xfdue\x98\x8b\xa2\xdb\xef\xcf\x1c\xb0\x04T\xa9\xecw\x8cj\x97\x00\x01\xa2.ɀO\x8c\x9f\xd2mX\xab!;\x15\x98\xeacW\xfaި.5\xd0\xf9\xe9\xb2\xbe\x01T\x11tS\x16\x97\xd6$\xb66r\u007f;`O\xfeU0G\xeaͲ\x00u\x8c\xc0t\f\x01\xf0\xf1\x97F9oʵ\x9e\xf5Ē\xa0\x93g\xf6\xf8\xb0\x1b\xacQ\x87\xf5\xd2\xf1!5\xa3\xdb\n\xf20\x9eU\xe5Ҕ\xbfV\x06!\xf1\xc0\xe8\xd1r\xbb\xce7\x03\x83\xb0\xa0=\xb2\x91(\xc8\x1e\xd3\xc4\x05\x14o\xe9\xdc\tM\xfbL\xdc\x1dZL\xed\xadO}\xb0-s\x9c\xab塷j\xb8\x1f@\x12\xa5\xd20\xb9P\xafɥ֊\xa1\xd2a\"\xc1\x00{!\x91,Sl\xf3\x1e\x1c\xea\xc3f\x89\xdc\v(A\xb0\x80\ar\xef\x18\xe2\x91\x04\xf0I\xd0y\"\xcc%}\xc1dbv\xa1\xdd.\x99\x88\b\x13B\xc0\b'\xa1\xd3\xee,\xb0{\x8d#\xe3\x9e\xd5i\xa4ݢq|G\x01\x17\xd0\xe2B\xa5ߒ+Z\xf0\xd23\n\xd1\x12\x82\xbb\x9f\xd6.\xd7LK\xce\xc1\x02 \xb7ZAu\xdb\xdf\x180\n=\x90\xb6\xa4v`{\xe5Jps\xc8\xec\x95\x18P\xa3\xf9\xb3\xcc\x04\x8a\x00\xd1sW^b\xe5ȱ\xc8<\xcfzf\x8a_^\xe2\xd1\xe3|\xe85=\xbaDb\x1d& D\x06#\x12a=1\u008e\x18\x10\xd5\n\xc8\xe0\xc5Ǡ\xf3\xc6l9\x11\xa8\xfd2\xb4\x04\x8b\x94\x11\xf5,\xef\x8f/8,2,\xc7Cp6\x96,\x05\b{\xc8\x06\x96e\x9cU\xebX\x93\xc8\xd20d\x1f\xab^lm\xbbc\xba\xe2V\x1b\x12f,\xcd\x06\xc7\xc6\x11bk\x9d\u007fg\x99;>\xe0S!\x978\x95\xe0+\x9e2\xbf\xbb\xb6\xe8\x86謘\"I:\xb8З#\xb5\xb0\xbeix\xe9\xaf\u007fC,8\xaaI\xdb\xd7G\xc9~\xf81\x82\xd1\xe0\x12\v\xc2\xe6\r?@\x8b\xf4\x82l9\x06B芆\x80\xbdG\x11c\x1c\xdc$\f\x10\x80+\x9dc\x04\x95_\x89\xa3|\xf1\n\xcc\xd0\x10\xa3\x1a\xc0.\xb0\n\x1b\x18\xf3\xdc`\xe9`\xf1\x19]4\x9e\xb6\xa5\x12\xac0,Aq\u007f)\xdc\xc1M9nx\x8c4Z\xc1\xda\x1d\xd1\xc6\x1b?%m\xd8\x1a\xf7\xaa~\fL(X\x8e\b.\xa1\x8cwx\xd1:A\vx\xbb\xa3\x1c\xba\x9a\x8c\x80\xf5\x82\x82l\x8fb\xc0\xed\xa0\xd2eX\x90\x91\x81z@؉[\xfe\x88\x8a\x840\x92\b\x01\xb7h\xde\x1e\xe4V\x16\xf5\xa4\x00\xc4\x17.`|Ι<95JH\xbdE\x9a\x8c˫;3\xf0T\x94\xfa\x80O\xca@\xf4\xa9\x10a\x10\xab\x06-BP\x11\x95\bH2%\xaad近\xa7\xc5\xea\xa4\xd1!\x950(\x1aW\x80\xd4\f`\xcc\xd0>)GL*\x9f\x0f7\xfey\xe8\x82M\xd4\vd\xfcF\xfe\xc3Q\xe5x\xdd\xefJ\xbf\xc0\xa3/\xb8\t\xd4\xe3\xe3xZ.fgА\xe1-\t\xe9\t\x04\xac\xbc\x9b\x824]\x81\xceIJ\x16ޤ\x1a\x89\x86E;p\xcaR\xb4@>\x97*\x10E\xc0\x0f]\\\xa7\x0eT\x10a\xa59b\x8c\xc11\xba\xb6\x04K\xa2\xee\xa6Ӑ3\x9f\x87\xe0\xf8&Z+\x02\v%b\x18\a\f\xc55\t\x84b\v\x80\a\x85\xbd\u007f\x02<[\xfeѢ\xe1 ԡ\xebUɕQCGxL\xf9Y\x17\xa2\xedݡ\xcf^\xfe\xadVTI\xc1+{a\x99\xb0\b_;\x10\x81*\xdf\xfd0v\xd1\x184\x18\xd9\xe9+\xc3\xde\f6\xac\x9e6\xae\xaa\x89\xb6v\xba)\x89=8\x94\x06\xa7P\a\x06\x9f\x19\xad\xb1e3N\x95)ӦZ\x8c'\xaa\xf9c{0\x19ɝ\xfa\x92\fM\xfb\xdc\xf5\x92h\xa9\x10\x17\xc9:`d\x12E\x05\xc1k{\xe18\xf9;\xed\xd4|x\x86\tQ\x9cZ\xc5\xe3\xed\x0e\a\xb9\x1c\xb3R\xd2\xe8\x93ɠ\xedg\x06j\xcfd\x81\xfa\xb8=~\x90y`\xd6\x13 &\x03LA\xf79\x04\xaamݢ\x1e'\xc8GU\xdey\x87A\x1evT\xee\xac \xb8\xde\\\x19 \x81\x89\xd2\xf6\x04!\x90x=\xccb\a<݈z\xcd\xce\xf5W\x00t\xe6\xde\x06\x88\x03\\\x06\x15$\x8a~\xa7\xdd=\xc6\xdf1\xa1\xa0\x94\x1b\xc6L\xc9\xea\\D\xbd\x04\xb5\xcbI\x00\xcc*Ҋ\xeb]\xdf\x04P\\w\x98K\xd3W\xb9\xfa\xe5\x81e\xe3\xd1\xe9\x9e['\x0f98\xa7\x9f\x90\x12[t\xac\x86\x03\xce\xc0o\x06H wb|\fC\xf6.Ѫ^\x96];Dpd:(\xf4\xdd\"\xcc\xcb\xe2ɵcA\x0f\xf7\xd2\x12\xf6X\x90\x99\x95C\x11\b\xef\xe1\xa7d\aQY\xbe\xd1\xef\x8d\x18\xc1\f܆I\xfa\x01E\xa0>\xe2ם\xad\xb5\xd5\xe0\xf4\xben\x82\xc1\xe1zI\x83\x83\x89\x93r\xe8\xfd\xad\xe7N\xe0\xeado\x83\x01\xd2u\xc4\xd1\xcb\xcf\xff\xed\xe07%\xab\xd0\xc9\x14\x15\xbc%\xf3\xb0\be˵\xbb\v+{\x10M\x82]\xb5\xd5\f\xf8/\xcdK\x1e\x1c\xfdY\x10\x14MC\xa2\xb2\x801\x93\xea\x11\xaf \"`\x1d\xd1D\x86\xebS\xd0Qm\xa9S\x85\xf0\x99֚\x00\x96\xedN\xb0\x15\x19\x99Π\xf2\x9a\x1d\x93Ӣ\x8cA\xeb\xfa@Lɣl\xe9\x1c\x82\xfb9\xe0\x0e\xb2n\bW\x96\xef$\x16DC\xe7F\x9f^\x848\"\xca\aC\x13\xbf3\xa3\r\x86\xb0K\x15 \x8f32\xb3)I\x93̛\x90J\x8cap\xe2/\x90o\xe4o\x91U\xd9E\x80b\x8c\x00y\x0e\x87\x01\x85\x8bPT\xf8\x98\xbc\xfb\xa4\x87M\x1fb\xea\xb0\xe0\x87`v\x99D)'\xa4\x9b\xa8\x10\x90\xff\ne\x83\t\xaed\xb0\x96\xb0\xfc ֍-SY\f\xb9\xe3VI\x8f\x9c\x1e%`\x10\x98\xa6\x01\xbc&0\x890\x1b\xb0\x87\x833\x96\xe6\xc3\x196\xab\xa7\x12\xe7\xa7⛛\x8b\xdd{@\x04\xa2\x03\x9bd\xebت\x11\x18\x12\x84ūb\x13)Y@\xb5/\x13\xb2\x02ٹ\x10-c\xcd\xd8\x11=\xa6j\xedf\x84 \xb2Ѣ@\xd2\x02(G^B\x1eg\xf6\xa9\x97\x8e,\x85D\x91\x92\xd6u=-\x87\xf9\x18\xf9\xfa\xb5\xc4隠8\xb5\xed\x18W\xcb֣ \x13\x13\x04\xab\xfeDT\tg@N\x85&\x13\x06\xbe\xa0\v\x8be\xb6\xc9\xc5S\x00\x86\xac\xa6\x89X\xfc\xebV\n\x86\xfe\xcf\xc7\xc3K\xb5\\\xf5\xe8\x15\x90\x8e\xc5(M\xa8\xb2\x9d}\xa6u\xfb&\xf2\x8b\xf5\x86\xcen\x8c\xe4\xe52\xa8$N\xbd\xcdn`\xb2\xaf\xf2\xc7\xd8\xe4\x92! \xd4w\xa1\xec:\x86\x88\b\x93\x93\x89\xfa\x02\x93ڃH\xb8\r\f\x02\xf2\xb9\xb2\x12\xa6\xac\ue0dd!\x84\\u;`d\xed\xb0\xd8\tQ>\xc8/\xc4\b\xcf\xee卦\xc6\xc6\x1d\x9bP\xf8z\xe1J%\xee\b;\x11\xa4yc\x88\xa4&\x1b\xa9y\xa8\xf0\x18:\x0f\x16\xf0e9.\xb8\a\x05c\x161M\x86\xa8\x98\xa2\x1bR#\x9a\xe1^\xdbK\xd0#\xab7A\xfa\x929\xb7o\x05\x8e\x00\xfb74\xd0\x05\x9be'&\f|\u007f[\x93\x87\x1cx\xc0\xee}\x18\xcdf\x8beUk\xa8)\xeb\x10\xbbf\x9e\x8d-\x00)E\xccm\x96\f\xdcy\x9cR^\x1f>\xcf5W\x8dř'H\xaaӃ\x1f'\r\x1c\x94\xba\xc3F\x04\xe3Q.\xec\x18\xe8\xacW\x88\xcb\xe4:\xfb7HeX\xa4\x1b\x1eg\x9b\xb0\x0eD\xa5\xe4\xb4\xc7-\xe7͆.#v\xd0d\xb7\"\x11q\xf4C\xdb\x141\x92\x8a\xea2\xad؎\x9c\x1dX\x8c\xc0\xc4\xdbX\xe8\tDU\xa3\x99A+\x14\f\v\xff\xea\x1e\x98\xf2'T\xcb\x13\xf1F\x1a[\x9fM\fm\x8e\xa3\xaeW7\xedA\xf6\xd6\xcb:\xc1\x0eC\xc4\xe1>\xd0~w1R7\xa3\xe0\xea\xe3\xb8ƈɉ$\x8c=zQ\x82\xa6\x95\xb0\xd3E\x95H\xf3E\xcbJ^2Xo\x19\x8b\x17\xf5u(#\x9d\x99\x0e\r\xad\xf2n\x9b\xbb\x10\xfa\x93\xafx\xf1\xdc\n\x019G\x80ť\x99\x17p\xa5\xf4°Y,\xccL\xf4\xc1q\x82'\x02S\x1d\x19\x05w\x8e\x03\xd5\xc1\xf8K\xbeL\x10J'\xa5L\xe8\b\x93\xa9tj\xc0\xa2C;b\x06o.\xda\x02YN\xb2'\xd1\n&O%l\xb3[4#\xeb\xc1\x9a\xb7\xf1\xd8|F?N\a\xbb\xd4\xc1\bk2\xcd\xf8\x02\xb1\x8c\xcbt\xd0\x00,\xed\xe4?=RR\xa7\xf9\x92n=\xb2\xad\xa5Xܿ\xbd\xb9\f\xd4\xd1+\x02\xaf\x8c\xba'_\xa9\xb1\\\xbagD\x12፺\xf93R?g\x1e\x95LC;&g\xb3\x9bd\xaaĤ\xd3\xeaC\x8c\x8d~z\xf5 \xa5\xe5'T\xc9dW}-[\xbcB\n\xcco%\x96\"k\u007fW\xc8IFtS\xc0\x91\x11p\x11\x82\x81z\xe0\x81\x9fl\xea\xe9\xef\x82\xe2ʪ!\u007f\x8a\xbdmK=\xcdenf\xcb\xc2z}\x92\x85\x95f\xeb\x19f\xa7\xf4q\xa2J\x06*\x12bm\x0f3\x032\x04\x9a\x05\x82B\xde\xfa\x13\xa5P \x04\x8e0\xfb\xa3\xbah\x8d\x80\x91\r\xbc\x95%@\x04X\x962@\xac:\xcd\xd2\x1d\xa4\xbc\xb7j\bG\xb3)\x9fi\xcb\xc0\x9cA\x80\xa6bb\x1c\x00)\x82j[]ubj`\xcdjE:o|\xa5vI\x1dm:<\\\x85\x01]\x98\x99\x10:\xd6=c\x11\xabi\x8e\xba\x8e^a\xe2\xfc\xa2\xe4L]\x83\xe3\xac\xf0\xedc\x1d\xca\f\xc7@L\xc5\u007f2\x84\xb6\x8c\x81,'`V5\x91\x8aґ\x90\xcf\xd0+\x1c\xde\x14\x80|3\xcfhT\x9e9\x84\xa8i_\xd9\xf6\xad\x94zU){\x9bx1h\x17e\x86\xcfT\n\x05tG\x05Z}3v\x14\xb9\x99@\xa0\xd9ݽ\xdc\x11\r\x0f\x91\xc9@\x98\x94(1\x94\x1b\x160\x8bF\x96/\xa0\x98\xf1a\x82\xc3&\x94\x9b/\xa0\x84\x86\x10\xe3Y\x81E\xa2\xbb\xb2\xe8!\x03`&\xc0\x82Ӻ\x18WL\xc0\xe5\x81\xe6\x90<\x13\xd5*\xfa/\x88\x83\x8c\xe0>\xf4\b\x80;\x99\xf5\x83t\xb0mbXY\x06U\xabU\xa6\xa1\x0e\x95\t\xc9v\xc1,\xb2?\x9cE\xee\x02\xc1\x95\xe0R0$T\xc8@%\x0fԝ\x1ah\x04\xd6\xd1\xc0\nq\x11\xba\xb7\xe65[\xb9Þm\xc7,\x84\xb6R\x16H\xd4&\x9b\x13T:t\xa8]z\x8b\xcc\x1f\x05\xb8\xf6\xd0R\xf4\x0f\x84,\x0f\a\xb7W1\x88o\x83\x82,\t\xe6?\xdd\b2w\xb9\x03c\xe1\x91Ӻ\xbd\xa6\xe7Z\x01>i\xbb5\xa0\xf5#ʕ4\x02\x02\x9ae\xbb\x03P\x8a__(\xa2\x17|\xae\xd2\bD\xa9'@\xb9$_\vM͉$\xd0i\xb6\ah\xa5\x12\x10\xeafǝL\xceB\x047\xde\xc4\xf1\x19\x9fSZRA\xf6\x81\x84Gbx\x8c\xf0\xa5a\x81K_\xb9\v\x9b\xbe\x1d\xb9\x0ev\xaf\x1c#\xf51'\vm\xb6\x91\f\x17%\x89Z\"\xce&\x92\xa1\xaf\x05s\x8ba\xe1;I=\xdeQ\xeea\xd05\x90\xf2Ove\x14BV\bb\x1f4\xea\x14ƅ\xebS\x05\x85\xb3|\xc5\x1dlW\x10\xb2+Bŵto\xd1\x16\xcc\xd5L\x16Lj\xa5\x02n#I\xdb\xeb$1n\x84MfB\xd9\v\x9a\x0e\x94\x1d\xdbZ\a\xb98\x8dЇx8\x85\xb1]!\xe7է~7g\x85\xaf\x99\x0f\x8d悔ɛ\xf7\x1c\n#`D\x19\xb50\x12H\x18\xb6ߊth\xf23{\tA38\xad0J\xe9&ƠJ\x90\xc9\xc6B;\xc8\xf4RR\xa2\xf1\xda\x03\xe8y{\"\r\xfdL\u007f\xaa#>\x18\xad\x18ڀ\x01\x8bG\xa8\xf2\xb7Ą\\t\x1e_\x1cqS]\xedaQC\x06d\xf8\xa3\xd3H\x1e\xde\x14\xc9\x12\xe5u\x14\x18?Ċ-`\xed\xb6@GVЈ\x928^܊\x03\x90\xbep|\xc0\xec`ڱ\xe3\x11\xef\x06U͂\xcc\x10\"\xf2݇_\xc8\x0e<\xc4\x1c\x15\x90s`C\xbe5pWT\x88\xf3 \xe0\x9d\xddIa\xffN\xc7\xccO\"\\\beW\x834EO)v\xa0\x92`=\x9co\xbc{\xbaͤ\xb9\xa6g\xfd\xfa\x8aJښ4q8p\xdf\amg\x9b7\x10\xec\xadg\xe8\xfe\x88\xc3V\x134c\xbc1\xef\xeb\x11\x14\xea\xa2\"\x17\"@X\xf7p\bqK\xa2\x87\xb3o:ϱ\xfa\x9a\xf8x\x96,\xef\x00Rs9|\xc9\xf7\x10{Wp\x18\xfe$\x1dm\x8f\xa6\x17\xc1v\x18\x80\x1eܻ\xda\xc2t\x898\x0e\xe6\xb5\xf9\x02\xd6y\x11XM\xc7vKO\xd0,\xeb\"\x1e\xeb:ut\xb3\x96\x05mn\xd4\xff\xdc\xd1\x05o0\xd9b\xfc%<\xb0[\x1c\x05CEpB\xc1\x9f\x94\x85\x1a\xffȐ\x00=_(uR\xc9'ntU\x9a0Ѫ\n\xd1\x19\xfcG\xbc\xb2\x01w\x05z\xd5\t\x89\xb4\x16\x98\x1c\xf6p\xf5\x80u7\xc5P_f\xf6\xc1\x838\xa2\x85\x04\xfdb\x8eA\xe0\x88\xbdd\xe0\xf0X;\xe8\x9cNO\xc8\xc2\x05\x97܀R\xf5x!}\xf2F\xaf\x84Eh\x82\xec@DQ\x05 w\x9c\x95\xe6ya:G\xdap\x89\x80\r\x164\xa7\xc2\xe4\xe6 <.\x1d\x93\xb5\xb2f\xb6I\xc1\xf7r\xb7\xab\x878\x89\u05f7S\xcd\xf7Ik\x9a\x8b\xcan\x9cv\x11\xd4\xf6\x87\xe1pG)\x0fo\x9ej\x9a\xf9\xf9Bbi\r(\x04\x80\x84x\xa7B\x8d\x11)\x80C5\x10}a\xe6\xd1\x0fۓ\xba\xb8{=\xf2\x8a\x8fz Eۄ\x181<\x8a_K,J\xa5\xf5`5k\x92\xeb\t/\x11\xf1\xb0V\xb2VK\x10\x86\u05f6C\x12xY\x1dR{F\xb4\x9c\x1a}\x1f\xd0|\x89\xc3&\xba{\xe4\xb2\x1c\x02\x9cz-\xf7\xb0\x8c\x10\x95(\x98,\x1b3\x8cu\x11\x0f+\xf5\xc0ݦ\xc7A\x17\x83\xc2\x18\xa9@q\x14D\x88\xa7!]\xac\xbf\x9dLа\xd0˩\xeaI\x91\x80T*\xb04\xd5\xe9uE\xe7\x03\x84 \xfa\x84\xe9\x1d.\xf9\x13\xaa%\x8d\xc0\x90\xb2\xe5e\x9b\xf7\x98\x8d\x83-\x82\xfa\xb8!\x1fʐY\b\xca\x03s\xa2\xae֔p\xe4\tD(\xd40\\\xab\t\x9ej*w\x81 \xc10?q\x11\xacw\xa0\x19Α0M\xc2tN}S\xe8j\x8e\\\x89\xb3\xa0\x16\xc8e\xa5\x1dI\x8a\xb4|\x86f\xf2.\xd4TP\xe8R\x12\x10\u009e#\xd4\x14\x95\x16@%\xd5i\xee\xf6\xba\x83\x99Г\x16\xb0\x90ao\xacQ\xa0\xd4\xfcqM\x90a\xa4R\f}\xff\xa2\xb4\x86\xb0\x97\x80F~i\xd6/\xc8d1m\xafS\xe5\xa3}\xedT\xfb;aP8\xa8\xc9j\x19\xbb9\x9e2~!\xe5\xb6oE\xd8#\x17\xcat\xf0\xe8h\n[\xf0\f\xa4ff}\xab\xd5\x13;\x83\x0f9f\xb5\x11\x99\x02| \xb6AOj\xba\x13\x8e\xd1\xfdxy\xf4\xa2\x89TH\t˄hb!\x12\x8d\x97\x92\x89\xc5\xf4!\xe1\xd1\n\x8cfJQ\x1cNX\xc8\xf0 \x9d\xc1\xe2\xef\x02\xbc\xb3\xd3\xfaF,J\xd7;lh\xd1뭽\xb3:\x92\xba\x00\bf\xa27\xde\x1d\x90\xbc?\xa2\tB\xaa,\xea\xb1\xc5V\xde\xf1B\xf1\xb9,\x83zb\xf8\xa0GR\xfc\x80\x8fD\x12\fu\xc1^\x9d\x19\x1eܚ\x99\x19\x8c\xb4W\xf9+\xe1F\xd1a,\x88\xf7%\x89J\xd6ɠI&\x03C\x97\xfc\x9ah7#)_\b\x05룳\xbd\xba7hTc\xce7%\x97Y\xd0$\xa6\x83Q\x82=\xb59-|c\xe7\xd8\xe4~C^(\x84\xd4r\n\x89\x11J\xe3\xaef\x87$\x94\xd3jw\xfb\xd8\x02\x0f%\xf3\xc4\xe2t\xf3\xa4\xc6\x16\vY#\x82Cg\xc1\x06L\x1e\x94U\xa6\x03E\xf3%\x01\xe5\x06\xb09\xec&@\xec\xe1\x12\b\xdcR\xd6AF7!\xbc\x19\xe6\xede0M_>\x0f\x846\x0f\x99/\xaecU\xf5\x81\xcbk\xeb\x8c\x14A\x80\x041\x80s\x86\x00rT\x94\x18^\x80)]*\xeeT\x93U\xa4%\x02\x9c\x9bM\x14\xf7[\x03^R$\a\xd4I\v\x89)8l.\x1f\x95\xb6\xa2\xd3&J\xdb\xd8\xf3\x15\xf6b\x9b~\x8e\xd49\x80\x16D\x8cסι\xed\xedO\xe8Sp\x06\xd1\x1b\xae\x8cU\x10\x90\xc9\x17\xcaFu\xac\xed\x9aH-\x19\x1bb\xc3f\u007f\xda4B\xcaw\x04]\xef\x90\xeb\xf4\xb5,%\x97\x95kJ^\xcaPHh<=\xa2(\x00\x8b\x0e\x82ЅL\xc8\x00\x00\xe8\x943\x00@\x066v)6\x8a\x14s\"\xb3\x11Z\x119h\x94C\x99\x04\x83\x92,\xa0\xfcȐ\x11\xb1u\xdcm\x9d\n1\xd8\xff\xa7\xf1xe!\xe8\xd0O\x88r\xed\xe1S\x9d\xa6\xb9\x0e\x19p\xa6-\xf2\x87\x02\xcfx\x87\xfc\"\xfa\xf5\x95g6A\xf3\b\x86\x02e\xfb\x85\x92\xd39m|[\uf82dWl#ov֒(UZ\xf0\x99\xbfq\xd5Lg\x14\xa7P\xa0^\x16\xbe\xf54\x84C3\xe3\xaeW\xbc\xff\xae\xe3\x94Ԟ\xae\xe2\x19\x1f@\x8eϓ\xa6ڵ\xbf>\x03\x8cWH\v\x02\x14\xafy\x899\xf4\x86\x95\n\x01\xc2\xd2Z\xe5\x8bv\xdf\x01\xc5\xfezf\x15.\x1f\xb2T\x0f\xd8>Ɠs\x020#U\xdd\xe6\xb20\xd0߇\x18^\n\x17\xf5\xc7\xc7\x1d~\xa7\x88k\xc5\x17\x11\x81\xa6L\x06\r\x80\xc0*\x1d\xa9EP\x93m\xe6Z\xbd\xe6\x12\xac#>\xe7~>^\f\xee\x93|B[\xe2\xfd7\xe2D}\xcbX?,\uf543~\xc1\xec\xc3n8<,\x9f`\xc4L\x00+8\xac!\xc2/\xcet\xf7\xe4\x89\xf6X\xbb\a\xdd\xfe2\xbc\x89\xf4w\xa5]\xd4њ\x01l\xfc\xda\x03j3\xdaJ\xd2\xc6s\x90io\"{\xba\u03a2'b\xda?\xaa\n%\xfb\xfeYPa\x80\x97蕄\x10\x98Ql\xc1\xd4\u007fCW\x12\xfb\xca!-\xf9\x92\x82`\x8cq\xfc\r\xa2T\xa9\x9c@t\xc2]\xab\xa0\x01\x81\xfc\xba\xdda\xd8\f\x11\x1f]6\x9b\xd0\x04\x86H\xc2mB\x844L\xd0TD\xbd\xa8rh\xa5\x03\v@\xf1Dj!\x01L\xd95\xfb\xb5\xc7\xcdz\x80\xae^\xefh\x82\x10\tR\x05\xfaѼ{\xf2\xa0\x10\xd1w\"TOv'\x01:\x9a\xf5\x0e\xdd;\x02\xe3\"\x8f\x8c\xa8lA\x01$q\x13\x02\x9d<\x8c\x11TB\xfa~\x11\xc6\xd5\xe0\xfa\"\xa0\xd5_S\xc5ϒ\x164%U_\xd5\xff+\x01m\xab=r\x84\v\x99XD\x98\x9c\xfeT[!\xfd\x0e\xd2\x156\xd4P\xd3\x1a\xad\x01U\t\u007f\x01D\xd0I\xa7^\x1e\xdc\x0eG4Spv@9\xabG\xfaQ\x93]m\x12K\xf4\xfb\xbc(\x92J\xdcΓ(/\xc7녬\x85\xfe\xac\x1a\u007f\x04\x82w\f\x9d\x02\x80\xd5dz\x8d\x1b\xaa\xf4P\xbf$\x01:\xb7\x03\xe6Q!0\x97ᆦ%\f?,O\xbd\xd4n\x97\xbe\xdfw׀3T\xab\v$;\xc0\xa9\"\xc8$\x97\nG\xc0\xecl\u007f\x1b\tc(l\xe0\x86\xb8\f\xf4mj\x1a6\xeb6\xb0p\xf0\x81\x86\xb9\xabz\x838\xady\xf7h\x90Jy\x8fʏӽ,\"\x1e4?6\x8a;\xb9\xab\x00%\xd0&\xe1C*\xe7afb\xf0\xbeؓ\x99\xf2\xa3\xd9&\xf1\x83I\xaf@\x80\xd8zҌ\fo\xf0\x11V\x17\xb7\x81\xe7\xd4؛O0\xa1k=͘C\xb2>A\xf32\x81\x84\b\xb5\xb4\xa3\xa2\xe8#[3\xd0\xeb[3\xd6\x1f\x8c46\xbbʖ\x11\xfd\x9bʐ\x0f\xa1@\xb6\x98\x83\xa1\xc0\x9f\x04\x0e\x9c\xe0k\u007f\xc0K\x81\xca\\\xe9\x15\x1e\xdczh\x1cd\x11Eϋ\xc4H\xc0\x10\xd7\x1f\xac\xf41rO\x1ff\xa4\xf4\xbd\xcd\xc8\xdcR{K\x0f\x84rC:\x9ej\xa0KV-\x00\x00\x1e\xf1\x00ᄽ\x82\xf1A\u007f\xc7\xee\x1dUx)\x8c\xd0N[\x82\xa8fڄW3\xdd(8\xb0\xb99\x91\xee\xe8L)\xe6E\x0fE\x9d\xa4\x1ec\xa4l\a\xfb\x84\x86\xc7t\xc0\x86\x04F*^\x98[\xfe\x9dt\xdc)\x81\x88\xa1\xaf\x04Id\x04g7\x98uZ\x8ak\x1b,\x00u.\xc8e\xe6\x9c\xf2=%\xd4\x16\xe8*\x8f\xec\xc1\x96\x88\r\xf1\xc9\r\x14v\x97\x01\xf7p6\x13%\x8cp\x1c\x9bi\xf7]\x022\xe9\x8d\xdc;V\x0e\xc8+&\x97\x97\x11\x1d\xe4\xa6\f\x0e\xa8/\xe74k\xaeA\t\xd9_\x11'9$\x94b p\b\xcc\x1b\u007fƄ\x03\xc5!u\xba\xdd\xff\x9f̵D\xddTF\x92\xbaY\xf0\xfd\x17\x85\x8b;\xe8b\x1d\x04\x1b\xab\x81\x02\x1c>d\xbbE\x81ʼn\xf7@\xda\\\xddM\x1c\xe6\x92\x04I\x00\xae\xbeܞ\u007f\x1c\xb5\x15\xa0\x86O\xd4\xdem\u05cd\xfb\x16\x1c\xb92s\x02\xb6\xa4p\x05\xbf\x1b\x1e(\x17\x16\xe1)\xf3\x9e\xb7j867B\xc6z\xd0!\t\x05\fݐ\xcc,\x06\x02\x8a&\x80\xceNU\x8f\x93\xb78\x98F#\xbeԝ\x14\x8b)5\x19a4,'\xafOI\t\x12:g\f\xbdJ*~w\xe4\x1dj]\x1c\x82\xb1%\xfe\xcaG\xc4L\xd4\x05\xf0nߗsL4z\x90\xa9\xf8\x1c8\xb50~\x81\xb9\x0e\x93\x89iAOH\xcc\x12\v\"\x98\x8b\xa2\x17M\xf3l\xc0\x9a\xac\x9a\xec\x84r\x81$>\n\x98\xcfo\xf0o.rB\xf5\x94\x8ay\t,9\xb4\xf2\xa6e2\xc3\xff2M\x04\x03C\x9d\"zQ\x1f\b=\xe0\xcf.\xa4\f[wԡ\x8e@\x18\x89LXy\xfdg>\x8fjz\xbbI\xc0\x98\xad\xa3\x0e\x86\xc9\xdb\xc3\xe3\x82\b\xb5v>\x04S5Oo\"..\x1c/Ѡ\xee=\x8f\xdb\x04x\x02\x82\xf1\x11\xd0ױ\x04\x9f\x90LT\xd55i@N\xd0\x15yԿ@\x8c\xf2\xb4\xc7\xe6\x0fE\x86\x90\xfd\x9d\x8a#F\x99\xb9\xa0?\x94\x97\xca(\x10\x04\xc3\x1d\x17\x835:C\x86\x13\x9d\x98\x8e\xc6\xee\xa5%\xfc\xd0\xc4.\xe1\x86\"\x14\xde$\x84\xbc\xc8'\xf5\xc1d\tW\xe7\\\x1d\n4\xf9iFҔ\x1e\x8c\xe6@\x14\x02#\xea\xc9@dY$\x05\b2\xcb\xccg\x16\x14\x03\xd5<+\x18\xb3\x85\x9b\xbe\xcbR\xfb\xb9\x92\xe7\\y@\xf64\x9ej҅[w\x02\x86.p)\xf5\x9d]\xcc\xcc9\xb6o\x80\x1dg)y¥\x97\xd7\xcd\uf634UX:\xd7\xfe\x9b\x89#͈\x8b4\xb2\x94\xc1\x9fR\xec\xaedWb\x95\x9d)\xde\xd0z\x1a\x13*SX\xe5\x9dy\xa5\xa9h\xb2\x84F|\a\x8f\xeb;劀\xbbu\xc0\x16\x01c\x0f\xe1\xa9$\xa0X.;~\\\nD\xd1\xf4\xc9\a\x90\x16RyD\xb4{<\x1a\xf6Ҙbtg\x8c\x86\x18-\xea\x19C\x12'Ͱ }T\x01\x10\\\xeb|Q\xc3\xf2\x97\x1eh\x00\xf0R2j\xfb\xc4\n\x14\xac\xd5=\x9c\xd2\xd4\x1f\x87\xf9\x1e\xd5G\x90\xd8'\xb74\xe7\xa0\xf5\xaa\x8c\xb0u\x82\x8dйk\xf9m\xa5\x98}\x1b\x02º\xd2\xf6\x05\b\xf9\xd9\x1cg\xeb\t\xb8Ub3\xdc\x10\x01\x05\xd0E\xb3o\ry\n\xf3PI\xd1ȭD\xfe\tf\xaaNIC\xbc \xc1H\x169Øj\x1e\xea\x89sUuM\x144\a\xcb\xf4.6\x82\xfch\xe5\x11\xdc44\xfb\xfc\x97,\x9aB\x85n\xae8\x03p\x14;\x0f\t\xec|\xba8\xc0zBP;\xf6\x83q\x99\x91SD\xc2:8\xa1\x11oy\xe0\x15P\xddJ\xa8\xdcF\xdb\xfe\xe5\x11\t\xd9SC\"2S\xc0|\xa3=\f\f\x86\xfa\x17\x95HN\xc8\xf0f\xf2\xa6\xd1\xf8\xf0\x84=\x16\x91\xdd*}X\xd2\x00\x93і\xf5\xba\x83\x01\xc1\x98:3J\x96\xba\xac߉\v\x98pT\xdc\xf7Ϸ,\xffn\xa7\a!\xd5\x05c\x86s\xe4\xe4\xd2be\x9d{\xc6\xe8F\xf2\x14\x0f\xf0\xda,Rc`\x94\x11\x1cTϖ\a@~\xdaif^\xa8\x8f>\x1bDEyP\xd1Y\xc9\x0f\xe3\x9aN\xd0\xc1\x16_ȑ\xb3\n\xcc\x1f\xec\x18\x8c\xe5t\\#\x14\x1d \xd5\x14.6~\xb0\xe1\x1c\xc7\x15\x90\xbc\xdc69\x8a\xbc\xbf\xd3\x1bi\x0e\xb2[O4e4D!M\x18 \t\n\xd3O4\xb7V\xfa\xe84\xed\xaa1\x8c\xbc[sf1\x13\x01\x1c\xbe\xb0\x0eJrn\xb0\uf566\x15\x15\v\x90\xaf<\x81p\xf2\xd1\xfd\xb6\x13D@s\x0e\x11\x00\x94\xf0DK\x10T|\t\f\xcb\xd2\xca\xfc\x18\xcd)ؕ\x1f=\xa7\xf3]\xc8\xce|\x9c\xea\x1b\xf2o\x14wJOiƍ\xbc@\x9a\xb9X\x14s2\xfa\xd5\x1a\x04\xe3\xc4\x17\xc2\xca\xf5H\xb5k\x13j\x97\xb6[\xa8\f\v\x8d\xa3\x0fl\xa5\xd7\xdab/\x12\r&1\xfdYsV8J)\x93\x03\xf9<\v\xe6\xff\xc8\x02\xa4\x12\x1d\x06\x11\x17q\x9a\x1a\xa1\x96k/\xed\x93g\xcbd\x95q\x1cw\xe4\x01Ɵ\x84\xf2\xb41\xdb6\xa5\x8a\x9c\x8a\xad,0\x8aπ\xb6e\x18\x9cT`\xa4$\x87z\xff7\xdb\x16\xa2\n\xf5\x18\x9c!\xbcDûa\x8ej\xba\x11,\u2d7d\xc4kKᱪ/\xfa\rw\xd1\xf6Ȥ\xcf*\x1cU[+\xa3\xf5\xdb1\xc4b\"\x13\x86\x0e#m\xc7T\x87Y\n)8l\xf2\x98\xb0#\xb8lvK\x85\xd85E\xeb\v\x82\xfcI\x91]`\b\x89\xa3|\xbcԍ\xa7OC\xe7d\xca\xcd\xf4)UlL\u007f\xd4m\xcd\x01Hn\xeb4\xfb\r\xd7Uv\xf0\x9bk6\xber\xb8\x06\x93\x8cM\xc3\x0eO\xc9\xf1\x01\x10\x06Ɛ[\xe9<\x94\xfaI\xfcX\x0e\xea\xee\xde\xceO\x9b\xa6\xfd\x01Ͱ\xe7\xf9\x89Q\x9f\xa9{C\xe8Yf}\x012ZP\xcb9+fRHU\xdf`\x10\v\xa8\xe9SvLE|\x95\xa2\xf3't\xc4>^\xcd9$qz\x17\x8cV\x8bm(y'\x85-\x02\xc6D\xb9IK\x1c\xb6T,OT\xd6\x0e\xf1\xa8\xad_\x96q\x14\xceZh.\vʓ\xe4\xcfe7\xc2\xf1垼\x04\x84\x9f\xa6\x04\t\x9e\xad%\x88R\\\xb1\x99jjv\xe1\xc9\x12\x85\\)As\x88\xfa\x1d\xaf\x05/\x89\xb9\xac\xc6\x1fH\x06\xb0U\xb7`S\xb03\xd2!s\x1d\x96د\xc7\xf40\xfcx\x88W\xbd\xa8eHt\x87{,\x00\x1b\b\\\xeb\x05S\x0f\xd9.\xbc\xa9\xfb\x0e\xb3\xba4\xb2\xac\u007f\xceT\x8e\xed<\x11y\x11<\x1c\xd3\x0ezx\xc7\xfdKh\x9b\a5\u007f\f0-Ph\xa3\x8a\x8c7\xbe\n,)ZR\xa3\xf0\xf9J\x8b\xc3b\x0e\x1bA\f\x83\xb9\x94\x00\a\xcd\x0f\x1eb\xc6p1tLr\xdfL\xb3Zg\x9a|\x8d\xc0\x93\x05\x98\xad\f$v\xdcP\x93XJ`\x14\xa0\n\xbd\x05\xf9\x05Q\x02\xe4\xc1c\xc1j\xf4\xcf\x17\xacZ\u0530\xa6\xb6qcr\xe9K\x02\x94[!G\x03\x899\xb3\v\xb1-_\x94\xea1\xbc\xc9\xc5\xf0\xaa%\\\x90\xed\xe1\xad\xfc\vX\xeboIh!\xae\xf0\x9d\f\x0e\xff\xaa\xca:'\xa5Gb\xa8x\x95\x85\xeeE\xc3G.\x1c\xae9\x97\xf2H\xa4r@\x1c\x8e8`\u007fQD:\xdbb\xf5\x8a\xd7\x14\x010~\x05\xa28*\x86j\xdcW\x01$\xc4\xf6hK\x0f+\x01\xa0s\xd0i.\x15!\xe7\x06n\x0ei\xac\x96\xe5\xf6oS`za\xb0B\x12\x05\xbc\x16XQ\xc0\x8fF\x8c\\\xfat$ۂ\xf8\x06v\xabP\x15\xc08h\x06\xf2\x0e\x82\xa8Rf,\xc3\xe7)\x16\xa0\xa2-\xf8\x98\xb82\x1f\xc75 \n\xc9\x03@\x9f!\x8fI\xe5\xcbw|?-\xb7\xc2e\x81\x0f\x82n\x138(\x06ε\xdc\xddEn\x06\x01\xb3\xba\x90\x1c\xe1iN\x1f\xda%jr\u0605\x18ׄ\t\xb0\xa7A[}o\xf5\xfb\xeeD\xcaG*\xb9:F\xceM\xc3`3\xa9}G\xba\x11\x18\xe1\x93M{+.\xe2\xdc{\xbbޮ\x8b\xb7\xb4\x95\x05\x89\xea#M\\,\xeb\xaa\xc6&i\x05\x84~\xa6zk7,ź\xbd\x88-\xd1\xccQͰDk\xc8w'\xfc\xe3\xa2W\b\xa1\x8ex{q7\xf6\xe4\u007fv\xb1\x19:`\xfb\x83q\x9f\xbc\x1f\x9a\x14b\x8b\x82\xa5\xf2PT/r\x95\xe8RLؙ$\xf3\xbb\xc5\xceS\x81X\x89\x01\n\x99\xb6u~\xb6k\xb7F\xd1A\x90\x9e\xc2\r\xc5\x16\xab\x01W\xd8SQ$\xb15\\\xab\xf7U\x1dy\xda[E\x13hC\xa5\xb8\va\xe4\x1b(\xf2\xb2\x0f \xb7\xb4\xcd<{Q>\xa4̚\xf4\xf3,<\x8ebPT\x84\xf2\x9b\xb4\xd8\x03\xe4\x1b\x02\x02!H\x13\xe4%\x04@\xe8\x10\x0e\x89A\x04\xaf\x14\x04\x11@\x15h\x02\xf07\x10s\x98\u007f\x8b\u007f샗C\xb8{ \xe3\xf0\xd58v\xf8\xe9\xf3j\x01\xfc\x80+!\x93\x03\x80\xa5\xff\xa4\xfeܐ)k\xf7)\nl\b\xf6׃ڇ짅l\x04;\x00\x0e&\a';)\xe8\x10\x9aH\x12h\xe5-\"J\x16\xb7y\x11jh݇\x0f$E\v\xdb#\xc2\xf2\x06\x18x\xc3hQ(dž\xd0ţn5\x89\x9a=\xf2$OO\xe5\x14\xf7\xf7\xdf\x1dJ\x84sP\x9f\x88\xc0\xc3\xfc\x80\xe0\xfd4\x9e\xb8\xbd\xe55\x88\xa6\xa5oA +\xb7\xe6LkW:a\x04x7\x93\xd2\x18\xa5\x19\xd7:\xc7b\xb7e\xb7%\x88\x8e\xbb\xc8z\xd22ڹ\x90\x04\xa9\xe9\xa5y䄫@\x1fF\x85ΐ\xfaش\x8eʲ\xfd_xԒp\xe6\xc6u\x1d\nr6o\xd3D\x16=\x92\x99Og\xc4\xffӠ\xbd\xc2\x12\ak\t\xe7\xab\xf3H\xe6O\x15\xa8|I\x8cB\xa2\x03r\x03\xa5\xfb\x9e\x94\x93I.\xbb\xfe?$\x90\xd0\xd5\xe1\x1c\xf0A&M|l.b\x05A\x80\x9dD\x18\xa5&\xc5i\x88\xce\x16\u0600\x88\x87\xea\x03\b\xc2\xc0\xab\x9dJ\xc3l\xd1\at@\xc4MX\\\x90\x04Q\na\x9eOA\xe7B@RT\x13\x8f[\xe5\xa2\x136\xde\f\xa2M\xa5\x82B\x02\x0ey\x13[\xc4B\xe8\xdb]\x9fc\xbc\x88\x86\xbf=Y»\xc9p\x1e$\xb0\xbe\x8b\x17\x12\xc1\a\x191\b\x88\xb8\x9b\xa1#&\xc7\xef\x81\x19Wn[\xa1\xf3\xcd-\x99\x01Ŕq@\xdb\x05h:\x18\xf1\n\xbf0\x12\bBl#\xf0~{i\xf8*[W\xe0\xd8\x10\x00\x00i\x0f\xc9c\xc0\xe0\xec\x98a\xf9 ~F#\x93Ic\xc0\xd9\b\x865!\x16\xa2\a\v\xc7\x00px=\r\x8fCe\n\xa4\xc34Ê\xa1\xb8\x1c-\x1d\x96\x87C\xb2\xb3㓁h\xe0͋3\x80\x8d\x02ƭ\x89\xd0\xc3l5XH\xf2\xa2j0\xd5W\xa7\xd0QxR\xad\x86\xe3&HAO\tq\xa1\xfcG٪\x9a\xc3\xc8\xd5 \xc1\xf3x3\r\x89*p8\x9b\x0eGLR\xa8\x17\xca\xe7\xc4J+\x11\xd9Je\xf3]fT\x1a3\xb3iZ\x95SE\xd2\xf7.\x92Li\x9e\xbb4Ҁ\xe4\xc3.HD\xe9\xdck\xa2\x8d\x11\x80\xd2nz\xc1\x8d%,\xae\xfd\x84\xb9\x1f\xec_`v\x15\xfe\xc2\xe0\xe2r\x01>\xb9k\x87\xdc\x00\x16\xf0\"\"\xb2m\x9bMgB\xbf\xb1jd\x17\x13\xaa)d*\x9e\xa2\x97\b4Jf#\xd6\xe3\x0fm0\x83`\x984\x05\x87\x83:\xee\x95R\xdb)\xe1UD\f\x03\xb6\xc4\x11k\"\x9c+;\x0f\xba~\xbb4C\x84\xbdHf\xf8\\\xa8*\x9dT8\x93\xef\xb8\xf0\x80\xf6r\x02\xca\xf8\xf5(`\x03Mjv\xa2\xc91\\\\5\xbcTL\xa5\xec\xba%,j2[>v\x96sW\xa2\x90#\xfb\x1bw\x94+}\xc6\xd5J\x19\xc1\xf1\xf2\xe8i\xa9\xa6\x14\\\x8e\xc6y\xe0\x16/\xe7I\x00ir\xbb\xb7\x81o%\x8c\x9b-.\x1e~\x1b\xf4G\x8e*\xca9\"R\xba\xe6\xb9\xfa\xc1ǜS\xb5\x05=֍\xadG\xe0\xa2\xc2\xe3R\xd9\xc1\x81B\x1e'\x88Y\x1d\xef#\x88\x1aP\xb7\xfa\xfb\x1d\x86\xaa\xf8\af\xc9*\x86\xab\xe7\x99\xcf\xe2\x94լ\x9f\b\xc5E@\x01\xaa\xdc\xc3Z\x1b\x9c\xed8\xcd\xc1b\\\xe7\x1a\xa9,QIa\x1f\xb9\xff\b灟\x83\x1a\xa7\tA\x05c\x8f\xd3\x14\x90=\x92\xdef?\xdc\xecw\xb7\x8b\xf6\xd4\a<\xc3\x19\x94\xcd\x0e\u07b9\xbcE\xdf\"\x8cH\xe2\x1dW\xc9c\x80=\xbdđ\xc2%\xe2\x15}\xf5\x17\xd8&\xe2\xfc\x89Z\x92\xbc\v\xfd\x9f\xccI\x89\x8a\v\xf5\xc6\a7d\xe7^:z\x01\x9a\b\n\x83\x1ap\b6\x85\xa95\xee\xf6\x8fR\xee\x1a\xee\x11\xd9\xdc\xf4դ\xb6\xfe\x04q\xd8\xe9\x8e\xe8$\xcf\xd4\x14\xa3i\xa7}\xae#\x10\xf6\v\\\x91\x85\xeb\x8eq\x06\xdcN\x1e\xfb\x97%\x1f\tO41ψ(\x0f]H\x1d\xe8\xe8\xa1$a\x9aA\xe7\x05\xe2k;\x90ĉ\x00\xb0b\x99\x88\xe8\n\xe9\x04\b\xbb9\xa9\xb8DQd\x95#\x15\xe2\xf8\x92mҐ\x92ɛ\x9d,\xc2\x04\x8dI@\xa9ĻG\x12\x16\xd2)X}\x87\x1dJ>y\x06\x03\xfb\x9b\xfa\x934\"\r\x93\xca=\x12\xda\x16\x11j\x04\xf7\x19\x81\x1c}\tNNv\xd5D\x9c\x8aJeR\x98\a\x17\xe6\x14\xccgs\x1a\xa3pPWw+\x1cŎ*\x055\xb6\xa9\x85\x18\x96\xe3U\xb3\xff:\xf2,O\x84Z\xda\x004*\rjh\x10i1U\xd1&sc\xa3\x97E\xdc\t\xfc\xad\x8c)1\x95\xea[^\xd85by2\xa5\xa0(\xe4˭Y\xd0\xfa\x9e\xf5\x02\x86\x8c\xce\xc9S\xbd\x8f\xd2\ue324jU\xd3\xd3\xd2̞\xf5ij~\x83\x9a\xa1e9\x14\xd5\xee\xad9\xda\x14\xa9.@*\xdf\xc6\\ܦ\x91r\x86\x94\xa55\xed\xf8?\xa1\xfc\x93l\xf9H\xf2e\x1a\x1f\xa3\xc1g\xe9YZ\xbb\x0f\xb0\xe7-\xcd\x00\xaft\xea@r\xccL\x18/qn\xc8\xe0\xfc\xde(B\xc7q\x87\xe1I\xac\x05\x89)-\x14\xb1;\bi?Q\x17E\x89B\xa7y\xf0\x01Ys\x85\xec7y3\x02\xd8\x14\xb9V\x00\xccz\\\xf2˂ܰ'\x02\x1b'\xf2Q4O\xc6\xe2\x90\xd6\xe4\xcc)\xb7\xa7A\xad\xaf\xdeNI>\xb1\x03\xf1\xa0\xe5\x05\x9eX\x13\xd7\xeb6\x11\xdb6\aѰ:\x83\xc0\x1b\xb8\x80\xbd:3\xbb\xc8\xcaJ\xc1A\xf1I\x1d\x02y\x96;˨*y\x9d\xeex\xd3}\xa9\xf7m\x95\f\xc0É f´\xd97\xce{\xb3E٬4\xc3\\k\t\u007f\x98iI\x91\xb4\x05\x02̌\x11\x82\x81\x8e\xb0\x97\x89C\xf0v\x1a\xdc\xf6FD\x90Ġ\xf0\x96+\x19\xe8\xc2\x0e\x85\x82\xd2\x1c\x84\x8f\xb7GƵ\x16\n\xc4\xe3\x86\x1dG^\x144=\xa0Dp\x85\bM\"\xe9_`\xe9?\xac\f\x18\xd9\x17\x0e\xc8bTA\vd\xaa\x05MU%\xce\xf6\x84\xef\x028\xff\xe5E\xa2\xe6B\vI\x80b%eO\xdafY\x06``\x8f\x0e+\xeeAK\v3\xa7+\xe8Y\xda4\x80\xa1B N\xf2l\x9d\xe3h_\xa3'm\xa4@X87\x14M\xcfBk\xc4\x0f̬\xd3*1\xf5Pp|\ue256T\xa7Z\x82ʆ$\xd5J\x81\x94\x00\t\xce\x13j\x9f\xe5nۉ\x11\r\x90\x008\x9a\xc9_\xc1(\xdeC\xe4\xdb\\&\xed%\x1ci\x99\x01\xe8\xdf\xee\xc6\x0eH\xef\x1bH+y\xe4\x0eX\x93\x11\xebu@ѣ\x99ͪ\xe8\t\x13X\xf2\xb4D\xee\xbcr\xfd|1\x03\xe2Xi\xd6\b\xd1/\xf2\xbd=\xfe\r\x19X2c\xcfi\xe9\xcc{\xb6A\x80\xcc\xe7p4\xebC9`բ\x89F\xb2O\xad\xc7A}\xf5\xe5\xe4\u007f\xedI>\xa2'E^m\x95\xa1}K$\xacK\xbbp\xe0\x85!a\x13\xceo\"\x95\xdfb+t\x18\x1f\x00s#\x83\x9c\xc1=\x84\x9e\x19Z\xaf\x02\x00\xacR]\x13*ْ7߁t\xff<\xfdwR\x84\x1f\xe7'ux\x02\\\x86=\x98m8\xe0\x96\xafS6\x02\x96\x93\x12\xb1\x01H\x98\xdeÐ\x9b\x89\x91L+&\x8agO}\x11\x98\xb7s\r\xcf/\xa9\x03\xa8\x18\x15%\xd7.l4v\xb8\xcd\xd9`zY\xdb\x02\"E\x82)\xf8\xc8ق\xa0f\x10ע\xdd\x05\x97\xb4\x84\xd2e\xad\b\x0e\xb7P\xc4\x13ΤgYP\xc4\xef\\\x81\x85L7\x9a\x19\xe4\xb4=\x83\\fVZ\x12\xdfn6\x020\x97B\x16p\x9d\xcd$\x84\xcf\v\x8a\xf9\xd0\xfc\x8e.\xa0\x95\xac\xb9\x80z/5 \x02H\x97r\x81D\xef`\x0eR\xfdI`D\xf9\x02\x01\xc7\xd5n\x946\xb6\xb8Ӻ\xca\xc0\x18\xc5Ҽ\x015\xf9\xaa\x89%!\xb3=(+'Kc\xb7\x94U\xb00\xd6\xc0\xf2hX\x1bB\xb8*)\x88#\x83\x82\x05\x1d\xd0|\x86\u007f!\xf2\x05\xb6\xd6pU\xd2\xf1\xfb\x14\x8e\x13\xd9\x13b\x81\xf8(e\xf4\x9e\xfa\x8e\x96\r\x9a\b˝\x19\x8e\xa3<#l\xba\t\x16\xa0\x1e\xf2b\xe0\x04钎\xee\x1b\na\xe4@@\xd0j\xcb(Q\xe1\f}\rDtE\x05R\x8c\xcdBԵmk\xe3q\xbfK\xf3\\\x80+#{\x94Z\xab\x1b\xc9\x1bE &\xdc\xc4\xfc)\xb8\x9a(\x85 Gf\xd5\xd2\x18\x90z\x1c\xcd\x01+\xe2\xa8LI\xcfC\x00/\x94\xb8\x8d\x18ӂ\x9b!\x99\x8115\xc8\xde\xf5\xa6\xb4K\u007f7\xfb\xc5,P\\m\x86\x01\x85\x87w\x81\xb0\x8a u\x9dJ\x96\xfe\xbb\x01-\xb2\xbbU\x17\xfe!\xc4֎u\x18\x9d\xccb\xf8l\x8f\x13\xa6\x91\xd8z\x85\r\x9b\x81 \xcfE?\xeb\xe6Bݥɥ+\x96\t\x9fy\xe0\xcar 1\x19\x86\x8bYS\x98\xd4>\xb9\xe4\xad\x19e\xbe\xf4\xe7\xd4\xcdO\x18\xca/\xaa¢F\x1a\xf05n\x81\xa3\xd6\xc1\t\x90\x83v\xa62\xa0\t0\a\x1c\xed\xa1~\x02\v\xbfDz\v\xf0%u\x03\bD\x9a\xe8\xd48\xab\x93\x05\xa2L\xdc7\xee#[\xd4@\xfdWOY\xcc\xda\xc7\xc18I\xddR \x91\xc1\x95W\xf2\\-\f\xe2\x9d\x19\xb1\xa7f\xc2\"F\x84`\xa91\xf9r\x9e\xcf\xdct[\x84f`\xa0|\x15/U\x9b\xf3&\xa8o6;\xf8a\xcf\x13n\xef\xc4ē\xb1\xf5\x1e\xa2b\xb0\xb6\x81\xcc[\xe9\x9a.\x03\xa9\xb7\"\x10\x82A\x9f\xffp\xe0\xa0\xe89K\xd5\x14\x977\a\xf0\xb3\t\x17d\x04,\xd8ٜnd\xd5P=\x18f,\x87\x18N\xb5Ą\t\xce^\xd6B7/\x15\xa3\x11\f\xfe\x862Hfm\xec\xf8y&.\xff\xd9s#\xb6\xe7E\nAN\xa86\xc534\x1f\x80\x0f\xf6Ĥ\xfb1+\xb4/\x80\xc8DG\xe3z\x90ޅF\x87'\x04\xf9\x02\xe8fՁ\xe9F\x13\x84\xeaט\xe8ԑ\xa1\xa6\xd5\xe13O&[\b\x01\x97\a\xdf\x1f\x0f\x13\f\xb9:\x02 \x01\xe6a\t\xfd\xccԓ\x9a.v\x04\xf2\xceG\xd8\xed\f\xa4tf7\x03\x05D\x8d\xbc1\xaaw\x91\x8b\x8ex\xa9µ\xa2\xa0\x0eQ\xa8\x1aA\xb2\"y\r$[\r@\xc2$\b\r*l\xdd\x11BR\xc8\xfdxG)ih\r @\xbaA\x94\x88L\roS¥\xf2\xd8\u007f\x96\xccM\xe5\xb2\xe0g(\x86=\xeb\x902\xa3&\xa6\x05\xcc\xda\xd8.\x90\x18\x9b\xe8|iXt \x91\x16\x12:\x866d`\x8f\xaa\"\xaa\x0e\xa2\x8d\a\xe9\x15+?\xee\x02\xd6(m\x96\xe0\x17>\x98n#\xb5\\\xf1g\xb5\xe7m\x96\xdd\xc0\x1a1\x8co\x01\xda^\xbcև#\xa9dTZ\xd9\x03\xa0\x00\x9fI_\x1evC\xa8(\x84\x8cR\x00Ҭ\xb5\xf2\xf4\x80\u007f(\x15\x18\xd6\x16[\xbe\x88W\xe0쾳\xb38\x98r~f\"\x10\xfb\"$m\xde\r8\x94\xda|D\x9bh*\b\x02\x12\v\x87\xab,\b\x1ad|\x04\x18\x81\x06 l\xad$n\xb9\xea\x10\xc1\xbd\x89<\xfbd\x85#\xac\xa8\x85\xc8\xe89\x197h\xc8\xe6Ku1\xa2\xc1G\xb5Ĕzخ\x14\xc1\x1cVq\xc0\x9f\xd7\fB%(Mi\xc5T\x17\x82睁\xd9njD\xa2\xc51\x94\x96\xc1d\xc4\xcbbJF\xa1\xcb n\xcc\x05\xfd\xad\xd0\xfbmDC)\x9cl\x8c\xb0\x1f\xcaд\x80\t\\p\xb32\a\xce\xf5چ\x0e\xa5li\xd1h\x95\xa8\b3\xa8\xeer\x06\xd3\x03\x95e\xc2YLH΄\xe3Y\xf6b,\xd1w\r\x1d!|r\x97\x14\xdd\xc5\xe9Z%\x1c\xffu\x836\xd0\xd4$71+)\x80\n\xe9\xc2I\u007f\xe0o\x9bq\xd6##@\x8aA\x1d\x8a\xbc\x8cH;\xf2.8\x92\xfe\x15HF\xebAJ]j\xa3\xe63S\x13\x10,rl\r\f\x1c\x83\xf65qjgS\x91e\x01@@<\xa4y\x84\x81\x02\x04\xc7Dv\xd9\xc7\xc0|\xde)\xb7)\x90\xbeq`\xaa\x93\x97$\x92\xf4-,|\xb63H\xbd\x1au\x9b\xf7\x11iCr4\xef,\xcb_$\xcbpe\xbbޯ\xb7\x1a\xc2\"6Ι\x94\x80\xb1\"\x86\n?\xb0O\x17\x05\x18\x94/l\x85t\v\x15/$\xc5\x1c\x8d&0\xd9:\xad\x86G\xe0*\fb\xb0h\r[\xfbd\xe1xL\r\xf4\xb7٪\xe0\x86\tީ\xc7l\x92k&\u007f\x11\xa8@\x91\x92\xdd\xda\xe2\xf4\a~\xa7\x1a'\x1dr\x00\x81\xb1\x05\x86\x1f3K|\x89m2\xeb\x03\xc3VI\\\x0f\x02\xcc`\xf8R\x9c%X\x8eS|_\a\xe0*2I\x12\xab\xac$\x02\xa2\x81\xf8\xb1\x1e\x91\n1D\x94P\xa8j\xe0\x8c*k\xc5\x19\xe1{;:\v\x86\xb7K\xd1\f\tG\x97χV\xbe\x15E3\xc7\xc2:\xba{\x00\x95ҳ\xb8:\t&N\xbe6\b\bH^m;\xf8\xccE\xce\xeeFv\xaf\xf3\x06\xefY\xee\xd6\xd45N\xbcC\xe8~\xd7]Z&IhkpI\xcc\xd6\xc3\x0f{%\x0fj\xc5\xca\x03\x88\xa9#J\bOV$\xe6\xe4\xb5+*&!k\x91bN\xe3>\xe1\xe6\u007f[\x82\xa4t^\xaa\xe5\xd1\r<}\xach\xbb0\x97\xb2\xf5i'r\xd2Ť\xa8\x14\xe3_A2L\xd8ҽr\x10!\xfc\x0e\xa4n{5;1\x92(=j\xb71.rE\xc1\\\x1a%\x12\x82J\xd0B\xd9\xe3\x86x\x02;D\uede0TG\xfc\xb41]\xd7\xe0O\x0f\x02\xfd\xcf`a\xc1\xaf^\xaa3!+\xee \xcb<\xe76\x0e\x0f\xb9Z`\xaf&|\xc1<3\v\x01\xde\xc0L,\x11\x11\xf7\xe9\x9b\xd6\xf7\x18?\x0f\xa1Z\xba \x97d\x16\x86ʤZ[g\x89a\xb9\x06\x03\xe4\xe5N!tx\x82h\x81\x1aŠl~\xa9\fv&\xc4\a<&\xf5\xd0\xe9\x17\x93$\xea\xd1@\xec\xf9!\xcb\x1eهj\xc4GL\xc6\x1e\x18\u007fsJ M$\x810"), + } + file9 := &embedded.EmbeddedFile{ + Filename: "af7ae505a9eed503f8b8e6982036873e.woff2", + FileModTime: time.Unix(1576651902, 0), + + Content: string("wOF2\x00\x01\x00\x00\x00\x01-h\x00\r\x00\x00\x00\x02\x86\x98\x00\x01-\x0e\x00\x04\x01\xcb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?FFTM\x1c\x1a \x06`\x00\x85r\x11\b\n\x89\x99(\x87\xb6X\x016\x02$\x03\x95p\v\x96\x10\x00\x04 \x05\x89\x06\a\xb4u[R\trGa\xf7\x91\x84*\xba\r\x81'\xed=\xeb:\xb5\x1a&\xd3\xcd=r\xb7*\n\x02\x19\xe5\x1a\xf1\xf6]\x04t\a\xdcE\xaan\xa3\xb2\xff\xff\xff\xff\xe4\xa41F\xdb\x0e\xdc@\xe0\xd5\xf4\xfb|\xad\x8a\x14\bf\x93m\x92`\x9b$ؑ\xa1@d[BQ\x11$([U<+(\xad\xb8@P\xd05\x1e\xe4`\x81\xb0\x0e\xda>\xf6P\x10\x1a;\xe1(\x91\xd11\xb3\xfdl\xdb\xfehԨ\xa2\xc2)\x9f\xdcYy\x94\xf2Ji\xe9\xeb\x17\xad\x85\xce|%ہ\xb7^\xac\x14G\x82\xa23\xb8\x12n\x9e\x95\xe8\xbaڕ\xdc\n\xc4͐D\x8a\x9ep\\Yr \x94L\xdfP\xf4\x0e\x8d\x1b\x83t\xa5)\xcb\x11\x98\xef\x13\xa76R\xc2^\"S\vL~\xf1YR\xd7CXR\x15\t\x8a4\x81\x8e\xe6F\xfay\\[\xbf\xe87n\xa1\xe2\xae|\x1ds໌q\x1e\xa3M\xbb\x8e%K\xc9\xff\x17.ۺ\x0e,\v\xfa\x84\xf7\xf8L\xd0t\xff'\xf6\x10\x90\xc9M\x1d,\x11\x15c\xf7\x88+b\xfa\xc4ׇ\xe7O\xfds\xf9^\xd8$\x85\x86\xd7z.\a\xf5mŠ\f\xfch&gb\xde\xf0\xe1v\xed\x87\xf3\x01\x0e\xc9'\x8a\x0f6\xa3:\xb0\xbb\xc3\xf3s\xebm\xa3b\x8c1بm0\"ǂ\x1a\xb0\xbf*V\x8c\xa8\x8d\x1e\xa3c\xa3$,0ATPT\xb41\x12\x03\xfb\xf4\xac<\v\xed;\xed\xf3\xd2`\x10\xe6\xb6'\xf1H\x0e?\xf1sΩ:\x91\x0fND\x9f\xa8\xfc\xa9\x10I\x11\xa4$\x8c\x04T\x14\x8b[\x81\x82b4\x8a\x11\xcd\xfc\u007f\xea\xec\xef,\xafμ\xd7」bl6\x91\xba\vIL\xe9i}ی&\xe04\xe3\x94m,'\xcb\x16\xcb\xf3#\xbdץ\xb3\u007fRw\x01\xa2bu\xc0\xb6,K\x96\v\xc6\x06\x9b\xe2v\x8b\x03\xdb\bm_-\xc0\xc0\xe6\\H\x8b\x9d\xfb\x8eHH\xfe\xaa\xf3\x93\xea\a\xc6\xc2?\x98\x96\xd3m\xf3\v9P\x88\xad\xd8)9\xe7J\xa8\x86$ƽ\x88\x9c\xe7\xb1\xf48\xf8\xe8\xc7\xda\xce\xce~\xb9;\xc4r\x15\x8dn\xbf=$\x11\x1a\xb5\x1f\x94Nddn\x1b!'\xae\xa6\xf0\xe3;\xb3\xf4\xac8\x99\xbc'\xd9N\xa6\xed\x1e!\u007f-\x18\x06J\x19ʶ\xd3.\xe0\xd8\xfa\x91\xeeX\xaf=\f,\x12\x04\x0e\x90\x9b\x1e\"`:\x18\xa2\xff\x1b\x0f\t\t {\x8d\xef\x9e\xdc\xe0\xbc\x12\xcbK!'\x9f\x00\xa1-FH\x94\x9c\t\x89#$~\x9bZ_\x84\xb9\x9d\x10\x12\xb5\x03N5VU8Fȯ\x1c\xa2\x8e%\x14P\xd4\xfbݫ\xda\xdb\xfb\x06\b\f\x86Cp\b\x02$\x04Q\x19\xa2\xb4\xbb\xda\x10\x9dr\xac\xec\xa2ʽ\x9b\xee\xbak\xbbk\xda\x1b\xa73ٷ\x13\xd1:R\x11%\x1e\x10\xb6\x812{\xf4\x87ީ\xf5\x92\x1dh%\xbb)8\xc9\x11\xf6\x00\xf8\xf1\x01\x0f\x18\nILK\x906v\xf4#\xed\xfb\xb3\xee\xfe\x06,;Ц6\x87\xa0N\x9a2\xcehv\xb7\x0f\x0e\b\xfe\xef\u007f\xcd\xfe\xeb\fOO\x91\xa7t#\x16\x85\x06\xe2xT\x89\xef\xaaBf\x02\x9d\x9e\x84q^\x16#\x9c\xae\x9f\x96?{\xfe5b\x8aI\xe2\xe0%-WZ\x90\xeb\xb9b\xa4A\xa3\x13\f^\xe41\xcd\xd9n5\x19\xf9\xae\xe9\x8aצNQ\x9dY'\xfa\xe6\xdd\xcd\x12\x96\x04\xfc\x91S\x04\xdc\x18\x1f\xa6!t\" \x06`b3\xe9\xf7%\x93\a\xf4\xef35\xbb\x02\x14\xd1fv;\xab\x9d\xd5\xcelά\xee9\x9c:jgf?gr\x9b\xf5p\xffx\x9f \x80\x0f|\x12\xfc $\b e\x12\x94\x1c\x12\x94Z\x14(\xc5\x14$w(ZrS\x90\xe8v+\x9bZ\xd9\x1c\xcf\xd6q\xf6M\xa2\xec\x1e\x9b\xee\xcd\xeaݙm?&s[\xf6\xe5t\x99S\x92Sj\x8e\xa79\x9c\xaf\xe3\xf7?\xad|\xda\xea\r\xf1\xf0\xc5>G\x0e\xcc\x06,\x10bDշ^\xa9\xf4\xaa^\xa9\xc7\xdd\x1b:l\x8a3\x8e\xbdNA\x9a`\xab5\v\x9c26\xb3\x01L\xf9pS\xf2\tAߧ/U\xeb\n\xc2֘\xb4\xbc\xb3\xb4'9\\\xb4\xa7Նt\xb8\x85\x10\xaf!\xdf\xf6\xf6\xfa\xb7\x1a\xfd\x1b\x81l\x00\x06\x85 PMR\xb4\x9a\x909n\x80\n\xcd`\x15\x12\x13(\xca\x10@\xd2 Hy)M\xd2dM\xca\r\x90\x1c5\xe9Ԥ\x13H'ґ\x9a\x1c\xf2mS<\xfa\xe8\xdbq&k\xbc)\\\xcf{;\xee1\xc5\xc3m\xf9\a\x9b8\xdb{\xe1\x8b\xd5X\x841\xdd-3ǚ\x90\x91)\x82B(\x84\x91,\xfb%\xf5\x93\x10\xb0\xb6\xb6\x8d\x04\xc4\v\x05\x05\xdd\xfd\xdbw\x9fo~\xbe\x98t\xed\xf0HW8l\x90\xd4Z\x11\tr\xa4\xe3\xbf\xff=e\xb3\x1a\xec\xdf1+\xe6\a\x05/Ɏ1W?ְr\xee\x12\x0e89PL\xc6\xd2\x01>uo9 \xc5\x181 tØ\xab\xc3uc\xa7\x9d\x91\xee\xc4@\xb3\xf9]K\x14\x10R\xef\u007fbN\xff\xbb\x92v\xfb\x93\xb4\xd4\x1a\xaa\xa8(\xb8\"\x8a\x83y뽻{\x1c\fc\xae\xff\x8f\xe6\xf3scz\xa6\x19&\xaep5\xa7\xe5\x04\xa1,j\xb3n \xa2kN\xc4!\x83.\x83n^\xf7\xf8Uu\x1f\x00@|\xfc\x18?v\xb5>\xf7\a\xb9\x1d\xb9\xdc\x1c\x91r\x18Ua\xdcHR \v\x1a\x8f\x10\xfa\xb9\xd7\xf8Ց\x00\x93\xf3I\rD\x89\xdfˋQ\xbf\xbd~p\xe9\n\x80܍;;\xb8n\xf9\xf9\x8dL\x18\x17$\xa1t\xf9\t:\thFCY\xa1\xed\xdeTO\xa0FN\x1dN~}\x17\xf11\"`\xb3\xa8\xfc\x9f\xd8a\xcf\a\xcb(\xcd?H \x11\x97\x96\x87\x1f\xc4\\\x96\xcd\xe5u\xca0\x13LԵ\xf5\xf1'\xb5\xed\xba\xbd\xbe͔PbnmO\xbf\x98\xeb\xb6\xdd\xfd\x8d\xbf\x02\x18Jl\x8b?\x02\x01\b\x9e\xe5s\xab\xe7\x05\x880,\x0e8\x8cx\xc9B\xf2\xfa\xf6\xbeB\x19\xc7\xe5\x91F\x89\x10\x14\x9f_\xdf\x1bRiZ\x1d\xf8\xff\xb7\xd4~e#\x15j\xb0\x11\xb1w\xfdhOc*&F6\f\xacYq\xc1\x92\x05{\x89}?\xc9\xf3>\xf7u\x1e\xfb\xb6.\xf34\x0e\xceh%\x05g\x94`\x04\xa7&\xd7\xe7 \xb8\xcb\x12)\xa9\xacR5\x18\xe5H\x8c}\xb1\xa7\xffˤ\xb0kܩ\xdb\x1c\x90'J\x99\xdeO\xbf\x00I\x88\xdb\x13\xb6\x9d_\xef\xb3\u007f\x05\x91qOb'\xd6Hǟ\x00BYEM\xa3\x03\x1c6\xc8v\x84\x815\xaa\x10NJ\r\xe5\x15\x01O\x88N\a\x1aF\vNx(1\x92:\x01\\\xba߫C\xe0k\x8ec\xa0b8\x05Q\xf4\t\x13d\xe1\x18[L\x14(el\x1c+2u-\xee\xd0a֘d\xa2\x8e5;\xa2N$\xd4\xf6\"\xa2H\xaa\x8f\x10\xabSF\xbao\xeb2i\xa8\"\x8a\xd9\\\xb3h\x047I\x8c\xf6\xa0\x10fN8\x80q\x97\x8cx\xea#v\n\xa56um\xef\t\xe0\x19\x9d\xb0`\xdbNM-J\x00\\\xf4\x10F\xb7\xc7r\xe9D\x02\x80\x1e\xb5Z\xd30\x93\a#'ꥈn\xec\x11\xd2GjL\x82چX\x14\x1bʌ\xa2A\xaa\x9d\xf1gYs\x99*\xb2Y\xca\xdc\a\xc7^ٵ\x98;\"\xd8\x1d$hb\u007f=\xb9\x16\x19ϛ\x13\x980\xdevH<\x97Vv\u007f\x81c\x9b_\x00\\Y\x8a\x03\xec\xa3\xe8w;dB\x16\x02\x83\x8b\x03N\x83\x843\x1b!$\xce\xe7\xe7\xb4\xe7\xe2\xdeI|P\x98 ~\x13&\x13\xe4\x03d\xc5.\xc8\x03\x1b\u0530\xe9\x02-a\a\xf3\xfaa\x19\t++\xc2\x13\x929\xba.mR\xf8\xe94\xe3cy\xaf\x9e\xb9#\x8bU\xd5\xc2FW\xee\bu\xbd\r\xdc\t\x17i/\U0001cbd4f~\x804\xdd\xf0l\x83\xeb\x0eXS\xf49Ä\x1b\xf71E\x9d\xf0\xbd3@\x90\xfd\xdak\x13\x88\xdc\x15@\x17'#\xa3\xbc\xb6c\xac\xbd\xd9n\xea\xa9 \xba\xf1\x15\xefS_;\xac%\xfb\xeeI\x8a\xd0\xc1+\xbb\xf8.\xf3L\x1a\xd8C\x02x\xb1\xeb\xee\x1e\x1e\xbe\xfaꆱw\t\xda\xcdVۂ\x80\x81\xba\xa8\xe1\xa4\xc0\xc3\xf9Exf~H`\xbd\xe90\x1f\xbc!d\x94\xe8@Q{Oh1\x89\x17\x17\xb1H\xc1\xb6Fë\xd5zs\x1a\x8d7\xf3݉\xb6\xb3Ɯt\x0frv\xcc\xe8\xa9\xd2k\x9d\xbb\x86heS3\xb7ۇv\x999\x84q|\xabO\x82\xef\x97K)\x95U\\\xf2\x96A\xd2%\xa3\xb9\xbb\x02\xc4o\x1e{l<\x86\xdbK\xb8\xff\xba\x9d͎\xa2\xa4\x8ei\xb3\x8f\xf1H\xebG\x80I\x85z\x9d=6\x9aWWo0\xeb\xd9\v|\x15\xde%A\xf7\x1ajdD)!\r\x80\xa9pw\xae\xc8\xee_\x82\xb3\xeb;\xb8\xf1\xa6\xdbc\x97D#\xe9\xffˁM\x90\xc0\xdeNz\x9c\xf2\x05\xb7\x04p\xb0^\x8fCDx\xde\xc2xj)\x845O\xc89\xfb\r\xa1`\xd1\xd2EDX\xeex\xf1\x8d ݒGU\xc8\xc0\xed˯\x0eę\xaa\x04\xa9\xef\xd6ډ\x9c.%\r\xb7\xbf\xb6Έ\xb1~\f\xe3\xf1\xfa=\xff\b\x1a\x16C\x13o\xa6)\rF\x847\xf3\xca\xe7$Z\xa4\xfd(\xb7g\xc1\xeboB\xad\xa7\r\xdbƜ\xc0@\xde\xe5&\xf2\xc3\xdae\xee{\x06\xea\xe2厣\xa0\bl\xa0\xb0f\x8a_\xc6Rx\x99N[\xa7]\f\xae\x9b\a8`-3\x99s\xb4\xa6\xc1\x92{\u007fPj\x01\xde\x19\xb8Wuc9\uf178\xae\xa9\x84\x1b[>\x1d\xea-\x9f.D\xa2\u070eY\xfa\x1f\xf7\x9b\x15\x0f\x80\x1ed\x87\f\xcf\xc2\xd8\a\xa2\xb2+\x18^{\x93\xae\xb9C\xee\xf7\x89\xb1m\xe0\xc4\xd9\xf0,\xa6\xb1@N<\xb2\x90\x1d\xda\xd9\xd0\xf8\xf2\x89\xaf\x1f\u007f\x0e.\x8d\x94V\xf1\xe6M\xf0\xda\x11S\xec+\xd3\\D\x9e+\xa2\xdaR\xa2|\xd16\xb5\v\xe2'q\\T\xe0\xdd\x02\xa6\x95\xf3\x1c\x1e9\x87D\x84\x06X<\u007f$\xedp\x89\x80\xde\a\"\xbb酦\x92\xfc$\x9bҷ\v\xde,\xf9p\x1f\xbbs\xf9\xa5T\xd3\xce\x1a\xdd\xfe\xafb\xbb\xff\xd4NkI\x91\x1e_\xe6\xa1`\xd5\xe6\nF\xe8\x88\x1f\xeaW\x93\x9fV\xff\x94%\xd9\xd1w\b\xad~\xa9\xa4\xc4DԐ\xd9\xc2\xcb\xdd*\xf3\xb3xi\xf2\x1e\xb8y[rZ\xaa\x87\x00\x99[S%\xb4G\x9b\xdc\x18s`F<ㅣ\x85\xb3\xac \xa2\xc1V\x8b+\xfe\xf3!+\xad\x96\xf7\xf5\x8a\xb8؍\x8b9y\x9fk\xc5\xc1fb\x9182\xde\x06s\xde}l;[)e$\xc4\xf8\x89T\x9d\x86\x96k\xad\x83\x92\xe0)\x9av\x8f\xb6\xa99\xac\x01\x84\xe3\x1b\xa7{\xd3u\x13\xf2u\x8ft\x8f\xc8\u07b3@E\xe3\xf4>|C\xf6\xda<\\4%\b\x97Rv\xe1\f\xa5\xb6\xe9\xe5\xc4\xe8\xaa\xda\xf4@\u05faC\xcc8\\\x91\xf8~)\x14#k|\xbe\xb9.a\xebo\xaa\xba\xda\x03\xba00G\x94q0\x1d\x14%\xf1\xfc\xf0\x13\xa1\x99hp\x8b\xa9\xba\rL\xff\x9c\xde\"\x8c+>\x8e\xec\xe6\xb5%\xaa\v^Mˊ\x98N\x9as\xd3\xc8\x06q\x8e\xb4=\x95\x12\xb0\x0f\xbe\xee\xe5䦆\xb0K\x114r\xe7-*\xef\xe7%\xe8\xdah#\xd7%;pP馔h\xd6C=\xf7\xce\xfa\xda\xda\r\x97\x1a\xe5&\x14)\xa9ba\x84\xc6KL\xf8@\xbf\xf9\x9e\xe4t\xba!\xa2~2\xedS]rYl\xbaZ6\xd03ўJ\xdeo\xb4\x98O\xa3V\xf5;\xb9h&gO5\x92RT\x88/}\xf9\xc1\xd2\xc6{\xae\xa5\xf2\x17\x17AZ\xd2&\x87\x19S\xf3\xe2\xd9t\xd8\xca\xf9\x9c\xcf\x03\vͯ\x01\xe9\xa2P\xea\xebC\xa1\xa4\x14\xa20\x13\b\xb4\xb6D,\xfbpbpз\xd4z)\xa7 ]\x80I\xf7>\x1a\x00\x0eQ\\Bl\xc1\"\xba\x97^3R>r\xfd*\xfb\xbb\x04C>\xc0\x1e\x1e\x83\xa7\xe1\x17xPU\xbaz\x1e\xad}Y\x11=\x02\x0f\xf5̕\x16\xbc}\xf5ж\xc7\x10\x9a\x19\n\xe7\r\x1c6-`/\"H\v\no\x85&\x92D\x97I0\xffE2Xa\x89\x95-\x1f\xa9{\x0e5\xc0\x81\x99<\r,}\x94\xd1\x13``6\xfa\xc7\xed\x18\x90ji\xa2\xe9\xd8im\x12'\xdcw\xac5\xfc\xdb\xfaRF,ч\x88%\x1eSY\x96\x84\xbb\xc6Wh\xa36L_i샣=\x9a\x9b\xbei1\xf13\xfeYI7N\xb8Cp\x8dI\xc9\xf0Ĕ\xbe\xc3\x12(\x0f\xa8r\xaf\xbe\xbd0\xab\xdd{j\x89\x19\xf7\xba\x85r\x8bK\xbc\x9e\x99\xe5Тo)l\xd9\xc4\xf4\x873na\xbfT1\u007f\\\xa7\xc3I\x19E(\xe9m\xbd\xf7\xb2\xbd߃\x9b\x93\xc2D\xf4l\xfa\xac\u007fe\xb3\xb3\xc7\xe6$Å\xdfwX\x9e\x88\xccU\xac\xfc(@\x95\x84\xae\xf7M\xf5a\"n\xac\x0e,\xe4*vG\xb3\x1d\x96\x1c\x89̨\x13x\xb9\x8a\xae>\x95G\xd9\fS\x82\x11\x83\x80\xee\xbdg\xc0̉\"\x94Q\xcbv\xa4b\x140*z\xdb\xc8PE\xf4y\xc1ɉ\x8c?7\xaf$\x13\v\xc1\x8e\xd8\xf0%\x9e\x1d\x89G\x87\xd2\xd1\xe4p\xc9dY\xc8&f\xe2\a!\xed\xfb\xc7a6\x94\x8e|\xa8\b)\xbf\x0e;u7#\xc23\xc94\x90mJij\xdb\xf8\no\xf7\xf6\x89O\xf8p\xadȁ\xa2v8j\xa0\xea\x99\xfcx(K\xcb/Z\xdcd\xbb\x03\x8a\x8fx\xc9Ń\xfdm7V\xd1_\\\xa7f\xd7L\xe57\fp\x9bX\xf3z\x16\x1e\xec\x85H7\xbe-\xab\x0e\x96\xb5,(1KHb\xade\x90\xa8,r-\x19\x1c\xa3\xa0\x11p\xa1L\xcb\xef\xc6\xed\xa03=\xe6T\x98\x02\xc62\xa9t\x912ټX\x96k:\xa9\xb4\xb5\xff\bZ\x805\xc0\xcfs\x05\x89\x0ep\x0e\x88\xd2SsT\xab\xb8\x05\x1a\xd5\xeb:.]\xb5\xb7D\"\x94@\xb0\xf5-\xb6E\xb7̑\x06!\x10\x94\x13A\x8d\xf0\x912\xbaɶ-\xf0F\x19}\xb1˒\x802Bǃ\x92\x8dQ\x1a\x99\xd5\x17\xe0\x05)t\xc5ç|\xda#4\x84|\xdc\\\xf7㨀\xf0\xc8`\xb7fc\x10,\xb6\x9f#\xd4\ag\x89\xe91:\xd9-\xd6\x16\xab\xa1\xb9ty\x17 \xdb]\xfb\x87\x98\xe0\xe42\xafZ~\x02\xb1\x84\x00.)\xe3\xe9\xae\xf3\xf4\xb3\xd7\x02nj\xe0\xd6\x1e\xb5\xa1\xdc%R\xa5K\x8d\x98\xab\xbf(y\x90\x02`\x918\x96\xb6C\x1a\xd7\xc7֍\xfa\xb7\xcb\xf7z\x93\xba\x1d\x8aK-N\x8e\f\x84\xf3\x01\x0e\xf5`^+\xa6\xf5\x8b\x9en\b\xa2\xa8\x8b3\xb9\xdbϴ\x18\xfe\x02\xe5\xf4\x80\x9d\x16\x95T\x81\xf23\x82tQ\xe1أ\xa9\x06\b4<>:J0È%\xe5ݑZab`\xe8\xbd\x03\xeavͬ\xfc\x86a\xf6T/Z\x01\x02\xfa\x14\x9caޝ\xc7ГIi\t\x9bW1\x90\x16\xfc\xf1\xfd\x83_\xa9\x90\x10>)\xc3\xfa\x97\xbeH\"\x94\x8a\xf9\xe3\xe9p\x92\xeb\v\x83|7m\x14F\xb5^Z\xcf\xcd~f\x8b\x11\x170J\xf1\xea^\x00\xc9I\x91\x17\xdc3V\xb9!\xe9\x18\xa5\xdc{\xd3<\xa5+\xe7O\x9f\x95\xdb\xd8\x1feB#\x95Bc\xd2\x1a\xd9\xc0\x02\xe8jL\\\x11\x12\xa3\xc4-\xbeZh\x95[\xd7\xfaI<\x8d\xaa\xfc\x0f\xf1\x84\x18q\xa8v\xde~\x96k]\x9bG\xc3\xce\xd5TD\xbf?S\xa9\xcb\xd9\xd6/\x1a\xc6-\xd4\xd7%ݒ\x89\x94\xd9\xe87\f\x88\xfew\xa6i|C\x16\xcbI\xa1\xc4q\xf1wc\xa8\x80W\x01\x9b\x14x\f\x9a\xb1 \xcf\f/7\x04\x81x\xac\x82HO/\xae\xe5\xb5\x1d\xf0o]\x91\x9e\x0f\x94G]\x8ay\x8f߃\xeb\xfc\x87\xfb#\x85\x87\x1f7\xa9\x8fb\xcd\xe3$\x93t\xc7\x1c\xaaR\xdb$ \x06\xbe\x98\xe9\u007f]\xe3\xb4a7\x1b\xcdF\xa3Ѯ\xaf\xb2\x8f,n!r\xcb\xdfI|2\xc0\x10\xbc\xe3\xb88\xea\x92x\xff6\xe7\x99gS\xa6h\xb1\t\xb2\x93R^^\x93D.\xf8x\x8aM\xd1MS?漞'G\xfa#\xfc~\xe1+\x9d\xac\xba\xc4\xec\bv4\x8ad!FyT\xdc9\xf1-\xb2fVa7h\xfbB\xae\xcb\x174\xfe\xab\x9f\x96\xe8\x17,\xa92\xbcƉ\xc4\xfd\x15&vTHMqp\xf04\x14?\x02R\\\xb4\xbd\xb2\xaa\xbeXa<\x91\xd84\x10\xee\x96\x1c@Mi\xacH\xd4D_\xbe\xe8\t\x9bE\x11g\xaa\xcfR\x89y\xb1M\x9a\xd3\xd1lT\xfeؠJݮ\r\xab\x96y\x0fc\xca\xce\"\x99HJ\xf4, 6\x8au\xf6/ڴ\x9b\xe2\x0e\xad\x9d\x04\xc0\x0f\x8b\x94\xe9\x89y\x8e\x00\x97V\xcb\xd9\xe6nJn۟H\\P\xc5R\xa3Bd|\xd3\x144\xb9_\xe8\x8e$k\xee\x9c\xcb\xc6\xc0\xc6.\xb9\x9aw\x12\xea\x96\xca\x1b\u0099\x14\x01I\xa0pS\xbd\xfd$\xe4\xfc\x1c\x96|}j\xce\xd6\xf49\xc8\xda\xe4\xa4\xe9\x13\xc3\xfe\x11\xa1m\x87|\x831\xd1ߘ\x9e\xb7\xb7\xfcn\xbe93\x839\xbe\x1f\x01\xeb\ueb10\xd45q\x02S\xfa|\x86\x9b\x9fxW\xed9\x13\xda\xdc\xec\xcd\xeaB\xb2\x96VZ!\xba\x99\xb8\xcbm\xa7K/\xfbLn;i\xab\xeeu\xb3\xed$\xe6\x15*\xcet3\x10\xd6Ͷ\x13\x8c\xd7@}\x00\x14\xb0\xa4\xb4B{\xf5Y\xef\xe2\xb8\xe4\x9fԑ\x94\x14z\xab2J\xe7u@\xdfa\xf7\x16\\\x19M\xfb\x89\x87\x0eR7o\xb3\xf3\x18dz\xe8\xa0\x15\xa8\xa0\x9be\xb3\xf27\xde/$4]^\x95\xc1\xbf2k\x8a\x1ch$\x8c\x13=\x1c%\x00\x89\xe51\xeeI\xe7B\xd2\u0603 \x83\xcfH|\b\x02\xf8N.[\xc9M\\\vL\x97\x8c\xfbb\xda\xed\xda\xe91Mg\xe6\xf2\x1a:\x9dNV._0\xb1\x00,\x9e+\x16\xe1,\xb8\xa4h\xddt7\xb4l8\x8ds~IV^\rN\xe5˼M\xf2\xb2\xc3\u007f\xf8ؑj\xe4\xdcك-\xa2\toܮůQ\xe4\xc1o\x10[m\u007f\x88\xa0j\xe9=r\x03\x9c\xfcm>\xf1~z4$M\x9a\xe1\x17\x1b}z \xd5\uf6c0s\x00\x8bh\"\"\x9e\x87\xecu7\xb7V{Rûݦ\x00\xb8O\x11-\x9e\x85D9V\xd6٥g\x86IʎK\xecLg۶B\x10\xffT\x0f\xa8\xf3P\xb5'\x87K\x17\xcf\xca̦\xef\n\x0eqW\x05\x84֒\xf33e\xb6\xb3\xa5\x12\x04\xffp\xe4\x86&\x90\x96\x88ے\x89\xe6L\x8b\x18hp\xb3\xaa\xa7\xd5N\x83aS\xae\xa3\fw\xf9\xa1\n&\x98\xd4\xe2\x85;e(\x87,-\x027v\xcax\xa3-\xbf\xdbw$W\xa9\x17\xcfnX\xf3U\x9f\x9e\x87\x85\xb8\x89\xea\xf7\xc6t8\x89\x9b\x11\xb5\x91\x99\x03Y\xe7\x11\x8a\xba?KM\x9fct\xbbY\u0603\xbep*Շ\x8e\xfa\x89\x05\x8b\xe2-\xed\x84\x1c\xee\xcbБfL\xac|\xc2[nL\x8a\xe7\x9c\r}4\x89{5\xd9\x18頠\xa33\u19cc\x1d\x15\v\x88n\x8a\xb0\x94$$,+\xa3DN\aԄ-H\xedV>\x98\xd7H\xa6\x8e\x98\xda\xf9Os\\\b\xb7\x05\xff\x95-\xd1;\xc0W6\x00N\xf8\x95M\x89\xdd8\xb2\x9dFi\x95\x91\xd4;\xbe\x8d\xa57\x19k\xf32\xb16%\x02֒\xcc\x0f\x1ca],:!\x8dʲڽE,\x1d\x9f\xde{U\x84\xfe\x01\vnaw\xbb\xb1\xf9\x85Ng\xa1\x86.\xad\xf2I\a9r:j\xa0\x84\x15\xff\x92\x8c\x1a\xb0\xabF\xedb\xacK\x85\xc7Ψf)*c\x96\xa6G5<\xf3\xccC\xa0\x98\x00\x9f\x95.g\xf4\x15]\x04\xa8\xeb\xafk\x96\x92\n\x19\xb6\xa5\x81\x17 A0\xe3\xbe-\xbe\xd3٣\x16\xa6\xa9v\u007f\x04\x86T \xb8\x05\x06\x0fd4K(\xa8\x16\xc5Yq`\xb2\xaa\x9b(u\xdd\xe5{,\xbd:0*$|2\xec\x0e\x83\x9a\x8b/\x04I\xba\xcb,\x93`E\xbc\x86\xe8\xd8\x14\xf1xP\x1b\xae\xb3#q\x84\xb0\xaf\xcf\xcc`\x00\x9b\xe0/\xeb:\xea\x80\xc8\xd2\xd3\xd6';\x8dىV\x06\x87\x11D)˴\f\xce\vr\xc9\xfc\xe3\x8f\xf689\xbew\xa2}[\x01\xfa\x86F\xac\x88\xcb\b\xeb\xa2\xf9ޜ\x17η\x0e\x9c\xbe\xa1\x1d+\xe5\xd2\u009ah\x9eKH\xde\\\xe0ǚU\x8a\x8e\x1d\xa8䬂J\xc0V$pUj\x99|c0\xcb\xee\xdc{\xaf\xde\xc7L\xf3\xebA\xab\xda?\xe8V\xe6=\xa74\x8d\xf2\xefS\xba\x19Ŵt`\xf5\xc5\xc6d\x99\xff\x89o\xfc\xd9d\xa5b\x06UP\x06\x94\x17\xcc\x02\xf0J\xa5x\x13\xd1g\xa4\xaeJR\xf8r\x9dO\x85\xb9\xcfs\t\xf3\x1d\xc6\xc1\x91\xa1\xda\x184Mw\x98\xa9\xdc\x1e\r\x0f\xe8\"\"\xf64\x142\xf7\xe1\xe8\xe0`M\xc4\x1a\xf1D\xba/N!\x89\xd5v\x823չ\xb7\xf2\x81\xe1.\x8c\x15f+\x93@xO\x97V\xc8q\xea\x9bj^\xd7Cߪ\xa9Km\xae\xf7\x9f\x11,\xe2\xb18H\x049\x8cZ\xa8\xac<&\xb8o\xb6\x85\x1f(\xd1@\xff\xb0k\xa9\xf1\x1e\xdf\xd6M5\x9b\xf3\x1f\x8d\xa1]\xb1M\x85\xb8U2\f=\x10vpB6DXj`\xa9r\xaa\xf2<\xf5w\x95\xc61\xe6\x99Y\xd0:\xd5 \xe7o\x91<\xbf\x009\xa2;\x8c\x01\x9d\xf8\x8eF\xc0\xd5\xfa\x93$\x1c;2֜\xd7j\xb4\xb1\x10\xfa\u07ba\xecx,\x16\x12\xcb\x1aʁ\x9dC\x04\xc5Rĉt\x18\x16\xb8\xb0\x12$\x83\x1cVJf\x1e\xc1f\x88\xc59\xc7)\x00\xafa\x999P\x89\xab&\xe0\xf8\xd1\xc56Oo\xbe\xd6\x03\x17l\xa9<\x9d\xd4\xf3\xe2\x02\x19\xf2\x19\xefds=#\x013\xc5s\x16\x8f\xb5P-\xd0bD\xa0\xd4\xfc\"\x8d\x0f\xec[:\xb0wɺ^j\xf9\x89Ӂ\xbb\xd0Qej`\x8c\x8b\x97Tq\x92\x05=\xa2\xfa\xb1\x94H&\xa3o\x8f\x1b\xa1\x1bkĉLD\xdeW\xa1O\xfb\x86\xc2\xf9\x94\xeb\xca*J3s[\x19\xce6\x9dj1\xf0@\xd9\xd8nr<\xaeξۇ\x86#\x89\xcd\xd2@\t\x880\xbf\x9bc\x06\t\xa2\x9d\x1f\x05\x99?ﵝ<2\x8aD\xd5Ӧ\t\xbf\xe8}\xaf\xb0Ts\xcd\xd9S\xce\xfd\xd0\"\xe2\vR\xcd\n\xae\x95\xa4.}\xdfoZ\xde\xcd\x18\xe3\x87\xf9Fo*\x98\x95\xa7ݗ\x87\xb6\xff\xb7\x96\xb5:\xdd\xf4\xd6\x1b\xc1\x93\xbc\xc17\xc9\xed\xf7H\xc2\xf2䍚\x0e\xa5x\xa1\xb4]\xc5\xdb\xc7a\x196\x1ev5\xed\x12R\xfd\xa0̾e1\x87\xed$XL\x85\x9b\xba\xc3\nJ\x89aa\x9a\x11\x13݆,\xc6\xf3섐\xcc\x1a\"3-\xcfG\xe4!\x1c˥8\xb3\xb7\xf28\n|\xe0T:S\xdeP\x93\x8c\x02\x1f\xb8\xb6\xf5\xf1p\x1cMR\xaeY\xdeb\xf4\xe6\xa5{\xef+\xbbO\xfdeۛ2\xf6\xf2\xd7g\x05\xa7\xa9\xd3u\xae\xe7\xf7V=\xfaU>-\xc5\x01kb6U\x9f\x12\x92\x92ЩpZ\xe2M\xbd\xd0O\xa8`\xff\xb2\xdc$W\xe8D\xc1y\x1b\x8e\x11\xb9\xf1A\u07fb\xa3[\xc04\x05\x8d\xfca\x91\xfcJ\u007f?\xaefD?=\x97\uf449d\xb0\xaf(KD䴱:\xe2\x9cD\x1e\x93/[\xe5#\xa2\u007f\xf5$A\f\xc5\xfb#KH.\x11:\x95\x9ex?%\xe6\xdbV\xf4r\xb7\x15@\x01[B$\xcc}\x9ec\xf1o\x18\xe1\x93\xdbS6`LPfM&ɔ\x80\x9bA<:\x8a\a\xaev\x90\x9eÚ\nQ\xd2~P\xdf\x1b\x10w\xa1\x92\xef[\xeb\xed+\b\xf7\x9e\x14\xad\x91\x86\x8f\xfb\x01`+j\xa3 V\xdf\xc7+\x8f\x9eR*\xe3\x01\xb6\xb5u\xa3l\u007f!\x14\x0e\xa3\xfe\xea|\xfe+'\xafKY\xfe6\x9b6\xb6\xcd_\x06\xeb\x96ud\xd2}_\x03\x87\xac\xdc[\xffyuۘ\x95j\x8e\xa5\x00\xb0\xbbo$\xc6\xe3Y=\xa0yjR\x9c\x11i)\x8b\x16\x99\x06b\x90ԋLaD(\xbdX\xfdU\xcawI\b\xabڻZ\x80\x16$\xf47\x02ڻ\xee9\x1a\xb9\xfa&\u007f\x99\xd64Z\xc3\xdd\xd6'\x8c\x93DF\x9f\xf5\xdd\x10[N]\xc5~\xe6d\x18D?V\xf0\xf6\x17Q\x95W\xa1\xcdͲ\x81}vS>\xc1N\x0e\x03m\xf7\xc9\xc3+\x03S\xdeq\xf0\xb8\x0eH\xb0\xffa\xff\xfa\xcaU!\xf7Β\xaf\xe6\x86\x1a\x17\x89\xdaWb_+\xa5\xab\x8d\x99\xe8U\xf4\xfeO]\x8a^\x1b\xbf\xec\b\xfcl5\a9\t@\xc5\xe41\xe6'\u007f\xeb\xe0\xd9A\x9f^\xfe\x83m\xec\xaa\x12\xfd\xc9\x11\xb2o\xb1\x12:\x9b\xc19\xb8ף\xa3s\x19\x0e\x9b-\x13\xdd\x00N:\x1a\xbb\x11\x98\x80tD\x01-\xc6zkS\xb7\xeaj\xb5a4\xed\x9frc\xb4\u007fz\x0fF\xfbۻ \u07bf\xe1\x84x\xff\xdav\x88\xf77[\x00\xbcäC8\x96#7\xb6p5\xdf+\xb3\x86\xb3 \x1c\xe2~\x1d*\x85bJJY\xdczֳw+\xfc\xb5\xcd\xd9\x02\xef\x10-\xc8\xeap\x99/L\xccL[cg\xd8\xf7\xd1\xcdn\xf4lc\xb8\x93a\xffP\x89\x86\xd4\xcbH\xabF\xe7\xbf\x02\xbb\xbe\x9b$}\xd29`\u007f\xa3\xa1\xcb\xd6\x18\xb0\x91\\\n\x82\xf4\x0f83\xe6\x12Ym\xf01b>\xbf~ƽJ\xae\xf9\u0602\xafϏ\xc9\xfcyBs=\"\x92\x86\xe8\xcc\xc3f\xed(zK\x89\x05\x1c\xf7M\u007f\xc5\"\x8d\x1a\bH`\xe5\xc6w\b\xb5c\xbdEd\x85\xea:b8\xae6(\x029\xb0\x18\x89<\xef\x10\xc9c\xffl\x8dݘ\x1e/\x85\xbd\x16\xfc\x10k\x9d\x9bg\xea\fG\xa4\xb4\xbd\x8c\x01\x91\xb0\xc9\xda\xe0^\x02ESE)5\xd6G\xeb_^\xbd\x8fk߇\v\xf2v\x89\xbf\xd5̚\xd3\x11}T3\xff;6\xf1\f Wv\x15TCP_\xa0\xf6\xd0k\xf3\xc2\xea\x8c._e\xbc\xe0єNJ\xd3L\x00{T\xc9!\xb3\x8a6\x93j>h\xf8\x9c0\xdd\f\xba#\xe7\x86\xdd\xd9[\xaf\xea㗚\xa9\xc0\x86\xccK\xc3\x01\xb1z\x93,\xfe!\xda\x133\x88\xa6\xd22\x98\xe7\x06\x81\xb6:6d>\x1d\xa5\x05himE\xd6\\\xcc=\xf0H\f\xba\xd4\x1cZ+{6\x9c\xac@W\xcaʯ&\x11lC'\x12\xc2,\x92\x10\x11\xd0rX \x14\x12\a!\x15\x1a8\x9f(\\\xe3̭2\x98-\xc1P8\x0eh\xe8\xef@\x0e\x92\x14C4\v\x9a\x8d<~\xb3\xa1\x06\xd9\xeeZ7j%)\fe\xfe\xb4\xc5\xebeF\xcb\xfcpZ\xea'15\xb1\v\xd3^6\x1aB\x83\xcd\x05\xc83\xb8nc\x99o#\x14~\xba\x88\xc2²q\x98\xafR\xdb@!ա\xf7\xd0 z\xc3^\xddKs]T\xde@\x83TN\xb3T \x85,S*@\x017\xd0\x13\xd9\x17C\xbe\xaf\x89ī\xdbɅ\x98\x0f\xf6\x93\x92L\x0e\x9d\xa8iQ\x86N\x95\x1c,\x84\xc4\t#:\xe5\xceRѪ\xbb\x88\xa5j\xf8\x92\x17\x179\x97\x05\x15\xe21\x80-\x82Y\x99\x97P\xc7N¿\x00\x8a\\&\xb9yL8\xafӹ\xcd\xf7\x89&0\xcbc\x92\xc1v\b\x14\xf0Ɖ\\\x8e\xc0\x8a\xa1\xf2J\xb5A\xca\xcd;\xa4\xf2Q;\x1c\x95]\x85\x89\xfdI\xb4M8\t\xd9s\xaf\x02\xaa\xd8\x14Mf\xf4?\u0530\a\x1c\xa1I\x12\x18\x9a\xb2r\x1b\xbbr!\xd2K\x869я8p\xd9}Q\xbf콍\x8b\xe7g\xfb-\x84*\x0fsm\xb5~\xc5X\x06\xd7P\x1a0d\xf8M^\b\xb5\xf0?D\xc5\x18dI\x82m<\x86\xa8p;\xa1\u007f\x06y\x8e\x06,\"ۦ\xa66\xad\xe4v\xcap\aT\\^\xcan\xf4\xdb\xf7\xbe\u007f\x053m\xa4>8\xa4eC\xae\xf1\xdcN}\x10\xad\xcd\xea\xedcà\xe6٭$s7ۼ\x13\xfa\x9c#յR\xa5{b\xba\xb94\xa6\xf7\xcbvM\x9dq\x84\xb3\x11\x83l)<\x8bV\x94{ě晐\xb12P\x99\x00\xfaT\x19\x80'\x1dD\xd8\f\nVt\xbb\x02\x90\xbc\xce\xf2\x15\x9d\x87oP\xadaU\x92\xc9\xe36`\x88\xa0\x01\xff\"\u0081\x81Qe\xef]k\x04a-\xdf^v\xf0O\xea\xf4\x86ճ\x86\xfd\xf8\xc4j\xfe\xdf\x12\x98ְr\xcd1\xe3f4cs\xba_%v%l\x93\xe3K\xdfZNi\x92+V\xf8\xee3\xdf'\xb7\xa4\xc4\xd4\xe0~\xe7\x94\xebN\x9bM\xe0G@H\xef\xe4\x1dB\xeeb+\xd3\xfd\xca\xee\xa7v\xddVFq@\x18\x9bݱuKZ\x9dh\xaap@\xec\xedE0\xf7\xf8\x81\xbf\xe4ua\x81\x97\xce\xf2SXd\x84\xee\x85U\xb8\x93\x98K}ԯ\xd28G\x81X\xc7K\x02\x19iI\x04\xac\x82\xed\xa3%\x9a\v\xc7\xfb\x83\x00\a\x19uR)\xb1E\x9e\xe0\x92I-\xa8ږ8\x9c\xc6|\x0e1\a\xd6\x12\xcbG\x12\x80Ξ\xe0\xe6f6\xebȀ\xee=!\x16K\xc0F6\x92Qf\x1e[X\xb1\x15\xd2\xda~\xc0\x10\xf4\x97_\x8f\xe0j\xa2\\^\xea͋^\x14k\x85\x94\x9a\x9d`\x93\x88\xfe\xf9D\xf8\xb5s\xf5\x05\x05\x06G]~\x96㤛y\x13\ao\x10\x02\x01\x8a}\x8e\u007f\xd1;+i%\x8b\b\x1aN}\x87Q\xbc\x9c0\xbf\xe5\xfeԥ\xedU\xbf\xc9u)M\xb6\xdd[\xc6Z`\"\x9f7\r\xb9\xe2\x1a\x0e?/[C\xe4{\xccl\xf1\x82)\xf2$\x18Mr\x89\xf5\xc0\x9a|^\xba\x04\x91\ta\x99\xbb\xe2\xb7\x10\x03\xfe\xa7:\x88\xa0\xcd\"\xe9֊\x9d\xdba\t\xc2l\x02\xf2>\x1b\xdeh\x00\xc7\xe1y\xa2\u007f\x80\x14a\xd1\xce{\x9e2>\xaf\xfeCP\xae\x89\x90\xb0L\xc5\x0f\x10 \x9aj?\xd1n\btg\xe5\x9e\xd8\xd3]\x03\xa6\x16\xe1S\x88\xb8\xf8\xf8{\xe1\xb5UӇ\x05\x91('\xb3\xb5b\xe7\xa3'f\x8f\xe6g0Ӄ\xdd\xea\x18\x95\xc4LPA\xa5Mtd\x15\a\xcc)\xe3\xb32ú\xe3Y!\xd6v\x00\x8e&`o\x85\xaf\xfe2\x12P[\v\x1b\x9daޔ\x84\xbb5\xfb\xc0\fS\x87|#+\x80\xb2\x017J\x05\xa4\x8a\n#\x1bȸ\xcc_\xab\xd5dU\xa9\xa46#V\x19D\xae\x86\xc0\x9bB\"K\x83\xf7\xd6|\xa2\x1a\xb8\xc0\xc1\x19\x16\x80)\x02o\x90\xd0\x10\xaatk\xfdl\x03\x9a\xe6\xc8,\xae\x14\xfbl\x11\xe8\xa1\xeb\x0f\xf3U\x1f\xec)ݹe\x985\x81\x15\x96O\x03\u007f\xa1\xa9\xa7\x04\x93\x93\xaf\x03\x89y\xb5UAt2\xd0_\xb7\xe0\xfd\xee\xf1\xd1\xee\x03\v\xf2n53e*\x83\x831\xbb\x93\x93v\xf4\x15\xb0\xb4\xde(K_H\xb5vV\xcbʉ3}\x12\a,\xd5\xc6A\xb4C\xe0Uƍ\u0602\x12\x94Cu\b\x99\xab\xc9t\x0e\xac\xf9i\xce-]\xb9`\xe6\x05\xce\xd6\xe9\xf9\x1b\xcc7\x84]R\xe6\x0f\r!zs\xb2N\xfb\x96t\xa3\x04\x8a\x91&\xbe\xc5̉̄k)\xbc\xceSL\xa5\xcd\xf4\x9b\x0f\x84̹\xaey\x117\x82\xaa$\xb4\xb0ϥDJ\xaeN\x1f\xcad\xe5\xec\"\x89\xd4\xf9\u007f9\x1c\xe9\n\xe631 I\xcd\x17\x97Z(^(\rlw6\r/\xf5@\x8eY\x8aB\x8e^\xde\xd8\xd9}\xb0OT~9c\xbec\xc2\xf2\x8e]\xf9\x9a\x95{\xe2)\xcb\xdd}\xee\xb9D8\xed$\x13{\x13\xfb\xf0\xde\x13\xc7yc\x96,\x12ʤ\x80{\xf6tA\xbaW3z\x10HI\xba\xabm\xc3\xf0D\xc64ܤU\x04\xfd\xdaT3d\xa6\x0fI\xd2\x0e\x9d\xf3D\x92)\r\x12\x8c\xe0I۬\x8d.\x01d\xeb~\xe9[\f-\xfbK\x96^2\x80Zc\f\x93\xda\n\xdd8\xfd\x83u\xbe,Y\xe9\xb4^\\\xd9_\xa6\xacԁ\xc1_\xf8+\xda\x17cJ\xa5\xda\x1c$\xa3\\2:ZW\xe6\f\xd5b\xd4B\xa0\xedw=\xd7\xda[1'N\x03\x9fYVz4\x93\x1e;\xb3\xfc(\x97fzN\xa7\xc4\u007f\xe0U\x81\xf3f(\u007fp֙\xe0!x\xd7#\x83\x97\xe0\xb6\xcfL\xa9=#\x16ŋT\xe5hn\x05\xd3b\x8b\xe4a˳\"\xd6\xc5,\xccT\xe2\\o\xd4!\x82\xf0@@sN%\xa6\xd6\x18|\n\x95\xc7\xe7t\xe8\xe4Xj\xbb\tj\x1b\xb3\xd3\t\xbfQo5\xba\xfd\x8a\x9d\x1a\x98\xb9\xb3\xedo\x8feF\x03)\x19o\x10\xf9\xf4\x81\x90 \xeb9˷\xcf:\xe1h*'cJ\xe5\xf5孏\x98\xbc[\xce\xd9{\x12Ȅ\x06Nf\xa5nz\x99]8F\x11\xbf/\xea\xa7\x1b|\x92\xba1\xcav\xed\f\xffg@\xd4J:\xb1Y\xcc\xefնNu\xda:\xa2d\xea\xe6hH\xac\xa2\xf0\xf6o\n\xa1\xf8\xbf\xbbt\xbcM\x90\xc6`\x84\x84R̍\xbfR\xf4\xf7i\xc1:|N\xdb_P\"\xa0\xa2\xfd\x88B@\xb0\xb9\xb4\xc8 m`a\x9e\xf5\x8b\xa2:M\xfd\v\x8b\xd0\x02\x12\tc2\xcbŨ<\xc8\x15\xa6\xfdؓ\xb4\x96U\b\x8fO\x8dS\x02\x92\\\x9d\x81\x00%a\\A\x05\xbap\xe7\xf4\f\xe4\xf8ꄯ\xf2\xb1\xbde\xc6\\\xe6\xc8A\x92\xac\xa9\xa9\x9b.̰{\xa7\xd6\xeb\xacw\x86ǿ~\xd1\xcd6\xff\x8e\xba\x99\xbf\x88\t\xf8\x1c;\bs2\x83\x14ŋ`\xf8\xb1\x85W\x8b`\xfdTyP\xf7g\xa8\x01ee0\x16\x87\xf7\f\x11\xed\xf400\xea}/ǔ\xbc\x8d;h[tG\xf9D\xbb5\xd6^E\xbf\xc6#\xe3h\xf7ȍ:f?\t\xfb\x05u3z0\xefڎ\xef$\xeaT\xa8\xa8\x9e^T\xcfAhz\x05\x12\x97\t\x97x\n\xe8I{\x0f\x81\xdd5\x1b\xa6\xe8\xce\xdd\xc0\x8c\x8b\xf8'\xe4r\xc2\xfc\x19\xa5K\n\x80\x9bz\x8eo l֢<\xba\x9e\xd5Nl\xb2\x8c\x9d\x10f\xa8\xa7M\u007f*\xcc~\xd0Uʏ\x87W\xf3\xda_\x9f\x04?\a\x96v\x1e;(A\x80\x19\x85\xa8ͺ\xdaR\xc3^\xff 3\xb7=6\xd26=2\xe6n\xeb~}c\xaf\xbd\x15\a\x90O7\x93X\f\x86\x95\xe0d\xba\xac\x01J\x19\xd6|\x8f\xdeLP\x9cޝ~\x0fͅ\xa9\xfa\xf18\x9a+QD\xec\xf4\xe0\\\xaf\xd4\xe6ҭ\víS\xc3\x17\\\xa7=\xf7U\xd9v\xcc\rM䅚\x1ec\"a\xfb\xabK;\xcfA\xae\x1c\x16=ԨĚ\xa9\x94\xb9\xd6k\x81\x01J\x84N\x80p\x9b\xe8M%AR`\xd1و;\xd8\xf9(\x13\xfb\xbd\x875\xc3\x10W\x9a\xbd\xdb=\xb5\b\x8b\x86Y \x9dg-\xe4^\bv4\x81\xd0X\u007f\xaeى\xfa\x85J\xd8@\xee\xd7=\xf8c\xc73\xc5\xea\xfc\xec}\xca*)\x12\bu\x92\xd6\xca\xffb\x1b\xbcT\xb9\x13F\x9a\x1b'\xd3|\xb9N3\x97\xc1\xb9\xe6E\xdf\xde\x00\xb2\xce9\x89\xbbڪ)1\x90\xd0!\x12G\xdb\x1a\xbd\xf7k8\x92\xad6\x94D\xef\n~H\xaf\xb8\xbdGp\xc0\x04%\xa8Fz3\xee2\xc1\xc4M\x1a\xdfJ\xa2aZ\xde\xd6?\xabc\x8d\xe0n0\x9e)?\x8bh\xe1\x04N\x17\x80\xc0u\x9e\xcf\x1f\x9a\x05\xb2\x1d\xfe\vm3\x1fH\x8e~\xb2\xc1\x1f\xdb\xca1rD\xfc'\xbd\xac\xd6\xd71\xfb\x9e\xe0\xc7\xd5\u007f\x91Kr\x9dt\x9bs\x01J\xd4J\x0fs\xbe\xa3\xd9\xf6\xb3\xa6\u007f\xbeָU\xd7\x05\xcc\xcf\xcd\xf5\x05\x10\x9e2\xb4\xf5\x14r^\xa0+hNzg\x96\xb1l0'\\\x1c/e\x91\xdbtXԐ\xd3v\x9dl \xc9j\xe7cm}!Q\xd6\x1dϼ\x8e\xe3t#\xd4\xe6z\x88\xb6#]\x16\xdb\xd5\xda\x1f\xa1\x1fϕ\xd7\xdeO\x9c\xd1ׇjE\xe1:\x93#\t\xf76\x81n:<\x91N\xe7\x10\xcd\xd1u\xc7i\xb1\xa6\x8d\xe1\x18\xc9{\x85z\xde\x18\x0f\xb5\xd71ʞ\xa4\xea\xfe\xe3\xa3\xebUV\xc9\xf2l\xfd\f+\xd1a\xc2N\xf0\xc2W\xab\xe4\x8d\xc9h\xbb\xcb)O\xa72ymEl٤\xafA\xd6\xd57\x1f\xa4\xa5\xabYQp\xf0\x15\xf6\x06\xb1fB\xac\x8a<8\x8a\x9f\x85\xbb;\x02\xc6\x1f\x05\x8f\xe5\xf4\x96\xf8'gKR5n\x99\xf6\xcc\x06\xe6\xbd\v\xc1T@\t\xaen\xbc*\xb6\x17\x83!=\x16a5\u007f\x89\x9e\xac\xa2\xa1\x83\x88\xb0Z~CW\x97\xd1P^DX-Xf\xa7j\xe8\xfcN\x80ű\x10\xbdq4\xffO\x12\x06\xc1I@\x15\xf9\xe8S\xd2\x12\xfa\xc0\xfb}\xf2Xh/\xed>\xdc,b\x96\xe3\xe7\xf389\xb5\xc9\xf4\xee-:G|\x05W\x05\x91\x92)\xdd\xdeb\xdf\x1f\xfbA\xc7\xea\xf85G\x93\xde<*ٕ\xdb\xda:ğ\xa3\x06!\x14]gj~\xabO\a\xdf&\xff\x8bU\x87N뢹8\xd7\xdb \xae\xf8\x94\xe5\x87\x13g\xf1\f]\a-W\x1aW\u007f(W\xec\x87NI\xbc3\xba\xc3\x1aN\xd2\xc6\x0egr\xe3\x9e3|\xb7\x92m\r\xf2m\x8d\xa0'=[n\x94\ud7acM,?\xe6\x8c$\xb0\b\xd1HD\xae\x93D\xb2-\xae\xdbO\x18?5u\bX\xad]˓\xec\x14\xd33\xfa\x12\x1f7\xf9>\xab\x17*\xe6\x87w\x80\x01g?\x9a\xa8\x95*!\x92\xe9\xf8\xfaJyT\xa2@\vU\xb3g\xce\xd3z\xc5\xd1I\xf1\xba\x95\xcf_\x17\xa4\x06\x857\xd2&\xf2\\t\x8c\x10\u007f\xf0H.\x1fY\xf1Z\xe6(4Y'\xebd\xc2\f\xd7T\x87\r\x91F\xb8\xd2s\xbc-\xecqy\xbaa\xad\x127\x1b\xd3\r[\x8d\x8467K&\xc3J\x88/$\xe0\xb1c/\xc3\xd4x\x8c\x10\xf7\xbd[\x17\xc4\x01\xa1\x80ᶏ\x0e;\u007f\xf7Ī\xa2z1\x1aFv\xf8\xa7]G\x84'ڏ\xeaQ\xafBSO\xc2\x03\xfb\x89\x0e\x95\xe5\xbb\xed\xe9\xfdІ$\xd0\x01\x13y\x99(\xde\x13\xf0TS\x93\xfc-\x18\x1e;\x96hűz\xbe\xcc\x11T\x9a\xc8%D\xe1\xa3\xd7ts\x04\xa0\x88\"\x89\x89=\xeagwU\x12\x81uD?b\xa1\x18$\x1a\x1eZ\x16r\xfc9\xe8\xf7G\xbc\xce\xeb<\x99\x8c&\xfcÑa<\xc5v5\x9f\x930\xd1]\x19f%S\x17\xf2\x89\b\x9ea\x1f\u007fn*\xf1\xd7\xeb؊\x9d\x9d\x1d\xb3oмb\xda\xce\xfd\x828pJ9\x9f\xc1\x82\xd8⠚\xc2'\x98-s\xce@\x86r\xd0\xf0넅\xbc\xa9T\xb0\xba\xa5AX\x81\xa4\x06I\f\xd1\\8m]{\x83Of\v\x95`#\x1c\xca\xd6\x13X\xb3T^f\xba\x195\xf7\xd4''\x1b\xd9\xec\xc4\xec\xd0\x18\x16\xf8W\xca2Ϸ v\xc5sE\xe2\\\u007f\x9e\xed\x88Q\x18s\xb5\x9e(\x99ː@A\xe8\x14jR\x14\x1e*Z\xe8\xfc\x19\xb0\xe5a\x91\x88̳\xe8\x1cSl\x01і\xa2R\x8c[\xcbܜd\xbc*)\x9dɩ\xbb\x9c\xc0\fP\xe4¢ĽHt\x18\xa3o\xfd\xbc5\x9c\xf48\x89\xc9.\x84\xc2]\xc0h\xcb\\s\xe0І؋\xe1\v\xda\x03\x10\xe6\xd7?\x18\xf5Vs\xf1\xd8\xe8h-U\x83'\x89#E\xf6g\xf2\x89\xbam]\xf4\xc42NjWl\x19\xf6rm\xa9Z\xcd\xe3\x12\x97\xa3\xc3\xc3#2\xe7\xf6BE\x1875^^\x87\xa4\x03a4\a\xda\x04\xc5wU\xa9\xedK\xcb'g?ge\x93\u007f\xc8\xdf\x13213\xce\xe6\xe7\xb8\xccǸ\x9bo`\xd4\xd7lKzP6^\x97 \x88$\xf7$9N\x8a\x90\x14\x8bWvg2\xf9H\x02Ϗ\x93\xaf\xe6CR\xefߜa7F\x0e\xa1/\xe3\xb9\xf13\xf1\\8\xad\xfb\xadF\x84\\\xb9/z\fP\xcc\xef/?\xfd\xbd\xec\x1e\xe8\a\xee\xa7\xe9\xf5{x\xd6\xe3Ӽ\xf7]\xaf\x0f\xb3\xbe\xbb\x00\xf9\x89\xeb\x17/\xb4\x17^9\xfa@7c\xa3\u007fޥ\x0e\x1aG\x1b^2\x9f\xe0\xe6_\x96\xc6\xc2Be\x9a;b\x96\xa2~\xf3փ)\xc7Ό2\xb3j\x80\x8b\xd0 \x0e\x95r\xf18]'\x877\xda\xf3\xb0\r\xf5\x8b\x89\xc9 b\x8cC\xdfh\xc7\xfaT\xe6\xc5d\x97\x87\ue635\f\xfd)\x04\xa6+\v\x92\x89\xc5\amD)\xb2\xf5\xd5.5\x871\xd1-\x14\x00\xae\xfc\x1b\xce|Yy\xf5\xf1\x92\xe0*\x12\x01\xb1\xbao\x8dڤ\x1c\xf2L\x13 \xa4\x06\xdf\xf24A她=\x02\n\xc4\xf1\xf6T\x83\x98\xb8@|\xccX$\xa6\x15i\x1an.K\xdcI|\xeeR\x84\x02\xa0\xf7@\xdfP\x82\x86\xfe\xe6@\x85\x91\xdcP\x8f\xe3\xbd\x1c*\xb1\x96\x1b\x8aa\xb2\x97\xc3\xf5\x04\xb6k@\f\xce۟\x8c\x0f\x95\u007f\xaf\xa3\x94\x97\xed=I\x9a\x84\t\xe0=\x9bl\x17\x9b\xc1\x01\xbb\x8e[\xbc\xa9\xbcג\"\xc4h\xecX0\x8fQҜ\bf\x01\xa7\xfb˒\xdc\xe2펖\xf7c\xdc\x1e<\x1d#9`|cO}$o\x01>e\xa9X<\x8c`,\xfao\xbe\x90\x11\xa9_\xb1\xe8K\x893\v\xe7\f\x8c\x8d\x8e\x83\x15p\x96{Y\x12\xb1\x05\x87\x95\xe1\x1eAn[\xed\x199\xabM\xdb\b\r\xa9T(!\"\xbe\xa8\x06?Z\xb0]\x03\x83i\x05E\xc4m\xb2\vĞ\xc2>\xd5'\x96\x86\x99\xe5{G\xc8t\x9d\x1a\xaf \xaa\xd7*\x11~\xa6\xfc\xeb\x9ay\xb9\x95\xeb`\x89'\xabA\xfb?٘#\x01\xfc\xd4)\x02\xb7\x10o\xc6($\xe2\xf5\xe3ȉەL\x9f\x8d\xd4\xfcvYO1o\x1d\xbc\x9c\xf3_<\xec/ǐ\xb8\x01M\xca(\xb9\x80\xb4\x14W\u007f\xe8\xaf藑Q\x91'^\xea\x1b#0\xfaM|\x973}x7t\x91\xc9<\x88\xcea\xfe\xd6@\xbe̻\x00\xcbH\x9dl\x8f1\xc7>\x81\xc0\x1e\x9f& .\x13\xd4m\xf3v\xa2\x9a!*\xe0\xf4)$\xf3z\x9f\xdcmr\xc7\xd8t\xbd\x85\xb4\x15(\x88:\x1e\xb0\xb7\x83G\x88\x1cG\x87beV\xa6w\xa2i$C\xbeO1\xf4\xf8\x10 \x90\xd0\xdbc\xe7Z\xdcZ\xec\x8e0\xcbG\xc6 \b7\x02\x01z@Jy\x96\xaf~\xc2\xe5p)g\x1f\xd4,g\xed\xd9Y\x1bL.$\xb9,\x1f\xab\x05\xf7 \x97\xc6-\xde<\xa0\u007fk\x17\xce\xf9\xd2\xf9{\xce\u007fy\xfcc*0\xae2\xc6/q1\xa7\xb5\xce\xe1\xf2\xbb\xc1\xab\xa2\x93\x12\xbfg\xc2\x0f\xeb\xba\x16\x81\x83\xe0\xe4K\x16\xbe\x95\xf1M&\xc0R<\xe8\x0e\xe5\xc77xC\xe6\x9ey[M\xf4\x96ʛ\r#ͺ\xf9\x00\x8e\xa3\xe7D\x18ya\xb9\xfe\xa93\\\xae\xa7wf\x9ewr\xc8\x11F\xd9ĸ\xbf\xb7M\x13\xb3]\v\\\xb3\xa8N\xf8\xd8\x1e\xb0s\xb1Wݍd\x9d<ӡ\xfb\xd2\x00\x83W\xe5\x00\xbc\x9d\b\xaa064\xdf\xfet\a\xd5ȴ\xef\xd0v\xf0Ȼ0>ԯ\f\xcc\x04\x88\xef\xd0; \x04\b\xbd\x93)f\xaf#\xaf*\t\xa22<\x02\xfb\x0eh\xfd\xcd \xf7\x1f~'B\x18\xc2w\xac\v\x92\x0f\xbam\xa2H/\xe2\x19\x9c\xbd\xd3\xec\xb7\x03\x90\xaf\xe1wqM\xb0\x1d\x0f\xf0\x14\xc9\xd8\xf6o\xeeg\f\x13\x10\x1bC)̵67\xdb#\xe5\x88B\xc6S\x90\xf8>_-\x15[\xcd\xc4L|R\xbeR\xcf\xf1\x90\xcb\xd1l\x14Q\x83}\xee\x1c\\T\xbeH)\n\x9f9Fa\xb1\xbb\"^\xe0b\xa6A:\x91ݳQ4\xb1\xbb' \xca=\xbdsO\t\x0f\xa1\x03\x10\xc3\xf1'\x83\x1b\x19@\x02.\x9a\xe8\xd9Y&8z\n\x8a,i7\x15\x1a\xb2\xb5\xa3\xea\xfd3y\xd8\xc1;\x8d\x81\xebU}p/\xdfI\x9f\f\x01\xeb\xff\vxV\xf9x\xd6\xdeil\xf8F\xbdZ\xc5\xeaf\x9b\xff\xcb\xf9hX\xdac\x87\x98\xd4\xec\x1e.b\f\xe8\xeaB*\xac|&\xbf\xe2\x8f|g\xab\xb7e/\xcak\xc8u\xbb\xfev\\_H\x87\xb6\x9e\x9eb\x82\xa0\f\a\xfad\xd9p\xe1G\x9b\xbe/\xebA\x9a}\xf3\xc0\b㬬'\xec\xf7xȜ\xaeՋ\xe1\xb9;\xd6E\xf0\xdd\xd8\xe9\n\xcb!W\xb8\xdc\xdf\xe8\x04\a\x80j\xcc\xcc{\xaa\xed\x9c\xd9ZI$\xdfz\xbe{O\xde\x14p\xaf\x1e;\xe7x\xa6\x12\xb0=\u05fa\x98q\xde{\xfd\xd3\xf5\xa0\xf5\xc95\xfal2\xb83O\x8e\f\xe5=\x01\x19\xf9@\xed\x13j\x86j#\f\x13\xf8GY\xbfT\x93n\xa1>\xf9&ެ\x0e\xaf\xcd#\x83\xcfCBϩ\xffzL\x1euy\xb5\xf9\xddl\u007fS\x1f\x02\xefa\xbda\x97\xa5\xee0\xc7LTv\x82\xc03\x96\xe2,\x8c2\n\xe5sdT\x01r\xe7U}E\xdd\x03\x95\x9c\xddl\x001\xe0\xb7z\xa2`X\x0fa*h{\x1f\x9aq\x1aiuU\xe3\\\xde\x1a\x16\xaa\"L\xfe\xbaд@\xf9T\x95\xd6X\xd9RU\x87\xbeF\x03g\xf6]s\xe5\xc4\xdd\x17E\xc1\xce\x14\xb35\xabV0\xdf\xcbX\xac\xd2\x16/\xc6\xefu\xeb\xb5\xc6k\xbaz\x85\x9dB\xf5\xbc'\aك\xc0J\xbax\x19\x1b\xa2\xcc\xe7\xdf\x1c\t\xe6Iz\xf3\xee\x01\x80\xd27\xfa\x8a\x91\xf5\x8d\x92\xd2Y\xfe\x86Ε\xed1t\xb4\xbf\xb6y\xaf\x88\xb7Κ_}\x81\xa1|\xb4xm\xe3[\x04\xc0x\x02J}z\xfcl\xf3\xc8\xfeD\x9b\xd7V\x97\xfb\x86r\xf3\xd7csdsq\xbav\xe5[\x91\xe3\xb7&\x11\x8e\x8e`\x9foU\xb6\u007f\xb8\xbel\xeb?\a<\x1cj\xdbC\xf4!\tOe\x12qB\x0e\x93\xb6=\x99J\xdc\\\x9c\x1e`\x9e\xc4Lr\xb1孈\xe1d1Mh\x1d\xf7o\xabw\xd1ѹKi\x06\xeaģ\xead\x8a\x95*;^\x18ҋ\xcb\x18\xbf$\xb5\xb5xH\xb1\xef\x18\xc7U\xb8\xb3U`]G\xb5kC\xadꆂ\xe6\xec\xf7\xb3\x03\x06\x9a\xb1\xfdO\x98\xedQS\x85C\x95\xe2w\x93o\x8f\x16\vg~\xe1\x1fyG8P\xef\x99{{H\xae\xbf.$\xf5\xfb\x17\xdf\x156\xc5!\x16\x11}\b\x1cd4,q\x1f>\xe4`\x16\x80\x04ll\xb5UMBR\x93\xb9Pe\x02\x862\xe6A\x8d1R\x84\xb9\xe2H\xfcq\xbc\xe1l\bB\x90Q\xbf\xa6\xa6$\xd2W\xa3%\x89\xc7b\xe2\xb7hB\x89\xb2\xf9\x0eÚV\x1c@(?\xfc\x1d\x1d\xb6\u007fF\xf7\b\x9eA\x98Q}dl\xed\xc5\xe0+\x8c\xe7\x9db\x8a\x9b\x10\xe1NIM\x03\x16\xc3dT\"+\x18\x0e\x82ƌ\xb9\xb0\x18o0\xed\xc5`\xc4\x1889\xc1\xfe\xd7\xcf\xfc\\|5 ޣ\xf4\xbbئ(\xc7\xfa\x93\xa0\x8b\x92\xd8y\v\xf1j\xa5q\x94\x19m(\xb2\xec\xf7\x80\xe6\xd3<\\G\x91\t\x15\xde2\xd7\a\xe9\xf1dT\x9e\x18\xf3P\x9c\x970\xaf\xf4\xe8$\x88\xa7\xb6n\xcf\xe5\x1f@\xa1\n\x02Ē!\x01\xd7X\f\xbf㺕\x9f\x96\x96\x1c\x8d\xd3N\xe9\x83\xc6\x19kճ\xadxiki\x90\xf6\xde\xf3\x9c\u007fݝͨћ\"0?\xce^2\xe5\xb6XF\xe7\x8d,{s\xc0\xe6r_e\x10@V\xae\xfa\x15\x92\xc1\xf1\x92y\x9fg\x88\x92\x14\xfe\x1a\x13\f\xceN\xca_\xe7i\xf4\b\x8e\x97\xfbw\x02q\xbd;X\xda\xc8\x1cED\x83\xa0\\\xa1\xadb1\x1a\x1eG\xa3\x92(\xb6\xa4\x10\x8d\x8aRs\xd7\xc0\x92\xaaT\xc5\xcb\xdd\xf4<\x1b\\ډQ\xfe\xf9\x91\x022tT\t\x83;\x97\x9f\v`\x92\xd5\xdc[\x1b\a\xd9,\xb0\xeaAk\xbe\xa3K\xa3\xeabDl#\xe3b8\xcd,]\x99i\\\xac\x9b\xb1\xfe|kC\x89\xd9\xe5\xd0xLq~r\x16\xdd\n\xd4Ά>|\x8bž\xbb\x0fB\x8a\xdc\xc3\xc9a\x9f\xe8b\xc4\xf7?a\xdf\x10\xf0\x80\x87a\x0eg3\xbc0\xa0\xe8\x0e\xd2\xe3(\tj\xea\xdc\"F\xb5A*\xed{ߣ\xcbd\xb4]ř+XH\xe6\x94z\xc0s\xff\xd9\xd6\xf7\v\xe5\vZ\xa9\x02S\xe9\xe2L\x1d\x0f\xe0\x0eu:\xa7\x99˅\xe1)\xd2Ҳ\xc0\xddn\xb8J\x1c\x8eEB\x0fnS\xbe\xf6\xec\x0f\xb4>Ħ\xf1\x02\x13\x93\xfa\xc2\xcd\tm\xfdh,\xf2R\xcd\xfb\xe7\xdd\xd2T\x8a~}\xe99,\t\x90/\x82\xa5\xa7\xbe\xe2\xfb\xb5\xaf.\xee\x84\x02\xe1\xfd\xaaH\x80~\x85!\xc5\xe0\x85\xcb`\xd2\xd7\x02E\xf9\xbb\x0f\xbc\x18x\x19\xfb\x14\xf8\x14O\xf9ۖ \xdb\x1bm\x04w\x01I\xb0l꧴ёUz\x9dz\xf6k*\xbd*|m\xe5\x99\xca\x02*\v.?\xfd\xf5\xf7~\xe5\xfc\xbe\r\xc8\xe5c\xeb\xf8\xb9\xc0\x02hp\xd7\xd3?e\xcdY\x97]\xb9*H|̛1\xcf\xf4\x91\xf9\xc8e?\xa9V;\tا\t\x0e2\x11\x9aPQV\x88\xbc\x92lW6m\x1c5O\x11\xa43\x1b'\x03\xdb^\xfd\xa2\xab\x1cx\x13\x12\xe0,\xa8ҹ\x1b\xb3a)T\xec\x99\xf3\xa5eU\xfb\xaes10\xab\xdb\xd9\x16\x84ft9\x17\x13\x80\xfc\x80\xc3\xfe\x1c\xfcT\xbb\xae{\xd2!\xb0\x8aL\xc0\xa7\xd1@\xefOL\x8e\x97\xd5tǽ!\xc9\x0e\xfa\xb9^\xe3L!t\xad\xe6i \xf6\xa4\x96^\xb8\xf9:C\x12\xf8\xccR\xee\xd6\t\x82\xbd\x99\xf0K\x9c\xfd\r\x12?2T\xc9\xeaYx\xff۩Fq#\x1d0\x85\x8a\xb0\n<\xf2\xbd\x16\xafhѭ\xce\xfa\x9a\xf5\xc3)\x99\x06\xf5\xae\x1bkes\xb9a\xbdT\x93l\xd5\xf1\rx\x83\xb5\xaa\xc9\xff\x019\xb4\xf1\xbd\xd2d\x8f\xc9%+\xfe\xb3b8X\xfdZ\xca \xeb\xc8;g\x9d\x03v8\fn\x177\x93ϻ\xd4\xd8a\x93\x80&\xbd^\x1c\x8a\xc1\xd4o\x9cb{w\tOO\xe1\x03\xfb\x157\xbfjϯ\xb7زΞ\xc0\x05\xc3,\xe9~\xa2\xf3WY\x16\xbe\xf0ػqÎz\x9d\x1b\xb0\x8e\xb3Voλ\xe9g\xc6'5\u008d\xf7(\xab\xea\"ե\f\xc3\n\xfeA\x96Ӄ\x06[\x9d:\x94\xd3P\xbf\xf1|\xb9Ӓ+>\xa4\xf2#\xd1\x062?$Mnd\xbdu\xea\xc0\xa8e\xd1S\x9fJ%\x9f\x8c\xad\xfe\x12e؞~\x9d\xfdU\x9fq\x97\xd5\xf1\x18\x9a\n\xbc\u07b3\xd9҈z\xd9\x05Rn\xe0п,7\x84\x05\x8b˱\xe8\xf7\x12\xb5\xf7\xd1\xc5\xc5>`\x17\xc5\x15\x06\n\xcd/\xebuF\x12g\x87\x87\x13Og)P\xe7\x95J\xf4\x85\\)X\x1b\xbf\x04k VF\"\xf1\xe8\x03\\t\xf6\xd7\xd8\xcar\xd2\x02#\xf2\xd8wE]\xb3s\x1a\xac:Y\xa0#n\x87\x9a8\xc1\x80\vLm\"6D\x1b\x8b\xda\n\x8e\x1cV\x00\x1bġ\xaeH`Q \u0be2\xaa\xe0\xa8ү\xee\xadQ\x17kG\f\xd3\xff]\x01\xf2<2\x92N\x88?\x9d\x91\xa4\xe0U\r\xe7\xd0&\xe4\x19\xf2|\x86a\x95\xb9\xbd\x02_G\u070f\xb1}\x9bdi\x9f!\x90:`Ⱦ\x05\xe5\x85\xd1\xc1\x1b\xa1\xf8\xf5[\x04\xed\\,Y\xa9\xc4]J\xb3\xba\xfe\x19\xe9Ϲߐ\x88\xac\xc4ì~\xbb\xb6\x97O\x10\x11\x93\x9e\x1c\xdeA%>\x9d\v\xb6\xf1\x99\x04]\xd5\xe4\x132P\x99l5p\xb8\xe0O\x93\xc3ѐ\b\xf6\x81[ʀ4O@\x9f¡\x11,\x00\xc7\x00Ҭ\x8a\x87\x83-\x83,\x19\x994\xbd\x1d\xecX7\x9f-#?\x903\x92\xb8\x04\u007f{\x1e\x1f\x8b\xfd\xa9\x16M·\xdfC\xbf\x8d1\xce8\xa3\x15a\xbd\xaf\x1eY)\xb3M\xbf\"k\xea\x13\xada\xe6_=4\xa7JqM\x85\xe5?\xa2\xccnh6\x8ek\x8a\x1dɜ\x98\x10\x9dP\xff\x1a \x10\t\x9a2\xa0;\x893\f\xb3g\x824\x01\x1eՍZЦө\xa7GZ\xeck(m\x8d\fp\xb6v\xab\xeb\xa6\friZ\x11F\xcd}\x8a\xb8\x8bi:\xc9/\xeb\xfb\x9a\x10\x1d\x8cczP\x9f\xc5uV\xc5Q9E\x8d\xd2&'\xcc/\xec\v\x87\x91v\xe5\x9c\xf2\xad\xf9\x04<\x802\x86\xdf\xf4ۊ\xde\xf6\x8c\x16\x85\xe9YQ)\x82j.\x1a\xcd\xf8HN\xac\xfb\xa2\xda\x1711\x99s\xcd\xd5ʗ\xad\xe9\x92\xe7؋\xe0{\xe6\r\x9d\xa5'|\xadk\x83\xaalT\xab%\xef1\xf2ꪋ\x1dC\xa5\xcf\xddg\xf6QUJ[\xee'\xf2\xc4U\xfaؔ\xfb̝\x97ֶ{\xbf81\xe9 \x1f\x8a\x8dr\xa5n\x9a\xef\xe2\x9aҹ\x85\x12\xcd}\x1d\xba\xce\n\x05:\x13\x11\x00,\xc4й\xdc\xf76\x1aX7\xa4\x9f\xae\xef\xacf\xac\xc1\x1ae\x9b'\x05\r\aNM\x19\xa1\x152p|\x824\xd9\xf4p6\x05\x90\xb6\x02Vn듁p&S=\xc8[- ߞ\xf1\xe0\xbf~\x9dNj\xc6I\x9e\xb0\x9cY\xf5/c`YAq6\x9a-\xfd\x8bY\xae30#V~\x1ah\as\x86\xfeEPT;\xa1u\x1d\x97\xf0b6\xd6\xf8\x86WD#\xc5\aN1o>\xc1\x19\xea)Θ\xa9\xffC\x1bx4\x8c$\xb5/j\bl1\xf7\ny\x97.\xd8/\x9b\xad\xf2,\x97\xee\xf2\x8dRr\xd7\xf9\xe3\x96\xd0\xf7[YE*G\x10Е\xe2Km/\xfd|7\xfd\xc7\xee\xfc\v\xef\xfc\xdfSI\xb8\xea\x82SƗ\xb8q\xa6F\xd5\xd7㍹\xf8\x8c\xa86\xfd\xcc\x15\x05:\x05c\xe6\xfaVs\a\xc2\v@\xd8\xeaw\x9a\x80+\xdak\xff1\x81\xc4c\xcd\x1c\xcf\xf5aí\xe2\xe9\xc9\xfe\xa4\xe1w\x1e0\v:Y5\xcdQ\xb4\"\n\xc0\x8a\xea\x9f+\x16g\"\x12%*\x1e\xa32\x1a\x01\xe9t\xcb\xf5\x9a`\x8dG\xa5\x90ݴ\xa5\r\xc0f:hN3\xec\x163\xc6\x16^\x05\x86~\x87yө\xdf\xf6\xe0)\x1c\xd2o)l*\xde\xee\x91H\xf0-\x1d\x96;\xfb\xc8\xf4\x03\x03+\xd9|\x91\x18\xd2+[\xa5\x8a-\xd9\xd8\x15ZG\xae\x13X\xf9f~\x8e\x12M\xc6e\x95b7\x0f5\xa4\xb7\xd3[\t\xdeHo\x16}p\x10\x03i8\u007f\xf1;\x1d`\u007f\x94$\x907\xbd\x98~\xefYw\xa24\xf7\xe5Ryp\x06J\x92s\x88\xa2\xaa\x03\x82\xbd\xe0\xc1\x87\x86\x02}\xd8!*Yf\xd7~\x91\xb0\xf1\xb0\xea\xa6W\xf9\x81]\xb4TKV\x18\xe00Fy\xf9\xdal\x83\x1b\x89$\"\x99\xcf\\\xd6\xf9\xc2A\x1a\xbb\x83E?\xfe\xa2\xd4\x04W\r,\xdd[b\xf2\x12\x1e0q\xf9\xe6\x10\xd3.\xfb|\x97\xccx\xb5Z\x1e\x8d/\xcaˁ\x04\xc1\x95\xff]\x92\xf0\xd5P*4\x1a\x03\x94$*(\x93\x94\xc1\x89\b\x19R7\xd1\x01\xb4L\xa0&\xbe\xa2\xe0\x12\xe5`go\x10Tܑ.\x19\xa2$\x9cV̇\x89h\x16\xb5U\xeeL\xf0Hn\xa8e\xbe\xfai_\xad\"\x81\x93\xd8\x03o߁\x00\xfd\x16\xb7e*mb\xee\x9d\xe4D2\x9a\xa3\x96u{\xf4\xf4\x1eݹш\r߶\\\x1b\x9f\xa8\x89\xefؿ\xe8\xa9\xec\x84\xd9\xedZ\xa7D\xc7ܚ\xc6\xf4\nv\xe8z\xfe\x0e1Ul\x87\x10\xe0Rl-wk2V\xf9x\xd9Ց;\x9d\u06004\xfd00\x85=ԑx\x8f~\u07bdګ\x03\x03\xd1\xd7\fo2\x02R\xdbm\u007fԔ\xb8\xd7=\u007f\xde\xf4_\u007f\x9d\xd1r\xd7\x1f\xfb\x96Z&\x96ן/\u007f\x1b߸\xa7\x9d\xaf\xa1\xab(\xe7\xcd[\xcd\xe1C{\xe8%b[f\x03\x85.\xe1\xcc\xaf\\l$}\xedV\x11\xb5\xf8\x82\xcb\xf7چ\x1fU\xf6\x9f\xc8\x1d*B3\xfdl\x94\x0e\x14RPf\xeb\t\xd1d\x03\xaf'\x0e\xbe\xfa\xcd\xd5\x0e\xde\xd6\x02GL\xee\xee\xe5\xdb\xd1\xc5c\x01[\xc3d\xfdN\n\x8d%C9\x8bX\xa5<\xfaQ\xed\xed^i\xf9\xbb\xda\xef\x8bp,U ȑ\x14\x17\v\x1fTÉ\xf6~\x91\xedU\xae2\x17('w|\xd6/\x9a\xabB3\x14\x00\xc2\xea\xb1\xd7\xe8\xe7J\b,\xbbt\n\xea\x1e\xdc\xf1\xacWgLN$\xf2 [\xc8V\xe3\xfc\x0e|\u07be\x99v\xc0h0X\x9dX\xfe\f\xe9\xec\x9a\xcf\xd0<\xdbj\x8eh\xe7\xf9\x9c\xb6\x19\x89j0\xd0\xce{rLNm\xb3\xad\xe6[[L\x1e\xf63S\xb1$Y\b\x83\x11\xf7\xa5\xf1ʈ\x13~\r߇\xa5\u007f\x92\x91K\x9e\xb0\xba\xad\xf1\x18\xdd!\xd5QE(؋\x9a\x93\x8b\xc3\xd9P:&\u007f\x97\xf9{\xafƼӬ4sœ\x89\x85WL3A\x8c6\x85R\r\x11iv-\x157\x05S\x10:\x9fL\xb13\xad\xb0e\x06\x9a\xf1\xee\xb9=^\xaa\x8b\x89\xaf\x19\xa2Ŧ4˳\xbf4\x06\xc2OC\xdf\xe9R~ܐ\x8c\x85NK0+c$&3\x96M\xb1\xfc\xd6\xe9u<:\xa5\"\x15Z\x93\x94\xe8\x00,\x9d\x8a\xc7n2N\x96\xc6\xd4\xceEG\x96\x10\xeb\xd1%Wթ!`\x10\xdd\x034ى\u0087\xfa\x1b\x0f\xba_\xda\xce\x1c`\xd5\xea\x80}\xb4.\xf1Kq\xdf\xf4\xc5~\x9bJ\xc7k\xa6\xa7t\xb9\xcak\xcd\xf6S\xc3y*\xcb\r\xb3\xca\xfb)\xf7I\x8c\xf9k$Q\ue18c\xde\xf6\x86r\xd5q3\x89T\x94\xb5\u007f)A\nRs\xfe\xc8=[D\xb8\nj9\x1cq\xaa\xef\xe2v\x1e\u007f\xcfC\xdcno\x03\xe2\x9dKR\x1e2\x86v\xdf)\xc6\xcd\xd41d\x9cc}D\x992k<9?\xc0]\x0e;\xc48\xfd\xa1\u007f\xfa\xbaBR)x\xf6ˣ;H\xd3i\xb4}{\xcd74\x9e\xcd\xca\x174Ϗ[\x16\xc4\v\f\xde:g\x9aV\a-}@\xb8 ݡ\x1a_׀JPz\x17\xa5\xb3\x8f\xfa\x87\x8d\x95X;\x97)aDJ\xcd?\xa5\x8f\x9c\\\x15#X\x92\xc1\xecr\xe9\x9a\xe7w\xf0m\xbe\xc9\xcd\xfeA\xf3Ў2\\\xa9\r\xdd=\x11\xe669j\x89R\xf0\vLm\x8a\xa1\x8b\x02.I\xc2eG\xe3\xb5\xfc\xa0R\xb0'\x9c\x88v\xf7$\x98\tP\xd0\x19>5h\f_\n\x80\xaa\x01c\xd5ҠW\xae?\xbc\x86+\xfa\xc2\xe0\x00\xf5\xff\xbc\xf7\xe3`ރχ\xb2#C\xbd\x80\x97\xcb\b\x18\xc5B\xea\x9b\xe9W'B\xab\xc3~\xb3\xab\x82\xcd\xfdc\xe1b\r\x00\x13\xd2\xfe\xef\xda5~}`\xf0\xd5A\xd6E(\x12(r\xa2\x1b{2me5\xfb\x14\nt>`v\xb3\xc3\x03\x03\xefd\x02,\fp*=\xaeϕƼ\x01\x18'\xd8\xe1\xb9\a o\x8e$ݥ\xaa;f\xf2`\xa2̢\xd8\xfct\xb1\xb9ɟJ\xaf$\xdf\xfb\xe3\xaaH\x1f\xfe\xe5Z\xe5\x00\x04\x12K\x95\xc3Ԋ\x83\xb1\x1c\xcfk\x03\xc0+\x10L\x01m\xed\xad\x14\xde\xdf\xefR2\x1e\xa4\xe5\xae1\xf4,\xb0q\xe1\xc7\xc3\xf5\x88\x95\x87F\x1e\xef\v\xc1\xa3p\x92̹-\x97\xbdJ%b\xc7\xeb\x1f\xa0\x95\xcf=g\xf5V\xf5\xa3\x8d^\x89y\x81\x90\xbd~\xcf\x17\xc3\u05fc\xf5\x150~-P\xc7\xcfת{\xfcƛB\xa2\xf8\xc62X\xb2Z\xda?\xeb\boG!x\xcdn.\xca\xdb}%\xae}O\x1bo\t_\xbe?b\xb8\x1bJ\xdc\x12\xe1\x89\xe7N\xbe\xf9v\x1b\xb2$bl;z\xe9\xce`\x86&K\xab\x87x^]\"\x11\x92\xe5\x15\xc3d\x98\x0f+\x11\xe4g\v\x01eI2\x80\xf9\xaf\x8b\x04\xf6 \xf2\x81\x14B#\xf0(ijNN>SwF\xc1\fW\x00\xd3\f\xa1|\x97\x03b\xb8\x18\t\xfe\x02\x88\xc0W\xf9oW^\\q\x13\x1a\x8f?\xbf\xa61>\x04B\x00L\xd0/=\xd1iR\xff\xdb,\xbe\xeb\xf8\xe0\xc8cykW\xbe\x18Z)\xc7BU\xbc\xa0\x8e\xd6kjy\xd5\x1b4X\xfe\xf5\xc7K\xc3\xe6,\r3\xf1\n\xeeF\x00\x02\xfb\xe5\xbc9\x18\xe2pK\xebu\x8e\xaf\xb0շ\x83\v\x97\x8c\xd9q\x90@\xf7\x9c\x98OAv\xfeyG4\xf0\xfa\x90\xcb\xde\xde.,m\xb9\xa3#D\"^\xccѣ\x87\x018l\xa4QZ\xf5\xa51\xf5\xf3\x82\xab\xd0C\x94\xae\x9f\xe8\\\xab4oJܨ\x8c\xe8힊\x0f\x95\xa6\xa0\x85\x1d\x93\xfddD6\xe7h[\xa6\xbc|\x1a\x99\xd7L\xd1\x1c]\xd5V\xf8~\x81.\x86\xd7:\xb6\xe9\x0e\x8c\xc6\x12\xcc\xd40z*\x05\x18\x1c\xfa\x19\x15\x9aHX\xd7,\x80Ͽ\xcf7\x9f\x91z\xae\xf6U\xf4QN\xbce.7$:\xba\x86\xc5.\xcd\xca0֣M\xbd\xe5j\xb9\x13\xeb9\xff\x17g\xaa\v{2ڬC\x8d\x1b\xfe\x1b\xabO\x19\xbd\xa2墸\xd3\xfb\xff\x90N٘\u007f\xc3@.\x8b\xd4W\xd41\x05D\xb1\az\x1c[\x10\xc1\xb0\xe2[\xb0M%V\xe65\xecr!4&U\x99r\xab\rs\xe2\xa07%y\u007f\x00\xe7N\xd9J(?\xa5nYm\x89\x1e\"T\x13\xfaC\x8dMmr\xfb.\x04\xee\x98ݴ{bSNT\x8c\x1d\xec]*\x19}\xe8\x92\x1bv`\xaa\xa4\x98\xfb\xa2\x951\xea^H\x9d\xe5\xee\x8b\xd3v\x93No\xeeUۆAS6W\x99Oىe\v[(\xda\xceB\x11\x03\xe5\xa2͝\x1e\x85to1bϫ\x15ZH\x82\xe7\xbc{\xd1\xc0\xf5\xa4~\xcbN\x80}V\x1dˋٹ\x00o\xb2\x92\x15<\x8b>#\xc7\xfd\xa2o\xaa\xf0\xee\xbeTFD\"\xef\x1b%7\xef3\xae\xac\xd7.\xf5(?\x15\xbef\xb7\x92\x83\x8a\xe5\xe6]\xdf\xd2\xf5`!\xf5\x9c\xc0\xb1\xfc\xc0\xbf\xbc1%U\xef\xf4qL:蜧\xa8ϸ|\x92\x04\xfb@8'\xf3\x17+\xae\xf5V\xa8\xb6W\x1eu۠\x82\x9d0\u007f\x8b\v\xcb} +T/\x89\xeeQn\xe9\x13\xa0\xe2l\x10\xea\x9e~\x86c\xbb\xf2{\x97p\xab\xfea\xed=\xa6\xe8\xa3V:#vm\xf8\xe9~\x90\xe2\xc81\xee\x81\xcf\xed\x90\xf6t\t0\x8dSPH\x81]\xb6/\xc8j\xe2g/!\xbb\x92\x88\x1b{/\x1b\xa3c \xe5j\x9d\xd0\xf7\xc9h\x91\x85\xe2[\xe3=\x92\x10U\xd5\xfa@ʍq\x8bIg6\xceM\x96\xad\xff\xfa\x1f\x97\x95mq\xe9\xfb%Y8\xec\xbedc\u007f\xd5`\"\x17\x8d\xdaX\x91t\xae\xa4\xe5\x01\xb3\x9d\x13\xa4\xaf>\x9d\x17\a\"\x03\xb7\xfb{\xe2\x85\xc5ri\xb8\xc5\x14\xe9P\x9dO?\xfb\xac0=\x86/\xbf9\xb3\xd2F\x01\xed\x13n\x1eV}\xa6OY[\x12՜\x0f\x1b\xbd\xb5\xaf\"I\xee\xd9\n\xe9{GEz\t`)Ӈr\xca\x12\xec\xc1\x1d\xb6OoK\xf1\xffY\x02꺧\xfeS\xef\xe9\xc7\x02\x954\x03;\xa0\xa5\xbb\x94\xbe\xeb\xb7\xd4\x1eL'\xf4\xb1\xb9\xa2>\xe1\xb0c\xe8\xc4\xe1\x92N@\x19\x95\xbd\xe0\xaa\xf18 \xe1\x17ʋ\x8a{삕z\x14b\xf6\x048\x05_x\bV\xe2\xd4\xf0\xd3\xdc\xda(\x1eX\"]Δ\xacěM6w\xfe,\xa4f\xe8gf\x94\xd3+͜)T\xaa\xd5J\x1bU\bt>\r-\xe8]z}\x03\x1b\x86o\xa3*\x91mG\aŶ\x1f\x961\x89S\xcd\x1d\x8c<\xbb\xb1\xba\xbb۵\xe5\x87\xfc\xb7&\xaa\x85\x15:\x17\x97\x99Q\x83z\xf1H\xed\xe1j\xba\xbdl\x1a\xa6j\xfe\xb9L\x01\xee\x1c\r\xd8F,\xfb\xff\xc1\xf0\xf8\x8fa\xe8Y\xaa\"'Lˬ\x86ɴ\xa5\xb2bJp{\xf6\xbc\x976\xadի\xe6\xa4\x0eh\x93\xe6\xd1]\x13\xbf\x8d\x10m\xaa\r\xfdE\xd2=\xae\v\xd2~\x92\xeaf\xa1\xbb\xda\x04Fv\x1c\x8a\xdf\xea\x87E\xbb`EWin\x16ux\xe08!GVY\xe7??7K^\xf6\x15+\x9b[2\xb7\x96\xdd%_\xacmw\xe4\xbas\xc3Z\xb5\xea\xe9MZ?\xdcv\xe2l\x9e\xb3\x939\xa3\xb9f\xa4\x88O\xca\f\xcf{\x1c\xf9\xb2\xaa,\xb3'9\xab/\x1b}\x15\x00\rT}\xe5\xcc\x1b\xeb\xca\xe76\xd9\xdeV\xebzô\xffvU\x12\xb9[\xe2\xd1dT\x1e,_u\xeaV\xca\xed\xa3\xe4E\xcd+B\x16:\x81x\xe2\xe1a\x8fY.L4\x8dr\xddP\xcb1\xf2\"\x11\xad\xa1n\xaf\xefj[)Xs\xd6\x1154\x8d\xf5\x01\xdb \xc94s\xe5S\xca6\xdd\xc1\xab\xa2\xf2\f{\x99(\x05,\x89kW\xaa\x87\x10\xfb\n\xab:\x1aDm\xaa3\xfc\x88\xb0\x8e/\n\xf0T\xc5*\xdd\x1f\xd7\x05\xa9z'\xa91\x1e\xb6o\xf1'3\xff\x18\xf8o\x8aw|Ћ\x14\xa5\xa9=\xcaY\x87<\x10\n\x04a\x9eD\xa8m\x82\x1e?F_\xa3Y3\xe7f\x02^\xb7L\x12\x95f\xebf'\x1a\x15@\xd4\x18&M7\xb7F0{\x82\x8c\xe7\x95\x12G\xa7\x8a\xb1T\xc8B\xc4\xd1\xce\xd3/\xaf\x1ff\xb8\xd5zqc\xf8].L.I\x11\xb2n^\x1e\xbd\xa4\xd9\xd2W\xa1k\x94\xd6(\xed\x10h\x1a\x8a\xddc\xa4!Ȝ\xfa\xeb\xae|\xe2\x8a%\xd8?%\xc0\xd0\\\xfd\x846\xdd\x15Q\xc6\xc0\xb4n*\xb9\x990\xc0\x02\xe4\xb3'\x18\xab\x19'\x8a\x8d\x8e\xd3W\xaehĩ\xe3\x9f=\xfb\x00\xeeŝL\x96\x1a\xdcCg\bR\x04\U0005b64c\x89\xa69V\xee\x94\xea玫؛A\xa5\x10ӚT\xbfQ\xf5\xaey\xcc\x05č&i\xfd٣h\xf5\x9c\xe3QJ,#\xf6|d驺\x05z\xcd\xca\xf1\xa2|yYH\xb4\xc8\xe7\xee\xd1{\xaaFI\x12%\x99\xacO\xd8\x11\xe8\x14\x82\x16RD\x92&\xd6k\xea'\xce\t\x17\xf5\x91(\xa8\xac\xfd\xf1k\xd5ͷ_\xdcu\xe1XT\x05\x81\xb04\x83J\xdd\x14o\xad\x81\xddtǠ\x80\xf5\x1d`\x12X\xb3\u007f\xe8\v\xec\xf3\x88l\x04\xda/\x84\xde-\xddԩ\xaa\xac\xae\xc1\x19\n\x14TBIj\xa2ԛ/\x03\x9d\n\x82\xf8J\xc0n0,\xa6ħXB\xc4\xf7\xddU\xba\x9eH\xd5h\x1d\xd7\x17Fe\xa8\x02%\f\xd66\x8e%\f\xd4/\x12\xc6\xc1\xb5\xc6\x02\x14:&zLl\xb1\x19dKT\xb5\xf4\n\xb1^\xbcGv͊\xa2\xca\x0fSA4\x8a:\xe4D\xc1\x04I\x81\x06\xf9\xde\x03\xafʯ\x91\xf0\xe8<\xb8\v\x96!.\x941?\x1enT\xe5\x9e\xe0\x19\xc8z\x1d\ahԓ尵\f\x9fZ\x88B\xe4\x18\xaa\xf2\xa9\x17\x96\xce\uf1efCn\x16\xd2\ue5f5\x1f\xf9\xeeI\x9d\x9e\x00\xf8\x8f\xb3\x89~\x03+\xdb\xefs\x02m\xa68\xb9T\u007f\xb0\xc5=f!c\xb7(\x9aK\x1bH\xf7\x8a\xea\x83S\xad\xcb\xe8H7!L\xf0S\xbf.D\xc4\x024\xe7\x8b$\xfe\xd9~]\xcb\xdaٴa\xbcG\xe9\x02\x9as\xafi\bK7\x90\xc0\xe0\"\u007fdϸ}\xbf\xac\x89\xb5\x9a|\x9f{\x9d\xa9\xd8ܰQ\x927\xder-\x0f\xca\x1dy\xa7\xfb\xc7\xe0\x88̂z\xab\x15RaV\xce]\bv4t\xbc\x96\x9e\xa0\x8f\x8b\xbf\xb0\x052\xfa\b\xed\xe4\x04\xfa\xc2-\xe6\xc7讨YD\x8eی\x19\xedS\xd8@\xaa%_\xd1B(F\xd6\x13\xe3\xddHke\u007f%&\x045\xfb\xd5='\xbc\x1bjF,\xa7\xf7\xfb\x98\xbaG\xf5\xf4oW\xf8\x109\xe8;\xfc(\xefڤ\x90\xc1\xf7X\xd03z`\xf7f\x9dM\x83\xd4<\xb5~\xdf1\xea\xcb\xf9bR\xf46t\xa6\xe8\x140l\xbdu\xd6F\x9a\xa9\xbeIj\x11˯\xfb\xe3\xcb\x1eJo\xab\x88I\xccq\xa8\xb9\xb6Ĵ\x10(\x85\x1b\xaec\u007f\x03ǘ\xc7U\xef\xc8@\xf4\xba\xab\xdb\xd1\x1dѢ#\x02e\xcd&\x9b\xb1V\x95\xb3\xf7\xa9\xcc\xf3y(\x18\xfa\t\xf2{̧Ku\xa4\xcf\xe1\x98WK\x13e\x01\x94\x90Z\n^>(wDI\xa6\x19\x92\xdb\x12\x15߹}x\xc8\xde\n\xfe\xdaƺ\xe25\xbcgY\x80G2\xa6\x1c2\x0f\xc8\xd3\xfb&\x8b\xf3\xfb\x9e\f\xd3sσ!q\x19\x80\xca\\\t\xa1\xc1\x9e\xbc\xac\x8c\x8e\x19C\xddP%U\x8b\rfb\xeb\x13\xf5\x05\xf7S\xb5\xaf\xe5\xda'\xb5H\x85Lbi\xcc,\x9cs\xb5\xe4F\x03\xc0\xb9\xf46\xe4\x04\xa6\xae7\u07fcD\xe4\n\xe6\xa6g\x1ḍoGa)j\xe8S-&\x9d>7\x94\xd2y\xc6\xcf\xe7\x15\x1eCCΖ\bi\xe2]\x00MR\x1c\x93\xa0\xbb\fA\xf1\x1a\x8f0\x99\xf0\f\rKf\x93\xb4F=z\v\x8c\xc6g\x04g\x8a\x03\xaftf\x9b7\x17Kx \x90[\xd0\x12\xe5\xab\x1f\fL^.[\xb3\xa6ԭ>\xf3Z\xd1\x01c\xfb\x197\xe4\x16\x13\a\x8d\x8536\xfe\x16c\x1e͗\x99\xd7q\xcc\a\xb2w\xac\xb9*CC\xf9V<\xb7\xfc\x0e])E\x8d\x1d\xc39\x9a\x9f)\xa8ϛ\xca0l\x94SM\xeb\x1f.$\xf4bAS\x98\xea\x96Hib\x13%z\xec\xb2qݓV\x10\x03\xdd\xcf\x1b\u07b7ʀ\x187\xe4\xf6+8\xe0\xfa{\n\\\xe2H\xa6A\xe1Z\x1e\x00#[\x978\xc4\x05\xa40\x9e*\xc6\f\xd1r\x1f[-\x9csw\x1bn\xdbxP+\ue528HEl\xfb\x19\x87\xe5Y./\xddk6w\x19Kb\xae?\xfb8\xd68G\xf6I\a\x01.\xdf\vu\xa1\x01\x96\xb7r\u07bc\x99l9\x8f\x0fEiޜ\xf8\x01\x12\xa2\x86\x99`\x86\"\x82ƃ\x9e\x91\x8fȇ\x9f˺\xf3\xf6&v\xa1\xccI\xcc\xdb\x04բu*J\\[\xd5^\x03en\x06\xf4Q\x05%j\t?{\xebnW+\x9b\x10\xb31\v\x82\xb2Z\x80\xd8\xdcC\xab\xf2\t\x16\xd2$\xaf\xd73\xf7\xaf!\xdb\xee6\xea\xf7\x95\xa3\xfe/\xa5SG\xc7 @\xa94Ό\x1d\x19E\xb8!\xc3R\x1ad\x9e\x1e8hg?\x83\xd3J~\x11\x8f\x10\xa2\xb2u?\vZi\xa1\xbfD\x18\x83\x874\xa3\xedK{j%\x18)\x88'\x19\xb7\x05x\x9a\xe9Ma\xfe\xffYvkEt\x82,l\xd6\x04\xc5\x01\xfd\x13c:\xc9\xc3w\xe1\x85Xk||2\xf3\x9c\x85\x12\xeb$\xc2.Ey\x86=\x1f\x06x\x92\xc7*-LM\x9a\xb9_\x16\xbe\xb6\xefxC\x83\xd3\xd3{\x05\xc0t\xd3\xe7\x884\x02.\x9f\xa6<\x19\xa0\x04P\xf0r\xf1͙\x99\xe1\x11s\xb91\xb9\xbc/\x9c\x16\xd5N\x1d8\xb0uu\xa2\xbd.ӿS\xaa_r\x84j\xab]\xb8\\\xad\xa5\x9aav^\x95\xe4\x1b\xa2\xa9\xe1s\xf6\xf3Q\x11\x88\x9e\fZŜ\xf5-\xc5\xd4D\x8c\x00u\xb5S\xdd\x0f\x18\x8dg\x8b6\x83\x84\x0f\x86\xb2{${\xe6\x16r\x0f\xa62\xda\xcf\xf0\x00\xfe5\xf3>\xb6\xf8\x1b\x85,\t\x93\x87h\x0fc\xa6\x1b\x16b\xb1J֊\xcf?${ou\x95o>ͨ\xfe\xa4vCl\xa1\x92(\xb6\xc2<\xdc/0\xe7x\xfb(\x0eD'\u007faԧ\xd8R\x990\xdc\xdf\"\xe0o@\x9a\x86\xa8\xa4>N\b\x9b9ߖQ\xb9]\xb6\xe2\xa8\x1a}\xb8\xb7\x003\x81(\x8b z\x1e^)(Үe\xb4\b}E1\x17\\\x04\x02\xdfp\x1a\x9dB\x80(y\xfb\x95f̷\x13\xc5H\xf0\xf1\xcf\xc8Y\x84\xc4/HI\xfe\x8d\x00;,\xff\xa7\x94\bq«=\x95\xa7\xfc\x04d\xd6\xc6\u007f&\x02\x11T\xa6\x04<\xe5\x8d\x16\x99)3\bSfV1\xf3\xe5ړ'\xac\xfd\xd4vh\x92\xca\xcaD\xe6\xf4\xa4\xfc\v\xeen\x86$4n\xab\xb5\xb7'\xdcr}b\x120\xef\xe4D\xdbxo\xfcV\xea\v\xc1\x03\xd0\xfcU\x9dJgI\x1f\x18N\xfe\x89\x9c\xa7}\x06\xb2\xd64\x83\xbb/\x12\xc1\x1b\xee\x8a|ߥ\\\x94\xec$M\x95\x8cy\x81\xbb\"\x99j\xa6}\x05j\x8f\xb9\x00\xe8\x91\xc3i\b\u007fb\xd3\xf9!\xd4\x0fNӽ\x10SB\xb6v\xf3C9\xaewp\x9d7}\xea\xca5\xb1\xfd\xf8\xac\x84\x1eq2\xe8Ѫ\xe0\xc6Ҵ\x00\xf7UÍ\xbb,\xeb\xd5鼁\x1bI\x9d\x16\xf5}\xff;\xed\xddY͜ȝ\x94DJm[\xf0\xf6\xe5\xd0O\xac\xadsޥ$Fl\xe5X\x8a\x8e~\xa6=/_\x18\xbb\xe1S\xe9L\xec\xb1\xec\x17J\xc4\xd3\xdd&\xa8\xc7^(\rqwv#\xeb\xe3\xbf\t\x1e\xef\ua48e\xfb\xff.\xd1P\xdf\xd9\xe5\x16:bB\xf8\xb1f\x1aV\x882q\xcbgn\x89ٙ\v\xaf\x8b\x05l8VӅ\xb8\xb4b\xd1\xe5\xb40\x17\x83aG-OTlO=A\x8cf\x93\xb1W\xecO\u05edOJ\x9f\xfe\x1d{\x9b\xd5̑Ͳ\xb9g\xc6\xf0 k\x19:\x87\xe1\xf9\xedI\xfe\xe73\xe4\xcf*z\x10\x15\xe6\x9bA$\x11\xff\x87\xf3\x95\xbd̊k\xbeP\r\xc9`\xe6\xe6\xb3n\xf5FGx)\xebG\xffRPE%\xbd5\xc4\\\xfd}\xb7\xae\xda\x12\xc0\xbc\xa93۵Ruu\x9b\xde\bW\xe7-\xcc\xe8\xf1\x1f\x99\xfe\x98\xdf\xfa2\xd4\x14\xd4\xe6\xfb\xb9\xfa\xf4\xa5G\x89\xa2\x12\xfe\xab\x0f\x9d\x92\x8b\xf4\x1a\x0e%v\xcdoM\xff\xdd\xcdk x\a\x86\xefB\xf8uF\x8e\xe9N7ׂkV)12\xf0dB!\b4\r\xf9\xe0\xae.\n\x92\x8aN\x91\x038O,f\xbd\xfa\xa7\x12\x9c\u007f2TiV\ru\x8b\xb1\xe4\xc4d\xdbL\xf2\xae\xedzy\xa7\xf9\x1b\xcau\x98g\xd1\xf0\u0092\xcc;\xa6\x19Ks\xdf'\x0f^\xa4\xa7\x12\xa0y+\x83\x1a7UUO\x9d\xa8\xfbB\x99\xf8ж\xea+\xad$\xb4%O\xbb9elե*\x91\xdac@\xaa\x89\x05F\x89\x04\xf5c6\x14gg\x05\xf4MU\u007f_\xd9~1f\x84\xa6v\xbdV\xbb5\r\x89\x10\xf3-V\r\x9b\xdc0\x1d\x8f\x18\xc1 \x17)_D\xf1{\xbd\xf3Գb1\x1b\x19\x96#Q|\xe6\x83k\x9e9=\xad?\x87\xf7\xe4Po\x99\xc1\x9ec\xd6s\xbb\x1f\x1f\x83$&\xf1\x16\x9d}\xd3BoWT\x87\xe2\"M\xc2\f\xa7\xbc=\xa0Dy$,I\x9c\xd7\bN\x01,چ\xb1\tw\x99\x03I\xcdx\xfbE\x8d\x8f\x11\xa76\x90\xbdx\xe0n\xa1C\xd4C\x1f-\xa1\xf8\x1c\x99,\x9dϕ\xd2\xda̲Y\r:\xddy\xa5~\xb1\xccʝ\xcb\x17،\xa8\x8e=Y\xa2\a\xc3\xe2\x9ec\xcf,Txe\xa1qU\xa2k\xe7\xe0\xdd*O\xeb\xe6Tq\xf4\\\xb1E\x1c\xd8\a\xac\x80*\x84\xe2/\x00ؒ/\x89\xaaNS\xe4\u007fU\x1ef:\xec\xf5\x89\x96b\x8d\xfc?\xd5ī\xa7H\xd2t\x03$ٶUfu\x87\x86dH\"\x85\x1a\xa4$\xb62kQ\f\xcc/\x8b\xad\xcfW\x17iX\xfb\xfe\xcd\x1aN\x1b\xee\xb6\xcex\r\x1c\xb0r6\xfd\x9c\xba_y{?2\xc2\x17ڽ\xcd\xf3C~{\x93\xee\xdau\xd58\xe5\x99\x1b|\x86\x0e܁\x1c\xb9Sf\x95\xe9+\xe3\xa2\xef{\x06\x96\xea3\x17\x980`\xbbw\x17bcC\xf3\xd5\x0f\x91Q\xd8\xf4+zƪ\\T\x9f\u007f-\x0f\x1c\xe9\x1f{\xf8]\xde\x02\xa3ξ6\xd5Ѯ\xc2c\x91?\xc28\x96Z~|\x82&\xc4e\x13\xf3\x1c\xaeD\x9d\x969qW\x932R,Y+\x96\xbd\x13\xb8y<`Ow\xefA\x9abz6|\xb6]\xdc:q\xa7\xe4Z\xdfO\x17\xf7V\xd6gM\xf1\xd2̥ic\xcckJ\xcb0\x05\xc0=,\x9e\xfa\x89\xf2\xcc\xd24\xda,am\"\xd3\x1d\x88\x1a\xa6\xf4RC#\xf8\xdb,c\xe1\ff\xa2\xac\x1a\xcaZ\x1e6RcG\xbdŢ:\xba)\x11\x1fe\x8c\t\t\xfd\x9a\xc2eI\x17\xbd\x16\x1b\xddr\x0f6.\xea\x10\xf4Z;\x97\xcdP\xb0+O\xd3)\x88\xd3$\x16\\\xc1wI\xa2V\xec\xc2(h\xef\xf6`z\xb4{%\xcffp\xba\xfbxl\t}\xe8\xa5\x1ao\x9f\xd1n\x1br\r\xb1\x957\x9a%ӧ\xff\x1c\xb8{\x9e\x1f\xaf\r\x9b\x13\xe1x\x03\xaam\xa1\x1d\xa7\x06\xbd1oВ\xb3\xf4i\x83\xf1q\x13\xb0\xe4 \x12J\xd6\xca\xdcO\x9a\xaf'V!\x89\x99\"\xb7\x12\xb0=\x89$\x15\n\rї4\x84\xc2\xf8KS\xba+\xea\x91\xc2\xca&Z\xdaۙ\x83\x91'\xa4憥Y\x8e\x0e\xe0\xd0^\xdb\x16\xb7\x05e\xbe\x05\x02\xcc\xe6~\xff\xff\xf7}\xe2\x96,\x85\xc2x'\"s\xa3o߮d\xb1\xc7\xfd\xb1\x1f\xa3\u07fd}{.\b\xe7k\xe8\xc8\xc8TJY;ff\xea\x96\uf14e\xd7j\xa7KV\x92\xb8\x1c\xbcB\xef+\xd1\xf6j\xc5\xdc\x01\x1dqM\xaeWL\xaf\"\x9b\x1be\xf5/\x9d\u05f6\xbb\u07fbYf\x99\xfd\x8c\xf4xw\xa2I\xf5\xf2:k\xeb\x91I\xeb\xe8q.\x86\x87Dz\b\x9cdLWim\xee\xfc\xb8\xb3]\x1e\x00ɗ\xf5\xc2\xc7\xfb]\rf\xcf\xe2\xb8)\x82B\xe1\xea{l\xb2ֻ\xb7\xc1\x1d`\ue331\xcaj\xd6~\xa3ކ\xde\xe9\xaf;ā;~\xad7\xb1\xc5-zA\xc1\xef\xd8\xd7X\xc1'\xac\xce\x0etb\x9f\x8d\xd8\x1c\x83WO\xd5.\x98\xcb\x1f$\x00\xf4\x06GS0R\xc9\xe4\x13\x11a\xa1\x11#\xe5Q\xb8\xde\xfe\b\xfdP\xca\x1dO\xc9|\xdaP[\xaa\x9b\f\x86\xe3\xf9%`C\x12)c\xff\x9a\xc5\xc0\"\x17\xd6ͽdD1\xca\u007fxp_s*5\xc5ac<\x9bv\x1f\xfa\xc8P\v\x1f\xdb\xecc\x9bq`{D8\x86Shv\x10\x92\xec\x90i \xfb\xfa\xceW\x03\xd9\t\xa7\xf3w\xfapk\xee\xe0\xe6R\x12|\x18\xf6\xbd\x1aO\x9a2/n\xd0@\x926M\xe1\xb2\x00\xcdR\xe8իB|\xa9\x10\x98\\\x15Un\xa1\xa4\v^\xc3l\xafs\xdd\xc2\x05\xb4=\x10[{\xac\x97\x1e\xa5A\x03\xae\x05?\xb2\xf1\fzJ_\x10R6\x02\x04\xad\xfeSA\x83\xe5\xbf\xe3\t\xbf\x8c\xfa\x8f\xa0\xb5\xfco\x98\xa8\xffwn\xb6\x96\xfb~\xe1\xe1\x9eGK\x0f+\xf7(uhK\xb97\xd9\x03\x01\xfa\xe1\x14,\xb9\a\x06\x0f\xce\x16\xe7H\x81\f\xff⺔\xc7\xf9\xc8\x11\x87Q\xb8\xdb/\xb0\x9a,\xbf\xa7\xbfZ\x8b\xf4y\x92(NZ\xe8\xfd\x8c\xf6y\n\x88\x8b\xfb\xbaɧ\xb5\xb3\xe6\xf6e+u\xceh\xadC\xbe<\xc6/\xef,s\twy\xa8\xbf#\xf1j\xd7\xd8I\xe7\xf0\xc0\xa6诵\x9f{\xf1Ҏ\x12\xfe\xb4\xfa\xc9,ٿ\xf2%\ue943\xce`\x05S\"[;\xb4\xdd\xfd_~`\x1b!>\xec]\xfa\u070e\x13*\xce\xdat]8J\x99u\x1b\u05f7\x0f\xcduO\xc1\r\x89\xd5\x0eաH>\x88\x8a\bh\xefLkq7g\xe2\x12\xb8R2\x16\xf6,ʪ\x91\xba\x18Z]\xc6|\xa0\x90$\xacCZ\xa5\xac\xe4m\r\xb6\xd6\xee\xf4\xad\xc3\xf2q\xa2\x17\x03X\x01\xa7\x81\t\x9cLrS\xf9\x8f\xdfKb\x1f\x9f\xcc홞\xfe\x97\x12\xd3%H\xbe\x89\x85/\xba\xce\xcc\x1aw\x8d>\x0fG\x9b9\xc2(|\xf2v\xedv\x0f\xf3\xa0NnNvX\rN\nЀ`p\xbb\xd2\xc7\x0e\xc3\x19\xd1+\x03\xc9{(\xa4\xbbu\x03\\\x1f\x9c s\x04\x8c\xbbQ\xc8\xfa\xb3p\v\x87\x0eݨ3\xb9\x99q\xc5\\\x92\xf6͟\x9c\xe8$\x12\x19\xd1ﵧ\x8a;Q\xd8Sřz\xc1\x0e\x89[jl\t\x8a6n\x98 \x068\x85DT\xe4\x1b}\xb5\xe9\xb9㔨\xf6P\x8aE\x02\t%\x81\xbaBW\xf0\xfe\xafح\x16\x14\x8eY\xab\x1aw\x17\x85\xb7.\xc0\xed\x1d\xd1\xe2\xb4\xe5\x89!\xa1\x9c\xbd\xa7/\x14^\xb2mdSZ~j=\xb8*Qgd\xfd⨎\xd10t\xc3\xc6\x1c\xb1]\x86\x9f\x05\x05\xa2\x81\xc3q\x16\xc1-\xee.P\xa7JBp\x96\xea1\t\xe0ث\xe0\xc4at\xffl\x89/\xfa\x83\xf1y\xf2p\xd7\xf9q\xc6{~\xc7\xd1\xf8TOH\xd3\x05\x8c\xa66\xf7\x04\xd7\xfb\xb4\x1d\tu\x85N\xa2\xff\xa3wY\xb9|\xc3\xf6\nA\x98Vr\xcf\xecwD\bh4Kk\x96\x16\xa2\xf1\xc1+\r\xe1/\xbe@\r@\xd5\xc6O\x1e\x9c\xfb\a\xfd\x19\x94\xbeJ\xfc\xec\x01ZB1[\x87?l{\xf9JՊ\xfc\xa3\xad\x1bq\xa49Pv\xado\x00Y6\xc7CJ\xb0\x82\xba\xb8\x83\xf7\xa9\xfd\xcc\x0e\xd2\xc9\xe7$\xb5\xb7\x94H`7\x06Ei\x8d\xaf\xa8)*eK\xc1\xa3\u0602Y\b8\u007f\xa9\x97{V\xbb\xa2\xab)b\xa7\xd0\fpNv/A\xd9%\xe5\x82;\xddu\x1dh\x87(w̃\xbcl}\xa2*\xd14\xcby|uV:\a&\xe0*P;L\xf1\x18Q\xee\x99\xf3\xf3g*}O\xbe\xcdW;\x13xT\xbf!\xb8\xba\xd8\xf6F\x82[\f\xa5\xf9\xado\xe9\rl\x95\x88\xbe*\xfa\x1a\xb0\xa7\xb4\xc0K\x06\x01\x95\x84K\x87\xe2Uv\xb6ܼƌ٫NY4\x9b$Gd+\x843\x95$K\xc0VZ\xd1\x18\xbe\x0e\xb8F&\x11FuR\xf6\xa5j.GN\x9b\xacۖ\xca5ƴ\xca\bre\x19\x13vv\x16\x9f\x19v\xa5\xfc\xfa\x05Ȭ2M\xfa\xeaC[\xcc)\xcf\x18|\xc8\xdf\x01eGyb\x10\x18\xa7{\xf8)ڻ\x03\x8e\xbd\x90.\x15I{l\xda1\xa7\xa6\xfc\xa0C\xc0\x06\x97e\x85sZ\xe8t\x11\x8d\xc3h\xd1\xc6ɻ\x91Ræ\x01Gp\xc6\xc3\x157?\xbd\xb8(\xa7d\xb1\xc6W\x84^=\xb7\r\b\n\xa0\xc4\xd9&\xf5f\xf0V\x03\xbb\xf1͞\a\xb7iϟ\x12\\\x1b\xb4\x87\x91G\x17\xce\xf5\x9a6$\xde\x05\xb0$\x92\xb8uP=\ao\xe7u87\xbf\xd4\x1e\xbd\xec\x9d[\x9e%>`<\x15\x0e\x9e.\xf7\xcb$\xc7Mtӗ\xb6B)G\xaajS\xaeQ\xe3\xe6\xc6Ud\xfc`\x8e\xe8S\xb6\"\xb8\xa7\x1f3\xb7\x99\x1dɽ\x85}Mױ\xb3T\vth?\xf4\x177\x9f\xb1\x06\xed]\x9b\xe1\xd0\xf7\x84\xf2\x97i\xa2EH\xe5\x15\x89\x9fzş\xfd\xe5|\x15\xa7-\x9f\xc1\x19\x14\xd5td\x86\xa7\xbfۑ,\xfd:\xcbD\xcf\a\x9a\x1b\x92\xa9\x16\xd0j7l\xc1\xdd\x04D\x006٧\x17-\xfc\x86\x8f\x02\xb7\xd4\xc1+\xa7}ZU4\x9f^\xae\xe7xO\xb5ݼ\x9d\x9ff\xc5\xfc\xd8Q\x1eH\xf8\x1b\x14\x10\v\x8d\xc2\xeaU;\"I{\xf7)\x91\xdc1\x85\x04\x8dZ\xc0\xb0\xf8\x1a.\xf5\xd8\x17\xc5\a\xe1\x94\x12@\xf3\x88\x9b2\U000c45a9b\x03+q\xbaz\xf3V\xf0\x9b\v\x81s^\xc6>\x9f\x1f\x1e\xaf\x04\x02V[ŵ\xa5\xef\xc5-\x1f\x185\xcev\xbe\x80\xa1\xb4\xf1]蚮\x96\x97\xdac\xa6\xfb\"\xfc\x8d\"f\x88\xf9\xc4\\\xa5߬\xaf\xe3\x9c<\x8cۋcy\x1e\xad\x98#\xb6\xc5Qj\x9f6dr\u007f#\x01\xa7ȑ\xb3\x82\xde\x14J\xed\xcb4l\x12\x1a\xf2O\x16\x06\xee\xdf\xc6(y\x0e\x87\x16\xefN\xf5\xcd}$m\x8e\f[\x9a\x04-\xcb|\xf3\x93Ԉ*\xfd\x11\x1d\x94S\xf1\x8a\\\xf7ќ\x8d\xfe臉@\x12\xff\v\xcb@\n\xdd\xe0\xa4\b\xa8ie'\x9am\x82\x9f'q$\x9d\xb4\x12s'B\x03\x9a\u007f\x81\xc6\u0a7bA\xa9\xb9d\xf3)\xf6\xf0.\x06\x88*\t\xf9_y\xb6\x8e#z_\x17\x19Ы_\xee\x0f\xcf\xf1\xf4{\xbd\x13\xea_a\xac_=+䊒ӌϞ'P\xf4ܺw\rG\xd4J\xee\xd6l.\x8b\xba\xfdr\xa8q\xfbZ\xc8v\x1fD(\x9dDC\x19\x18G\x8f&\xe3C\xe9ر\xc3!\x11\xa1\xf2\x93\xaf=\x92ǣz4\x85\x82\x8av(\xa3$;\x03\xbc{\x06\x88\x1b2\x1a\x14\x14 @\x8fiǘ\xfcu\xdf\xee\apc\xd2E\xc3\x14\xec\n\x1a\thh\x00\ts\xe4\xcf>\r\x13\x81\xd6L\xb6^\xeb\xa2f\xefڻw\xbe\rTWޟ\xb6\xff\aR\xd9\r\xcc/_\xb9I\x1e\xaaĦ\xc4M'B\u007f.\x9e\xb4\xd8,P\x9a-\xe8\xfaH\xcaj)\xfd\xfe%P\u007f\xf9\xbd\xbe\xf4Dp2\xdb\xc8^\xed^w\x8d`K֫\x81K\xe8\x03Pa>ξ\ufae5jϨg\xea\xf8)\xfdKS\xfc\xd3ټ\x12\xeedGFYG\xcc$\x93\x15\xaa\x95\x15\xf8X`\x88\f7%\x92Ҁc\xb2K\x91\xdaQ\x16O\xb9\x1b\xc1\x8f\x81\"Bա\x1bB\x95'\xab\xe8\xb6^\x10.\xeb`\"\xf0\x86;\xcaG\u007f\xa2\x06\xd3\xff\x80\xc8leԒ\xadO^l\x89\x83:\x99Q\x19\xa1>\xec45e\x1b\x16\xf8\x1a=[7$z\xbd\xa7\x05\x83\xb4\u007f\f\xe1i\xbf\xe5F\xf0\\*B\xf4\x0e\x14'ǝ\xc6A\x96\f\x05ko\xde\x02\xb8\x90\xe7MFc\xbc\xc0\xdd\x10\xbe\x84\x85\xa7\x02\x173|\x80Ӭ%v\xf1\xa2>!\xd2\x1c\xb4\xaf]\xd8\u0080\xa5\x9f\xd8\xf6\x89'!\t\xf0\x1e\xef}:xi\x89\x17/\xeaxcR\xb1^\x01W\xa5\x8bI\xab\xf6\x86\xb6\xdf\xe1C\xfa\uf6e6\xdfz\xe4\xf3_`~c\xfe\xa2\x9aV\xa6\xefFvf\x8f]5On\x14\xfb\xacC\x82\xf2?\xc5\xddҷ\xba7\xac9\xa1\x9f']\xa6/g}\xa1\xe7\x82փi\x04\x81\xdeUIȃ\xa9\xaeO\x92t\x16\xda\xf0\xbe\xad̒\x06\xc2?\xcd\xd5k\x8c\xe7\xe7\x17\x02:\xd2\xc8\xd5\xd0[\xf9\xdc>TSi\xc3\xf4\xa1\x10\xa0\x04\x98\x9b\x9c\x1cE<7\xf7\x1aE-\xefN\tؐw;\xe7mD\b\x8d\xafu\xd6\xc7\xe4[\xc5\x1d\xea\xca\xc5\xd3\x06z\xc4+9\xaa\xc9g_P\x1aO$\x1f\xde\xcbUYN\x94\x81[\xbb#j\xad\xa2\xdc\xfb\x0fI&\xf5\xc3\xd33\x96\\e4n\x85\xcf\xd7\x11\x85)\x1dRvcx\xeb/\xf4V\xd2C\xc4?\xddK\xf5\x87\x9d\x89\x9bg{\x1fG\xb9\xfaX\xf9\x92\xb2\xb6\"b\x17\xac\xe3(\xe36\xce\v\xbcʛ\xbd|\xba\xa9\xf6\xf2\tR\xf0r\xd1I\x9c\xc9\xe0&\xc0-Nձ\xdc\xcf\xf9*\xa7?\x8e\x862BpEYP\v\xd1\x17[\x00\xa4\xdd.\xff\xa0\x85r?\xfdgO\xa3\x01h\x92\xbf/%l\xe4\xaf\xfdRO\xb8\x13E\xbc\r\xbaf\x1d N=d&\xfeu_qb\xc0?\fX°\x82\xdc\x13f\x04:\xd8\xccJ/\xac\v\x93}?(u\x8b6\xbe\x8b\xa3\xcfP\x98\"\xf8\xb3L~\xd7iV-\xdfg1\xed\xe8YB\x1cg\x82\x06\t\x14\x98\x1c\xdc\x18\x14\xfc\f\xfe\xec\xa4}\x17H\xa4K2\xa04\x05鵖r)\b\xa9ۡ\xc8#|ti\b\xeb@@\xa3\x1d\x86J\xe6R\x18[\xc5\x19\xc4k\rx\xa6\x93\xc9\x0f\xd8c\x02\x03E^\xf1\xe0\xec\x0e\xf2I2߸\xb0dVo\x95qP\xcd\x1f\x87\xb9kZa2\xdb\xd7H\x82/\x8e\x1b=(\xb8c[lW%i\xd6\x1b\xb8\x1f\xa3\xb7cX\x00\x82c\x88\x0f\xc1\xa3hP\xc6q\xb7\xd3\xe96\x89\x12\x19c\xfcM\xf2?\xbe\v}\x1fiSh\x87Rm\xd0\xe8]\x1e\xf9\xd0\x156;\xf4\xa8\x9f\x96\x8d\xda?'\xaf\xac\xf2\x04\x83B}g\xc5\xd9M\xabm\xf4\xeeǞ\xeb\xec\xcbCj,v\xb4\x9c\xcfԱ\xaf\xa0>\x89\xfa\xa7\x0f\x97G\xf0\xc0\x16\u007f\x92+zYl?G\xe8ܦ*{\x82\xb1\x12.\xecm7\xe4A\xc7T\xaa^1D\xe5\"\xa5;R\x8eUr\xf0\xa0\x10\x84\"bh\xf8\xa6\x0elqw$\x92\xb1\xd4/gy\xbeR\xbfmZp\x87%\x14\x8b0B\xce\x15ϝ#4\xffb\xc1\xe8\xe8\\q0n\xed\b\t\xeeN]M\x89<\xbeq\xeb\x88\xceN\x97\xd4\xf5{Ԉ\x86\xcdh\xcc@\xfe\xfc1?\xbb\xdb~\x8bt\xf9\xf2\xc0\xea\xc26͜\xd8\xda\xc1T\x9d\xb8k\xa7\x8e\xd5̆\x0f\x1eҙ\x19\x0f҇\xfb\\M\b\x00\xe5|\xc0t \x10\xd35O<4> J\x0e\xe7}\xbe\xde\x19,\xffQ\x1drQ*ͯ\xf6\x9bA\\\x15'\xf5)y\x05z\xd4'\x86\x1d\x13Kdخ\x06D\x8d\xf6Wdi\xbc@gzu'1\\\x15}\xbb^q\xc1\xe7\xcfI<\x06>e^\xd6h)\xc8Q*\x1e\xb9\xf4\x14lz\xad\u007fB\x80l?\vg\xdc\xf9\xb2\x01\xd4\xf7\x8a\x8b\xca\x03\xcdG\xd6\xeeZ\x9b\x1a\x1a\x82\xbe0`\x12\xb3\a\xe5~\xfb\xdd\a\xea\x939\xa3\xf7/ie+U\xb6r\xaf\x1fW\x97\xe9\xd1Ws6\n\x94g\xed*\x9dD}\xecz\x81yn+ህwUӋ։\xeb\xcdf\xa9\x14\x0fG\xbf\x03%!\xa9\xbb\x88L[#\xfe\x83\"\xd1h2\x99fmh\xff\xd2|Fqb}*\x95H\x88\b\xa9#z\x9c\xb4\xb1\x1fnV˴\x80\x99]\xf6xA \x981\x8d\xae\xa2\xa5m\x01\xb7\xa9\x1fk\xb1\n\tׂV\x12\x10|=\b\xc4@\xbb=\x85\xc1OB\a\xb0z\xc6P\xbcd\xf3\xc0\xc95Vrl$\x00\xbd\xa1\xd1ZՄ8\x90\xbb\x83\xb48^Ϗ\x98qp(:A6J5PY2\t\tèV\x1e\x99\xb5\x0e'G\x94\x89\xce\xccpe\xe6\u176d\\\xb6\xaahj\x93\x16\x1f\x1d\x0e\xa2\xd2p\xa11a\x84\x8e\xcaw\xc5ʓS\xb9A\x03\b$\x13\xd3|\xbdH\xc1\xf5E#7ч\xd5\xd2\xe0\xb4\xdc|\xfe\xd0p\xb2\xde\x1c*\xea\xca\xc4\n\x9b\a`\xe5D]Z\xf3\x94\x8cB-\x92\x80\\6\xcb\x13iW\x0fẍG\x8d\x04\xfa\x90\xfa\xfe\xef\x0eGG\x92\x10\xa0\u05ee~\x8dY\xbaJ\xa9\xbeT7Mq^\xc2\xe8\xba#\x820\x81\xa7\xe4\xd8õq\x87\xbe\x04\x1a\xf3\xd7\xcb\xeab\x8b0\x9aKVot\xf1[\r\x8a\x19Ֆm\x11\x0e^\xe7k \x17k\xb4\xba-d\xcbp\xdaݟ\u007f\xff\xaf^\fJ\xf4\xddd\xf63\xa2\xc7ݕF\x1a\x13\x8fF\xcfT\xe6Ϻۗ\x9d9o\x93\\S\xe3\x028\xe7\x03\x19\xd1qk\x10\xea\"\x81\x02σxL_:\xaf\xf8\x1cP\x9c\x8aLh\xc0\xa50!\xdc\xdeiˌ\x0e\xd4\x17{\xe8\xe88\x1b\xb5:\xb9\x9e\xf3zE\r\x04 \x18\xaeOy\xfa\xab\x8b/И\xe0l\r,)\xf3\xb4G\xbe\x86\xf2\xe7\x8d\xc5q\xce\xf2Q\xb6\x14\x98\x1bR\x19\xf3\x0e`\x81\xb0\\\x15\vJ\xf9>[\x8b\x1b\x00\x94\xa6\xa1ip&Հ@\xa1\xac\xf1\xad\x1a\xae\xb1\r\xae\xa9\x00$\xaf\x89\x05:\xc1\x10Q8\xb2\xa2\xa0Bt:@`{>\xbc\xa7\x85\x16'\xfba\xe7ޝu9\a\xe7\xe9\xfe\xf79\x10\xf0\x9e'\xa0\x01\b\xa9L\x1e\x12\xf9cи\xcađHh\x91\xf4d͞\xf2\x87\xeb\xe1YG\x8ff\x99\xa9\x01\x04\xb6\xab\xc1\x12\xd6\xdf/\x9f\tN\xe6\x02=\xf0\xf8Sf\xbb0T\xab;WJ&\xc3 \xc6I\x9c\v2\xb8\xb4\xf2\xfa\x02\xec31\x91\x00\xdbkÉr`\xc8\xd4}\xb2\x92A̶\xae\xfc\x99\xbe\xab\x13\x81\x83\xd4\xfc\xebd\b\x84\xbc\x94@\x1d\f\\q-\x10\x9e9(\xd6B\xec\xac,v\x11ѣ\xad\x12ALX\xc2q\xaaH[\xa9!\xc9f\xe4\x85-t|\xf8\xef\x9f\xd9\x04\x89n\xb9PΤR\x03^\xb0b\xc2\xec\xd5\xf8\xc3GO\x9ff\x85\x00=+\xa5\x8c\xa4\xe5h\xfe\xb4\xb0W\xf0D;Kf\xdex1\x82\xc8^\x17\vU\xab]\x923\xa0@j\xfcK8{V\xdb. \"k5\x02\x81\x0f\x1d\x11\xb0\xd1\xfeh\xa5G¾\xb5pC鹒\xb3*\xf96\x04\x06i\xaa\xd3S+п\xb8u4495\xeadj\x90+\f\x86\x9dKk\xb9\xd2Nq\xe9B\xa5\x19\x02\x05\x94M\xf0\x88\x13\x0e++?{\a\xc62\x13M\x83\x9bNJ\u007fV\xf1u\x10\xfc90\xd1$#dV\x9c/\xd5,)\x91\xcf\rAk0\x94Ƃ^\x1b\x8c\x87\x81\xf9F\x1c\x94ߛ\xcd\x05\xc0\xdc\xdcn\xb1\x02\x8b\xf7\xfb\xba\x94<%\xa2\x11\x9cJ\xad\xc0\x9c\xf7\x8cvq\x00$\x9c\x9b\xea\x1e\x9f\xc9\xe8\xafd\t@\xe4ww\xf5\xb8?\x9d\x04\xe5R\xc0\xfd\x18s\x90\nD1\xabF\x13-\xa0_\xf1E1}\xfdzc\xe3\x91\x16ƝZ\x8c\x19h\xd0\xf4[\xdc\x11\x1e\a\x94\xc6\xcf$\xc3\xfd\x9d&\x05\x00DWx\x18&fe\xc5%\xe9\xed ~)\t~\x8e\x12\x83XL\xb7t˛\xdd҅\x96\x8eJ\x06K\xdd//(\x97F[\f\x98KY=;\xca\x1f\xcaؕb\xff\xfa\x97\x83~$Vd\xb8]\x9a\xa28\xda\xdc|\xd4\xf7\x1a\x02\x81bJ\xd3\x16):v \xff\xfa\xa3\x183R\x86R\x97Q\xb4\x8f\x04}˺\xe4\u007fO\xed\f\xd6\tk\x06\xc5UP\xc4\xc1\x8b}\xb3\x9fSV\x95\xaf\xfd\f\xcc\u007fx\u007fs\x00Q\xcaro\xaf\xb1\x9f3\x1e\xa3\xffz\xe7\x902\x89F\x10\xa4\x8c\xd2\xfa'֯\xa3\xd8\xddnN?\xf0\x1e\xd7{\"]\xf51\x16B+\x1f\xc4յ\xa5\r\xe3\xb0;*\xab\n\x8a\xed\xd1eO]\xc2\xdd\xd6-\xce\xd2N~\xb5\xbf\xf82\xf5̜\xf2\xa3u%l\xc5(Z\xbe\xad\xbb\xa3\x9db\u007f\xa19M\x99h]Z\x1f\x0e3')\xa2\x149\xa0#\x87>\xcc*\xd7\x03\xe2\xa7\xfb%\xfb)\xb7V`\x10leY\x17\xee.5*\xd0\x0f\xd9\x0f\xa5D~\xea-\f\x89\xf6\ad5J\xe1\xc6Z\xf5!Q\x03\xb5\xb9Ӧ\xa7^f\x01P\x80\xa3/fj\xbe\v\x81T\xcaX\x91\x12\xa2\x04X&(f!\b\x88Ý^\x13\xf2\x98g/j<\t\xb3/\xda\xc7륃S'J֓5\xe1V^\t\xfe\x95\xfaߟ\xbf\x9e^\xc4\x19m\xbc{\xa0\x8f\x062\xbe\xac;\xa2\xa5\r0i7\x04$\x01\xe0\x0f\a\x16&⩵\xfeӵ\x8e\x8d\x8d\xab\x8fXEOS\xe8\x1f\xc0x\xc65\x0e\x1eDZ\xbdيt\"\x8e\x15h\xaa\x11\x88v\xe7\xaf_C\xda\x16\x83\xe5S\x95\x9b\xbd~A$\xba<\x86@\v\xd1\x01\xbc\xe5\x1ef\x8a\\;S\xcca\x8c)\x9a\xa66C\xd1\xd1_\x9d\xde\xdfΊ\fg0(4i-k\xc2\x13<\x05\n#5t\x8b\\CC\xa3\xab\x19h\xf5>\f;\x8f!`\xb6\b\x90\xa9\xa8\v 3\xaa\xf3-\xd7\x00\x056\x95ht\x0f\x89D]\x1b\xe9S\xb0eN\x87\xa8\xea\xeb\r\x8d}\x83}\x8d\x8d\x8b\xa8\xe6\"\xad\xde\xce\xcf\x13#Qn\x93\xb7\xb2\x16\xba`F:\x9f\xc3\x19\x10\x04>\x15\xa179$lV\xda\xcce~\xcc\xcb\xc7̈\x16J\x10a\xfa%\x93\x89q~\xd6ܣ\xb3˴\xaf\xa7^\x0fl\x87C\xb1\xf4\xb3\x03\rf+/\x0e\xae\v\xb9\xfe\xe1\xb4eBa\xbb\xe8\x13<\xed\xba'\xb4 \\*\x00F\xf3\x99C\xdb;\xad\x8d|\x1c\x84c\r\xb7\x86ڀ\x98N\xba\u007f\xf6f\xbe!\xe0\xff\xf9L2i~\x81<[\r\xc5\xd8\xc5\xedp\xeb\x84\b&\x9aѕA\xbekn\xeen\xba\x90r\xbe틧\xfd\xec\xe9\x1bn&\xbbf\x17\u007fv\x1cnjn\x94-\xcd\xe82\x1f\xdc5(!\xec\xd1\xf2\xa2\xf4\xd5\xdd\xc4rC~\x87\xe4\x8aD\x04\xb2\x97\xcd\"`\\T\x9f'j\t\xbe\xccP`\x920i\x1a\xdcO͚\xe7\x9dF\xeckrf\xeduə\xf7\xa2کj\\'\xaf\x1e3\x83!B\xbaIEl\xdfQ?\xa6\xf3m12\xc4pQ\xf5\xa5\xa5\xe2e\x8b>\x96\xe1R\xc7w\xe7تD\xe7.ۋ\xd0\xde\xe4\rXN#\xb1'N\xa2\xa4\xcajj\x01\xa2\x91о4\x17\xd5!\x06\x99\xb1tK_\xbd\xe2\x93\xcbf\xa5R\x80\xc0!@棼C\x12\x94J-\xa8\x12ja\xc9\x1eH*\xf6\xcd\f\xe3\xfb\x8d\x81\x9dN\xee\xcbp\xb4@w\x97V\xb4[;\xbb\xdd\r\xdd\xea➄s\xecq\xc2\xe5\xd1H\x8a\xa4l\x81\xb6ڜA\xbb?\xd4\xfey\xad\t\"\xbaj\xfd!\x80\xe4\x84\xd6<\u007f\xdcU\xb4?\xddh\xbd\xe5\xc0\xe5\u007f\xa6k\xe1\xa71\xb1\xa6oa\u07bb\xf8\xdb\xd6e\xe9\xfd8S\x80\x9c1\xf7Н䋄\xb6\x04\x8c!\xd3\xf3\xba\xe29\x93h\x85\xd8I\r\x18\x87\xd6B\x8e\xeb\n\a\x119K\xabo_(\x00[\x01f\x190\xb7\xb8\x88o!\xfc\v\x85\x92\xf931\x1d\x9eC\xb7\xbe\xc1;X\x0e\x96Ih$\xa5ɀ禹@\x84\xc5@0Wl\r\x1f\xdd\x11]\x86&)s6\xf0\xe0\xa84w\xf1\xa4Y\x903c.\xfc\xe3M\x02g\v^\xbc\x14\xc81\xd2\xc7\xe9\xb9O\xb3qs#Ms\xf1\x823ZNLMi\xf6}\xf0\xf0\xc6\r\xa19\x8d\u007fU\x82~\x87\xe8\xb3x~{\x16\xae$6\xba\b\x9c\xa8\x03F\xd5ɬQ\xafEi\xee2Wv\x86Y\x14F\xa6\fA\xdb\xe7\x9eV\x10l\xa8\v\x14\xb8\x06\xed\xd6\xe4\x04VDXer\xe2(\xb4\xc0\xb0Z\xbae\x9e\x92\xebͰ\x90\x163)\xdb\xca\\t\x00\x1a\x8a\xf95\\^\xe1\"r\xf2\x19Ш\xe7s\xb3\n\xdcw\xee\x1dP\xe45\x8e\xaaf7\xa1N\xdfK$f\xb3\xc8^q{\xb0\"L\x8d\x9d\xdc]\xaf\x88\x19z`@\xf8\x95DQh\x97\xcc\x04\xe66f\xb2\x9d\x16\x95\x1c~h\xabG\xa95\xc6uU\x047G\xe4\xf0\xed\xeb\xb8\xc4\x15~\xf7\n\xc1\xb8\xe3\xf5.\x88#3\xf1P\x13\v\x8e\xfaTV\xca!\xbc\x1fn\u007f\xac\xaf\xefژ\x05Pf6\xa0Չ>l\xdb6\t9@\xddҖ\xf7\xa6\x99\x1e\x8f\xa5\x02\xe05Ϛ62\xf2\xf9t@7\n\x9e\xe1L\x8e\xce2\t\x1d\xf6\xd7\x17 t\xfc\xf5\xed'ԯ\xc0bH\xca\xe4\xefԼ\x01\x88w\x12\xcb\xe6Wf\xf2\xf1\xb7Ɋ7=\xcc\xdb\xfc.=bx\r%\x05d?\r\xba\u007f\xc1\xee\x8da\xb3\xca\xcb \x929\xe0e\xffp\x90\xa7\x8b\xbdH\x8fҩ\fK\xc8\xe5\xf7\\\xf0\x90\xc5ۏ\xfb\x9d\x84\x9e\x84\x8c$\xa0\xb0\x98\xe3\x9bC%\x960\xa8\x96\x1c\xc1\xe6\r\xc9\xc6\xca\x05\xe6\x83\x01\x9d\xddntv\xa3\xbc:\x80\xb5M\xc8`᳑B\x84\x8d\xdbasp\x93&\v)\x02\"-\x12qc\x83\xa3\xaa\t\x9b\x93@\xa9I\xe2\xc7\xe8\xf3bk\xdc\xd9\x14\xb9\x9d\xa9\xcc\x053eP\x9c\x16F8\xdd\x01\x89ZmUL(\xd9\x11(qP05\xbf\x19n\x19'\xbc\xa5\xc1C\xf8\xc7\xc2V\x89\xb5\x8ai\xc0\xb5\xaa\x9b\xda\x12\x93\xa1\x8ej\x95\xd0\xf0ɿ\x04X?q\xe9g^:ӛ\xc0[[P\xb0V8\xa9\x9c\x19\xb2\v\xa1\x9f6\xa4\x00\xda=Iɉ(\b\xb5c\x06\xcdG\x96\x9a\x15\xdb@\xa9\x15\x17\xbd\xe0Lb!l\xb7l\x05\xdc\xc68߬Mv\xda\xf9\xfa\x9dvVb\xf5q\xdf~\x15\xdc\xd2\x12/\xa4\xda\xcd%\xc7Ii\x1f\x88\x85\xc0\xb6҂ϡ֣T\xf3\x9d=\xfa!B\xb3\x83\x04P\x06S\x06:\xa6m\x9du\xacv\x8b\xd0\x04\x05P\x04\x9f\xc8s\xcfϥ\xef;\xa7\xbf\x17\xa6\xcfZ\x04|s,\x16G\x85\x0f\xcb:\xe0\xc6pH\xf6\x8a\xafg\xd9\xe9V\x15u\x80\xa3\x17Z\bR>f\xe6\xcc@\x9d\xe2\x00e\x14⋮@F\xc3<6\xe3Ͳ\xe0.\x1d\x05\x93\xbaL\x81\r\xd6\x10/\x81)\x93X\x94\v\x043\"LN>\x94^\x82m\v\xd4\x14\x98w'\xd6\xc1\xe5\x15\x95\xa9>\xdb\xfa\xd4\x1b\\\xe3C<\xeb\xf1\x85C\xfdKb`\x9e(.\xf6\xeeu\xd6\xc1ְ\x9a\x81\xa5\xd6T\x9e\x18'\xc8 \x82o\xef\xd5\x06\xf3MG\xf4\x98{\x1dx\xb8$\nv\x06\xac\x1b\xfa9\xef\n\xab|\xe8\x9eF\xb0\x8d\xc9x\xcaʀa\x10@QI\xdb֧\xf3'\xed\u007f=\xcfz|Q\xf9o\xd8\xfc^B\xecf\xd3\xff\xa2,\xb3Zf\xfaW\xfa\x014\xe6\xa9#\x9d\b\a4\x93\xcey\x81I\xac\a\x95\x989#\xdb\xf45\f\x0eZڭ\x0eE\f\xa7\xd9\xe6\xc02\x1d\a\xe2\xb7p\x93'\xc6\xdb\x16B\x87\xa4~\xbb\xa5\xf6U\xb8j}\x15\x1aۣ\x10WwE\xfd`\xee\t\r\x11m\xf7'?\xe8\x16!\xac@ \x00\x80\x83C 2C\xd9\x1e\xf9\xd1\x00pc\xad\xc4\bl\x13ݻOš\xd8\x1f{(\xbeC2\x0e\xc9\xe0kC\x89\x83\xf1\xd1k\x81\xf6'\x8cU\x98\"\xae\x16\xe9C?\b\xbf\fT\xf2Q^\x90\xee\fڝ\xb8\xa4kK\xf1\xe6m\xc53\xce\xe9m\xec\xea$\xba\u06dd\x16\x81\x00\x8e\x1fͮ\xb0\xb4]\xe0\x89\xcc]9b\xf3\xb0\t\x88Jn\x12\x99)sn\x9ct_\xf2\xf2\x19\xeb_\x0fxEK\xad\x94D\x94\x06 \xa5\xbcB\t\x99$gY\x98A\xbfV>\x1fg$\x95%L\xd00L#\xee\xe3{\x1b&Ν\x98\x96Ft\x0fd\xeb\\\xc0\xa5P\x94\x13=\x9c\xd2\x1ba4\xe2\xca\r\x8f\x1f\x0f8\"\x9c<ܝ\x8a\x8bs\xfcL^^N\xdf\xdc\xf2Ec\x9c\xc7v\xb9\xac\xedH-_>\xe9\x97\xf2\xa7\xf1\u058b\xd8\xda\xf8\x02;|+\x87c\xa9\xc8!\x8b\xa9\x04\xbf\xb6\xbf\xde\xea\v8\xbe\x1fO/\xd2.规\xc1\xf7Jn\xc68\xbc&\xa8,\xec\x11\x81\x96%\xebs\xf3t\x90]6(\vk\a\x96H6\xf1\f\x89Fq#(ۉ[\x96y\x97\x8c\x8f\xa6{\xfb\xc10(\x93^\xe0\xca\vֿ\xc1b\xd6\xf8\xebף\xacŬ\x0e\x03\x83\x92\x80\xe4\x17\x14\x00\xdc\xda\v\x9d\x9d\xfd\xb4\x91&f\x86\xcezCqI\x89\xcf\x12\x10\x15\xdd<Μ$\x92\xab((h\\\xd2ED\xe9C\xd1\xf4\x1f\x01\x1d\x15\xad\xdd\x1c\xdc\xf3\xe9c_\xe8x\xf6/\xc1\x83E\x82.:\xe4\x1c\xfd\xfci^\xf8\xc6+\x8aΟ\x9e1\u007f\x18צ\xc9\xf3҂Ji4@`l\x87x\x10N\xefL$搘6\xc3\xd2T\x97\xaa\xc5\x12.\x9d\x96?\xd0\xea\x8f\xe4\x0f4\a]\f\x8dX\xa41h|}g8<1Ȥ<\v\xee@K\x02\x8d\x9a/\x16\xc7\xf5\xa2/\v\xe3\xa5\xd15\xedp\x01\xc8\u007fל\xcao\xeb\xe8\x91t\x92\xaep\x87\x10a j\xe9\xa5t\xe0bE\x91\x12\x9c\vE\xa9y\xf6\xb7&Ц4`د\x11\x89\xbd\xb5$\xd2L\x87\x04\x9d\xf9\"\xab\x85\u007f\xad\xe7\x83Jvi\xbe\f\xc1l\xee\x00j\xa3Z%=')\xbe\x968\x96\x18e\xe6\x88\x14\xc8\xe1`8\xfcT\xca\xe1\xc7\xec*\x8fM\xe78\xf5\x9b\xbb.\xac\x80\x87\xbb\x8d\xd6w\xb8~\x0f\xc9\xe2\xf5\\(H\x94t\xa4v\vr\xab\"jDo\xbdG\x10G\r\xe6\x98i\x03\xfe\xb2\x84l\x03He\x8c\x86%ia&9\xb3d\x89\xb6\xcf\x1cd>\xf3\xfc\x0e-i\r\xb7lM\x12\xee\xbeܰ\xd9\x16\xa1TA\xef\x94$\xb6\x9cVHG|\xe7\xb3\xec\n\x88\x17$\xc7\x0f\v\v\xea\xf9:\x1d\xc7\x121R\f\x15s\\\xf0Z \x14$\x91Pj\xd7ۇ\xbd\x8f]ً\xc6g\xd88`簆 \x16\xfbzߒ\xf2\xa4\xcbV\xd4X\x8f\x19\x15\xa3ݕx\xbartX/\xa0A\xd1p\xd72\xb4\x0f\b^[1~R{\xef\b뚬\x97\x19\xb2\xbcɇ\xa2:k\x0eC\x11U\x12'5n\x98\x90\x1c%\xa1'\xd7CX\x02P06G\x83ۮ\x91\xfbl[\xe9<\x96\x1bN\x83scOFeQ\xfa\xca-\x92gi$\xf3\x18RN\xe8\x13\xb2\xfdo\x197\xd2Wz\x9a\r_t\xba\xb9\"?\xeaz\x83\xf66\x8c\x97\x04\xbb\xcfy/H\x16\xa2}\xdc\x13\x1e\x92\xf1ё\x83\x02{qL\x81\x1d\x9c\xf1$\x92\xf2\r\n\xe7\x9c\xe0-\xc4\xc4\xf4a\xa1\x8f[\x8e\xfe\xf9st\v\xddnS\x8cn2\x8eğ\xe0@\xa1\u007f\x92\xee\x1aѷ\x8a\x8d\x0f\xbf\x0e\x0f\x8f\x8cxHNp\xc1\xa2\x89\xc7\xe3\xb5\xde\x10\x1e\xd22\xf1\xd0\xe3\b&\x04\xe1\xe9\v3\x03\t\xa7\xf1\x84\xf3\x91\xcd\xc0\xc6f\x8c\xf7x\xe3\x0f)\xe7\xfa\f\x11\x01WP'h\x827f\xf2>\x91\xda \x96\x02s!\xa8;\x15\xfcp\x81\xd5&Q\xfd\xb1\xb7\xcec\x0eN\x1f\x04>OgdH\xf7E\xde1u\t\x10{\x84\xcc^\xcbگ\xfcV\xe4}\xf1\xe8\xe32\xdb@\xe7J\xcaH\x05\x95S\xe1\x16\x1e\xf6\x14>!~\xf5\x16\x9bL\xe9^d\x1b\x10\t\x98\xe6r\xc0\xd25/\xe7\x1d\x90GyN\x0fW\xfe\b-\xf5`\x05\xa4\xb1\x1b\xe2\xe4ɚLJ\x03\x9e\x8b=\xa9\xd4(R\xa5V2\xc3ȏ\xecM;\xbe:\x8b-\xcf\xecA\b0<\x19Ȥ\tL\xc3\a1L~\x18.\x81\xac\x1c\xb5ܤ\x10\x89kg\xc7\xcfLinN\xf1d\x9b\x90\x8f\xf3\xbdu'\xad\xf2\xd2\xe3f]\xa1\x1e\xf1\xb5B\xfbs\x14L\xb7\xb7A\xc9\x015S\x87h\xd5K\xa3v\xe6\x9cvn-\xca_e\xbc9\x10e\xf5V\a\"m\x93\xaf\a\x89B\x12:\xefG\x03Ϋ\xbex\xd6c\xf5ZX\n\xae\xbe\xc9o\x1a\x1b\xe9\xday\xfe\xe5\xf9\x00\xf2\xc2H\x10KgT\x9c\x1c~cN\a¸\x17\xed\xe2\x00\x87OZK:\xdcb\xdcA\a\x80%9C\t]\x9d\xc3o\xf2\x15ʗ\x17\x98\xb9\xc8\xd5w\xdb1\x8d\xdd)\x1b(\xa3t\xb8\x98^\xb2?\xb1\x81u\x80Ʀ\x98\x03-\x14A\x01\x9d\xba\x8a9\xaf\x19\x8b\xa3\x00\xa7\xe99N\xd6ل\x1dL\xad\xf6\xc1\xbd#\xdaA2Yu\xda\xe9\xe1\xe1\xbd5\xc7\xc6/_\x1e\x1f=f\x12ql\x14\xca\xc7j\xf6\xc6\xe5އ\x88\xbf\x11\xbeˡ?u\xf6\xfdAr\xa9Z\x99\x9a\x16\xcd\x02\xd1]\xd3A\xebX \x14_\xd5v\xefM\x0f\xbc\x8f1V\x1c\x96\xbf&\x19P\\\xef\xea\x1d\xc56X\xa3\x932\xeb\xeb\x9dm7䥱[lҏ'\xbb\x1eA\xa9\xc9Q6R\xbb\vS\v\xedQ}\xeb딭S\x87\xece\u007f\x95\xec\xefS\x1c\\D-wLrTC]\xb9ӎorly\xbd݂X\xa5\xcd\xdbJ^fo\xee\xa3\f-\x8a\xe9\v\xf0˰\x87\x95(\x95X3\xd3R>\\\xd6#\xea\x96\t9\xe2\x16\x89VP饘QՐۑ\x1e,\x1ea\xf9e\xa4\xcf\xe4\xa6X\x9b#\xbf*\x85\xdf\xe7gV\xecTnq\xf9\x8f\xcdGL\x97(\x98\xc2Z)\xd3o\x84M\xf3\xc1i\x8e\xe5!#Z\xd1\x18\x04\xcaH\x05.\x83\xd0$\xf1\x89ɀW\xfa\xf5\xb4\xa0\xaf\\\xb0p\xa9\xb8\x15\xd0*ȶ\xf5\x8d\v\x17/\x0f\x94\x95.g\xbe\xd2y 9\x93\xefL2\x97\x81\x1ap\xa7(\xd1#Z-)i\x8e\xc1\xb8\xf3\xb5\xddj\xeb\xb4\xd2jԭ\x19=\x1f\x1a\xbc0b\x93\xf3\xf2\x1b`n\xa30\xe0a]\x9ck2\x93I)\xbaX\xedE\xdb8f\x96nD\xb1η\xbb%8\x92CS.\xdeo\xda\x15\x8bě\x18\xf6Ng\xdf'\u007fd\xddp\xad-\x9d\xd9J\x93=a\xba\x8a\xbdY\xabɹب\xa8\xfcNk\xb1Y\t\xa5\x91Ե=\x81\x9a\xd4\xc3\xe3\xf5\x17f\x85\xe7N\xa5\xac\xec\x03H\xce^\x95\xb9\x03\x9f\xce\x19\x9ff\xe3\xa8<\x96\x97\x1f\x89(|\xe2E\xd3\xe4(SL\xb5\xd7\\\xf9\x9f\x8a>\x9cu\xc24\x0fvdN\x97\xe9\xbe\xf5~\xb4HN\xf2\x00\xab[\xb1nD\xc4\xcc\xcaeh/ڈ(2\xa91\xa2he_ʔQnV=\x91C\xe4\xf6\xf0\x92\xa8\xf9H\xff\x1c\x1b\u007fE\x8d\xefg\x1bi~\xa7%\xaaB\xa5\xe315\xfe\xc6\xe0czŕ\vv\r\x81>a\xebY\x80\xf1%\xb1e\xbe&c!\xa0\x89\x15pIB\r\xcb8г]~A-l\xa164\xc31\xa5\x98\x92/\x15\xb0[\\\x12\\Z\b\fI\xf5\nT4\xd0\x1cW\xb9\xf9\xf0aa8'l\xfa\x88xRY\xac\xdfN\x92e\xfb\x00\xc6j3:\xdc\xed-\x06:G\x90\xdb6\x17\xe5\x19v\xd3\xe1ad$$`\x83M,ܔC\xf4\xf6\xbe\x04z\xf03\xb7!q\x861\x93\x98\xf7\x8f\xe0]Ӌ\xd9\x17\xdfn#x\x8e\xb5B\x0e\x8d\xca\xe7\xc6\xc0l]\xb8\xbeK\xc3^\xb7\x0ft\x0e\x95\xf4\xb9\xd6\xc2\x13_@Y\xd0\xfc\x17u\xec\x9cgS\xfa\xb5k\xae\xe7]\xd0\x02OƤ\x97&v:\xf5\x98\x1fN\x83\xdba\xfaL\x19\xd8\x11ewɋ\x9e\xf5-hY}:\x1e\xa8\xc1xi O\xb9\x05 \x95\x8ax|+^\x8bñ\xb2Cq\x01%\x84\u007f\x03\xe6\xb8]{[[\x1b\x1e\xd8q\"\x9a\t\xdcx@L\a\xd6upՔ\x1d\xd5\xc3j\xbb\xea\x83\v\v\xdc\xd6-\x01\xdd\xe8\xa3[=\xc9\u007f\x8b\xc0\xf5\x93ئ\xb2\\\f\xf1e\x89\x8bjq[\xfe%\xef\x1c\xb3^W\xa5\x87\x94\x1a\x19'\xe2Hj\xd3y\xc2c\xea\xf4%J8\x8a\x18Imx\x95\xc2\xe5=\xe8C/\xfa].&\xc1w4\xcdD\xde\xc3,Ƙ\x17\xce\x13\xca\x1c3\xf9\xb9\xea\x94\"\xb6z\x96\x14\x9f\x83`\xc5U\xa9\x90\x16\xea\xc1\r|M:\x1f3Qc!\x93_ǣ\xe5\xf1W(\x01\x18Wj\x87\x90\xd3\xf9q\xeb\xd6S\xf2#f(G4GޗI>\xb4\xa7\xd4\xe0\x85\xe4n\xd5ڄE\x92\x06\x0e\xfc٩\xff\xf7\x8d\xf2^\x84\x9b\x92\x80\xe6\x97˗\x8b\xdan\xf1HG[\xc7\x16M\x89'\xc9C\xd4&\x92Ǹ'o\xf8rUm\b\x05\x80\x1c\x8a\xc6\x11\xfb\xcdN\xcb\xcfݾ\u007fwJ\x01?\x89\x12\xe56\x97\\A<\x88\x8fN\xc1\xb6\xf7\x0eZK5\x12\xa2D\xc1)\x98\xfc\x85\xef\x1dHi=\x17\x82i\xd9qlS\x05\xce\xd5:\x9cB\x1a2\xb6&yY\x91\xed^\x1b\xd9\x06\x17bخu}\xe6\x10Y+l\u007fc\xfc\xbeZ\xdbmL\xc7\xd5%9\xa4\x15\xe3\xa6s\xc1\xc6̪Y\xefO\xf21\xe9ߺYD2\x0eL\xb6\n\xbf\xfd\xbfʢ%\xf8\xa2\xf5c\x15+7\x9d\aV\x94_.rsIq\rp\x1bש\xf0\xb9\xe5\xba >\x10\x04\xc9bG\xecNz\x95Ž2\xb2q\x96X\x93\xfdD\xf9I\xae\xd6a\x8a\xf6\x96\xda'H\xff\x10V\x83T\xa2\xad으\x99\x9f\x1f\x95E\xc9t\x8f|\xfa\xdaG\xb53\x96(\roOtrJl\x0f\x97\x12s\x02<\xe5;\xd5\xf2\xdc3)YQ\xf9\xe8\x81`gw\x878\x05\"o\xbd&\xef\xdf7>\x17\xeecѭ\x82\x88^\xa2\xf5@&\v\xe6\xd1t\xeaT\x93\a\x12}g\xbb\x1c\xb1$\x82}\x88\xec\xb00h\xbah\xbd\x13)\x88GT\xfa\x01\xbe\x00\xc7s\x94\xe3y4r\xec\xc7\x00\r \x14\x00\u007fo\xea\rM\xf2H;\vΦw\xea~|\xaa !(\xeb\xef\xf2\xf7\xcf\xf9\v\xf6\x86\xd9\xe0\xb6\x19\xf7ad\xd8\a\"\t\xb9\x91\v\xdb-sQg#\xe2,1M\xb0\x16\x9c|\xaf\xad/\xa9u\xcdh\xf6R\x94\xb1\xd3-\xc7.k$G\xf8K,݅1a\x15=a\xab\xfc\x8cYP\xc7A\xc6,q\x94%!\x11\xd6\xff\nON\x05\x15zvN6\xd7^\xa5\xc6\x03>\xf0\xeeƬA\xe9v\xdcJ\x87F\xf0ӽ\xcd)\xb0\xc9\n/\x9d\x99\x8aުl̒\xa9B3GM\x19\x9c\xaf'[\x18\x90\x1a,n\\\x16\xbe\xe7\x8c\\\x1dk\xdeѣ\rm1\x05\xa5hm\xb4o\xb5>!\xd3\x1a\xf4\xbb\xf0\xd5jM0C <\xa6\xe9\xe7\xff\xf3\a埵\x80\xb9ߎ\\\xbd\xbc\xbb\xbb\x91\xbe`K\u007f|\a_xN\xf4\x11\x11`ǀ\x9c\xb8\x9epW\x1d\x1dJ\f\xe8\fjHL\xf6M\x0f\xa9<\x94\xea_\x94\x92\x89=\a\xf9\u007f\x9f\xaa\x90C\x05\x14\xa8\x8a\x06M@\aWޅ\xce%ꉷ\x16\xb8\xfddž\x82\xf4\xe1\x93f\x14\x97\u007f\xa3\x8e%\xe4\xa7Mn\xd8p\xe6\xa1\vZ\x00\xd43\xfd@>'\xf6M\xbc\xf0d\r\xfeY\xba,B\x04T\xb3\x97u\xb1\xc2J\xf5:\xf9\x03\x1b\x83\xe6\xd8o>\xaf\xb5b^\x1dչ\xe1ȑ\x92ދGx\x8e\xba_W\xeb`\xcf\x04H\f\x04\x8f\x92\"=\xb4ϟ\xa3\xfe\x01z&=\xde\x05\b\x1c@\xfe%ӌH\xd9\xf3\xd8qi\x93x\x17\xb0DH\xbaXx\xcfjꄯK\x01 \x16|@\x00\x04QT\x16\xb0\xc6P\xa8\xe4+\a\x18\xe3:u\x1e\xee\xb2c\xdd}О\xbdT\xb2\x9b\xcb\v\xa1\xf0\x85B5\x8cڨ\xca\x0281\x82\xd6hȩ\xaa\xaa\x9c\xa7a\xb7\x99Fu\xf6XLc[\xa1nNרxtN\xdfD\x9bX\xd8\xc5*\x11N8\x04\x02\xfd\xf0\xc6\xdc\xe1\xc3s7\x1e\x02\x16\x89\x15|\xf8\xf6\x18\x86\xcd2\r\u007f\x90\x05R{>}78\xf8\xd8.\xc7\xe1\xb9G\x8e\x9d\x04\xd5y\x11Ղ\xb0\x9fOg\xc1#\xf8Q\x0e\x96\x91\x9aq\xf3'\xa0g\x12\n\xcff\x92\xaa\xb8\x12\xc2\a\x18K\xf8Y\x88\xb4`\xb29\x8fh\xf32\xea\u0084\xc96\xda\xfd$}\x93\x1e\xae\x0e\x1e \x97\x83(\xc3T?\xbb\xef\xb2\x18}A\xad`\xf7\x0f7\x1b\xd4\x058\x94\xe8\x80\x18L\x19HFR\x12\x03\x89G\x8a\n\vE\xfdFJ\bXw!S\xc3K\xd2r\x86\x1d\x8e\x00\x04\xde@EKa\xfa\xdc2\xcb\xf6'\xbe\xe9\xb1ʌ\x94%v[؟[7\xbe\x82\x1fS\xaeF\xb3j\xbc\x01\xe8j\x86\x14\x87[5\xe8h\xa1M\x06t,\xa1\xb9\xe1^\xff\xa1\xd2i#\xda\xe1Co\xaf\xb4\xceq§\xfbZ\xa7e\xe8\xe6\xf3\x9a\xbdt\xac\xbfe\xe3\x19Wi\xfe\x95\xb7\x87\xeep_\xd7t\xa8\xff^*>\xb2\xb8\xb1\xf9Vlh\xf1\xf9\x17Z\x9aQ\xa3jX\a\xa7\xcf\x1cB\xdf㨪\x829\xa9q\x027\xd6@\xf9\x19\xb1\x8b\x82\xaf\xb8'\xb4\x12\xd0\xed\x16\x1e\xe3\x9e\xe1\xfa\x1d\xab[=e\x1e\x1c\x89\xc4H+^ї\xba\xc5\xde\xeaa/\xf5G\x85\x136\x8cz\xd5<\xf06)yж\x87\xe5DH\xe4wF\xcb\xcf\xf3\xe3\x13v\xe5\xfa\xfa2nF\xbd)%\xc3d\xf8\xf3\xef\x03\xb9\xee.\x9d)\xe1\b\x14\xc6ەP6^÷r\t\x8d\xe3\x04{\xaah\xf7\xc8<\x8aL\xca?\xb3Ih.\xa7\xb7\x98\x8e\xb4dht[$\x9d\xe5\x1e\xe3\x16]\t\xec\xe2\xb2fŘ\xb09&4.\xda;\x00\xe6s;\x8fB\x8c\xaf\x95\xfd\xf6\n\x12\x9ak\xf6\xf5\x19\xdc\xe6\xf5\xf5\x95~\xcf>\xa8j)ϰy\"T\xcb㝼j\xbdMU\x1b\x81\x02\xe9d\u0382M\xbcݱ\xad\xb4[\xff\x84D\xf1g4\x0f{\x1a+\xe1ݝ\x1f\xa9\x8c\x02\xa1\x17:\xaa<\x839q\xa9\x02\xb7\x01\xfeA\xcf\u007f\x14\x02\x05\u007f\xa1\x15w\a\tL}\xbb\xc5A=£6\x13\x1b\xaf۠ev\xf8\xddAu\x11\x94+U\xfa_\xff\x1f\xf6Q\xde3f\xde?\x9f\xe4\xe2\x95\x1bR\xb7\\\x97\b0\x05R\xc6\x00\x18\u007f\r\xa4R^ \xf3,\xf7\x98\xebV\xd1w\x85\xdcW\xa2\x1b\x1d\x15\x82\u007f\xb2\xee2\xe2`A\t\x1f\xe5v\xa9G\xa9<9\v\x0f\x93\xca4nX;\xa1?\xbb\v\x89?\xf2\xa7\x1b*uV0\xfb\xab\xe4\xb4\xd3\xed\x03{[\x014\"\xae\x10\xc3\u0382,\xb6\x17\xc4\xee\x82\x15\x1aqӼ\xb1\xe7<\xec\xe7\x92RK\x9a+\x82\b\a\xdf\x1d\x86k5\xc8WxcF\xec\x84\xf0\x18P\bO\xfc\u007f\x1f=*\xc2\xf0\xa5;E\x12\xfb\x83\x05\x99\xd5\x18D\x83~\xbf\xcf:\x17\xd4\t\x92m\\A\xb6\xbep\xf8\xb2\xda\xfd\xcb\xeb\x19\\XX\xa7\bd\xb7\xff\xab\xf5+\xbfH\x0ek6\xfb\xffZb\xde\xec\xdfWsX\f\xe4\xac/\xd4\xcd\x03$_\xba\xadQ\x84\x13\x12\xf1\x84Z_\x97\xa9\xbdhh\x90L\xf5u|\xd7\xc6\x108\xf9\r\t\xc2\xd6\xe4Z\x94\xa6\xc2\xd4}\xf1IH\xc2:ƋoK}\xbb\x8c\n\xcca/-\xd5k\xa3\xf3xVq0\xc4\x02\xc2r\xca\xce\u007fLC\x90_\xe0\x84\b\x14D\x106h&軓S\xa5q}pߨ\xf2=\x9a\x18\xb8~38\xbe\x10\xa1\xf1^x\x8eSߡc\xbe\xa8\xd58Um\x11\xb1\xf7e~7\xb0\xb8\xb6\x1e\xf4\x99VUZ\xc7:\xf4vƯ\v\xe4[m\xe9>\x85\xbf\x13\x80?\xd3\r\xd1\b\xe0p\x1b}\xf4_\x06\xe1\xf9\x10gK\x06B\xdd\xf4\xa1\xfa\xc3_\n%\xeb_\xa4g=\xf7Ih|.ݥą\xf2\xfeV\x0e^1䓺0\t\"{\x93\x967\x86\x83m\x86s\xd09\xc8\x0fꛦ\xb3\xf4\xd1B\xe0\xf5\xecN\x9e\x94I\xc1\x13p\x87\xcci{\n]J\xac \xea\x10\xf6:M\xb8\xaa\xa5\xd2y\xe4%\x89\xc5u\x86\xe7\xd5\x06\x00\xbf\xfaG\xe6\x04\xcd\xffVց\xa1\x02\xb5\v\xe6\xd2\x01k\x02k\xb4\x14\xa4\x8d\x06\x8cpy\xe0\xa7\xe6\x81j\x06p:\x1a\x04G]\xafZ\xd0\xe8\xd8\xc8$\x120\n\x8b\xf4\xfa_\xeaN+M7\xfaY2\x18l\x15\n@\ax\x87\xea6\aq\x9d\xe1\t\xb7\x9d4\x9f\xd5\xdf59O\xd4Т\x9c}\x11T\x93\x90r\xfcf5\xfa\x9f2\xffk\x16 t\x01\xaa߲\xba}\xbbp\xc4U\\\xd2ur\xba\x9b\xb7\xb1sVl\xb8ת\x85a\x87\xf5\xbc\u07b2\x8e\r}Vm\xda\xf1\xc7~3\xffgm\x86\x8d\xcd,\x18\\7m}\x95-\x8e\xc1\x84*\xe3\x9a\x10,EH\x9bq\x03\xe7$Yx\xb8=\x0eE\x15\x98\xfc\xfe_V'\x9e\xf6C\xea\x19\xb2R\x99i\x87ND\xb5\xfa9\xf5\x03\x9d\x91/\x00\vC\x19b\xb2\xb3\xc1\xd8\xf8x\x9d\xa1@8`\xc12I̪,!\xf1\xd1\xc2\x03f݄\xb2nE\xf1\xf38\xdeb\xf1\xfa+\x12Q\x90\x942쪘\xeb\xbdCZ^?G\xf7\xf8Vf\xe2\xec\xf6砱\xb2\x04\xfb\x17(B\xeb\xe0Ie\xf3\xfc+\x14\x899\xad\x16\xee:\rA\f\x0e\v\xc3\xf5\x9c\xef\n\xff\xbcv\xa8\xa5\xd4\xd04\xd4RB\xb7H \xd7z\xe7ѳy\xec|\xffx\x1b\xbe\xae\x9c֣\xdbW?\x80E\x1b\xfb\x12\x1at\xb4\xd0FO\x0e\xcfܔ\xe1\x93c\x1e\xfb\x94=\xf5\x9a1E\xe5$V(T\xf3\x92\x9a\xd7\xc1}\v\xe6\xabrY\x18\x0e\xa3!H\x1chQ!.F/\rd\x10\x9e\xf6\xf4իG\xb4\x83\x9e0\xff\xef\xd4\xd1;j\x17\a86t\x1d\xfe\xc0\xc4\xea\xaa\xc5\x16\xae\xec\xd0\t8\xdc\xd5y\xe4\xf8\v\xdfQG\xb4\xfd/Z\xb5\x90a3\x06=\x06\n\xcb\xcf\xf4O\x81\xaa\x87\xc2_\xd5ؤJ\x9a\x99Pג\xa2I\xb1Rs\xa3Z=\x8e\x90|ڼA#\x91\x8c\xac\xac\x8c\xf0\x0e#\x91su\xeb\xee曻;.\xeb\xe9\xdd\x1a\x06\xbb\xfa.t\x8aש:\xeaK\x16IT'\x17\x816\x98\x1a\x95\xcam7\x98\xd2\"\xf2:\xef\x1a\xec\xe2\xbes\a\x03\xc5b\x12\xc7q\xd7yL\xe2@Z,Y\xaf\tbg\x98\x8e\xdd\xc5,\xc1\xfe\xbfn\x9f\x06\xfb\x89\x98{\x0eO\xb8;]\x93ɪ!_\xe3\"=c\x17\xf8Ӻ\x02\x86\x9a\x82dij\x9b2\xa4G\xecB\xbfX\xb5$\x80\xe3\xb5\xe0|\xa9\xab\x17\u007fi\xdb!\xb1\xa1\x82*nT\xee\x01%\x9b\x02\x13\xfb;\xcf\x15*\xea\xc5\xf6\xe4^3\xce/c\xed\xae\xb9E\xc0\x9f\x13s\x9f\b4\xf6\xbaC\x03wLj})\x19\xb1\xf9\xe2<(\x86\x9eYpHw\xe2\xdd\xf3W\x8b^\x92\xfdHL\x8c-\vv\xcb\xdbp\x84\xf9đ@\x01w\xde\xc4Пp\xc5̹\x9dU\xfaK\xb8\x97\xc0\xa1>1뷀\xf1\xc4L˾\xa9f\xe2\x040p\x89\xd0Ύ\x97\x1b=\xd4_\xeb\x8c\xf1\x9f!\v\t9\xfeq\xc6[\xba\xba\xc1ƭ\xae\xf9t\x84-c\\\r\xd5\t@\xd5q\xf1]\xb2\x92\xe0CAJ\xb4\xafp\xcdPao|\x1ey\xa9lN\xde\xea\x91{\x0fF\x86\xf3*3\xb3F\xd0\xf8\xcbxL\u007fTv\xa2\xb4\xd00ԛV,\x91\x90\xbb\xe4\xde\xfb\xf3\xd4jH\xf5A(\\\xc9\xf4\xd4x\xe2\a\xfa\xfb\x9f\xbe\axtP\xbd\r\xf5\xaf\xaaR\xa5^\xa9\xd7\xe5\xe5\x00S\xbf\xefh\"\x91H\xb0\xc6\xfdJn#_p\xbf.\xc2$\xad\xb2\x02\x19\x8ds2\xf0i\xa8\xf1\xfbB\xcc\xe6\xe6\xf1{T\xd1uZK\vt\\\xd4L\x1aI\x87\x19%\xbe\xed\xf1*\x9a\v\x8c\xbfP\xf8=\x16{\xf9b\xe0\"U\xb8Q\x87\"V\xd3R}\t>Z\x82\xd6\xf1\x8a\xd2\f\xa5\x81ŊN\xb1\xb3Vݮ\x02\xe9-\xfbJ\xc9\xech\x02\fσ\xe1\xcd\r\xc3^\xa9\xd9\xd5\xc1\f\x11\x8c;\x92\xa6FQ\xc3\xd4,*+\xe8\xad\"\xf5\"\xd500)\xb6:;:V\x94\xa7\x12P8*e(7\xd2Jl\x97\xbd\x8e\x8b\x9b0oHe^Ɗ\xe2\xe5y%\x81`\xbc\x93\x1d4\xa7\xc7Y\xd2[eX\x16}\xb26K\xfcJ\x05˩\x84\x91\x12\xcc\x00\x00^#<ɝ\xc9\b\xcfI\xdf_/\xee\xae23-@\xb1l\xb34\x96\xcb\xfb`\xca\xecP\xe2=\x01\xe6K&=.)\xe9\xcd՜XvL\xaa\x88\xc5f\xb1o\xd9\v\x9d\x8bBG]ޮ\x8d\x16\xd2+\x02\xf2\x8b\xe6\u0602Py\xb8\xd0I\x8en\xa9V`\xe6k-~S\x8c\xc5d\xd0\xed\x11d\xfd\x02\xd8cU\xb7\x97.\xdagƗ'\xdd 1N\x8a\xfd\xf5\xad0P!\xf4\x00\b\xa1ί\x82\x87H\x95\xed\xa8]Hf\xb0\x12\x9e\x0f[\xb4Z\xc2x\xcb\x1d\xe2\xc5\x05\\.\xc2 \x91\xe0\x80\xbd+\xa2\\_\x164\x13b\x98\xa6Ov\xaf\x1a\xff\x82\x8a\x92#\xbb\xae\xf6\xb1\x88\xc5v!\x82l\xcc\x04,\xd4x<\xec\x1aD\x13xIN\x02-F\x13\x82\xece,/\x89\\m\x82\xde\xd3d\xb4Py\x98\x12\xc4Ir\x86\x83ǐ&$\x8a\x11G\x1b\xbcK\xf1K\xb6\x16\x84և1\xc4q\x12\x97zG\x9f!\xaf\xa3\xb2\xb5A\x05\xed\xbb\xc0\x11\xb938\xad\x11̍\xcd\x0497U;ȴVe\xe6g \xb0\xe9\u074c\x1e\xbfL\xbb\xf8ΐo\x9ctp\x92R#\x05\x8e\xab\r\xeeA\xa7D\x88\x16\xa2\xc3䶅\x10\xa2)\xe8m\x83\"Ǜ\xf1\x19X!\x10\x0e-\xea\x97Μa\xbeR\x1e\x95\xaa\x82\xb9\x99_\xad\xf4\x91});\xcd;6\x13\xc5\xefП\xb2(\x8e\x8eo:֔\xfcqC^\xfd\xf9Ǖ\xed\xa9\xfb\xad۵\xe9\xadA=\x8ez\xf9\x1aO\xef\ab\xca\t\x85d\x84~\xf8\xca\xc5\xdb\xdb\xfb\xb6\x8d\xd7\xeehz\x97n/J~\x98ǪŤzS\xe8,J\x82\xa6J#2ŭ\xc3\xf3\x10i\v\xe1\xffZ~_\xa2{c\xbb\x8c\x1e]o\a\x96bR:\xf4v:\xeb\xa3\xe2\xf6?e?\ttZ]ָ\xdf\u0560\xdfgժMk\x0e\xea\x16\x14&\x8ezz\x9fq\xb3\x1f\xe5%\xc3UCW\\Y\xdeڻes\xf5\xb6\x867iv\xa2\xe4\a\xb9\xacZ\x97d\xef\b\x1a\x14\x11\x9fT\xa9\x16V\xe6\xacQ\xccC\x8e\x1c$m\x04Čk\xc0i\f\xddw\xb4ƿ\x05\x12#\xf3\xe6\xaf;\x0f\xcd\xf8̋\xc9\t%y\xcbG\x1f\xad8@5:yq)\xb4\xa8\xac|⌬N\xdd\xe7=\xfd\xb4\xc6\xec\xc5\xddBց\xc5^\\\xfe\xa9S\xf98]\a\x02\xeb\xf5\xaa]\x9a?{\xbc\xa0rW\xf9\xb5\xf2\xd2[\u007f-\xec\xb9+W\x0f\x18\xa4q\xd9)^2\xd5\xf8\xdf\xfd\xc7-\xc8\xcc\x1bKK\xa0\x140g4\x89LҼ\xee&O\xf9\xb2SP\xbcd\xed\xe0\x02\x9dŞ-m\xb2\x15\x80\x05\xc7>\xf7\xb8\xdd\xf3\x80\x87n\xecx\x1b\xcaQyY崎\x00b\xe1\x1c\xe2\x89y\xa6C\x12Q\x9a\b\x9b\xce\xc7\xfaA\x00\xcf\x19\x93)\b\x98\x8fB\xcb\xebD`<`\x92\x88\xec\x99\xc1\xd7\x18\xb3\xb1\xb2\xf0\x05\xe9\xbf\xfe7\x9e\xc9\a\x91\xbb%f\"\xa5Y\x89\x16\x93\x15\x8d\xfb>\xb6\x92\xd9ШG]\xdcT}\xea_\xf3\xe2\xfa\x9d\xc3\xea\xc8T\x18\xc4,a\u007f\xd2\xec\xdf^&xԠ\xab\x91\xe7,v\xa54\x98EpW\xf0¶\x9f\xf2S\x84A\x14\xfdN\xefⅭ\bgj\xde)\xde\xc9\xec\xe2&\xaa\x8ad\x99\x00\f\xba5\v\xb84\xad\u007f\xe4\xfe(\xda\x04\b\xe7\xe4$\xc1\xfd\xe3sD\xe2Bݦx\x9d\xf0O\x9fh\x11\xaaXQ\x9f\xccL\xe2\xb2w\x98\x05\x8a`\xed\x1fq\x8en\x1dP\xee\x88sT\xa1\x17s\xdb\xd5'@\xc7Tz\xc0\xbd,\xed2\x1f\xcc\xe8J\xb5*njވ\xfb4_\x98}3\xb9\xb8\x17\x9d\x9c\xbbי\xc7j\xc5ҫ-\xab%i\xf9\xa8\xf2\xa5\xbd\xe9\n\x80\xf2\xb7\x01\xbd\xc2P\x92O\xf3\xa4F?\x8f\xadkjS\xdb#\xed\a\x04G\xfa'\xeb\xcap\x1b\xf61\xe6\x8e\x1d\xbdJ\xc3\x18m\xeab\x06\xda\xf6\xcd\xd5a[\xef2\xef\xb1\xe5?kKq\x01\x1c\xa7\xb2!\x8c\x88@-^Y97\xf7*\x9d\x96o0\xf0\x81\x91i\xc5M\xd2l\xe4=\xf5ߺ\xfc\xb6\xb4\xed\xaa\xbf\xa5\x92\xf6\xbe(\xe97g\xa9\xbc\xbf_\xab\xdfǙ\xc7\x04W\xe5أ\xa4\xd3..\xfb\x8d\n\x8c\x0ep\xcd\xdb\x1e\xe8k\xa4\x8c\x03\x9f\xae\v\xee#\x0f\xac\xf3\xf8\xf8\xc1c]\x06@\xe0\xf9\x03\ue5d2\x8dq\x03\x8bo\x9as\x16]\xacvK\x8e\xc0i]\xd3C\x15+\x1d\x9aK6\xd6\v-\xed/'S\xa2\xcb\xe8{V\xaa\xe1F#p\x05ƦuO&\xe1\xe5g\x1e\xf4z\x89\xa9u\xf2\xe0t\x92\xaaxeL\x94.\x8a\xa8v\xdes\xdcMf\xefџ@/\xe3\xce)\xf6u\x95\xb0\xef\xc8\x1bA\xe3)\x1b0!۽\xf8\x00)/Y\xb8\b\xa2\xc6_$mU?S\u007f^\x15\xde\tGq\xd1\x01\xda\xcb\x13\xc8Vċj.v\xdd\xd6\xf1UH\xa1\xf30\xc1\xcamǕ\xd6\xd8*3\x12\xa8\xbc\x87\xd0b\at3\x80\xa3\xda\xc9(\xe1\xcf$F#\xb1\xc4P\x83hzZ\x98\xb2\xb2o\x11\xb6\x14\xda\\\xa2\xc8d\xf9沠pm\x1cL\x91~\xf6L\fj\x0e\x13b\x10\xcbm\x10mK\xe5\xd0\xc7\t\xa8qsN\xf1\xb6\"Q_Qh9\xd1\t-\x91\x1b\xdb㳟CU\xcf\x03\x01џ\xfd\x8fO\xea=ކ\xf6y\xd45\xf1\x84\xd1\fYk\xc8\xed\xd4\x1f\x8a\xc3N.e\x1cu\x9bi\xad#u\xb9\xe5ڒࠠ\xb9\xad\x92p\xd5\f*\x93\xd8!\xa1\xf4C_\u07fb3\x8c\xd5Q\xdap\x83az\x04m\xa6g\x1a\xe7-\x96\x8c\x99\t\xb9-\xe5\x89\xf3\xf4\a\x00\x02k\n\v8\x89\xabZ\a\xc4\xc3莧\x16\x96YP\x94d\xcc\x1fM\xaa\x9c\xb1\xf1`TG\xbc\xb5\xd0\x1chѤ]:\xabd\xf8\xd4\xd0VN\xcdv\x02c\xaaW:w\x99\x13\xeb\x8d|kҁ.:ӫ\x1e\x8dO\xddڑs\x80w\x1c p\x00T\x12\xca\xd2\x1f\f\x80\xb6%z\u0381ه\xc1*\xec0)\xd8\f\xea\x1eA\a&3\xaf\x92\x13PPQ_i.\xde-Z\xe9!\xe1\x8d\xd1\xf6\xbd%\xd1Tt\xf6\xa8\xf8f3\xebk״\xde+\xb4\xf0\xb4\xfff\x83\xd0\xdd6\x8b\x9d\xe3\xb5\a\xa5\v\xab\xd56mP\xd0яH4\xb1ׇ\x18\x85\xc32\xfe\xd5\xfc\n\xb1umMCͥ\x06\xe7\xa1pm*Y˭\xab\x8b\xd29\x0e\x01\xc2_\xbb\x9d\xf2\xe2\x15J\x11[\xc4\xf3\xf3\xba.9\xb4\xd7&\xf3\xe1,r\x80H\xb8i߃8Ʌ\xa0\xefa\xc2\xcd\xd6\xc8\xdf\x19\x97[\xbfN\x1e\x98n\xb3\xfe<\x8eCrxL\xb5\xefr\xf9J2\xe2vc\x18\x14\xfe\xe4>x\xcd\t\xfc\x9c\xee\xd6\x11\xe4J\x1e\x82#u\xe3\xa4\a\xb7:nY\x93\x16\x9d\x98}\x1al\xf4z\xc2Ӯ\xb4\xe9^Y;\x9e\xb6\xe4\xb1z\xb4\xea\xb3\x17Ӊ\xac1\xc0`7z\x83v/\x9a\x98_眓\xb0\xca\x0e{\x90\xcf\x1b='T\x87 `Jټ]\x18\x02\xf8ȇU\xcb\x02)K{v\xfb[\xa5\x84\x14\xb0՝y\xac`\xd7-0-\xd3?\x9d\x9a\xc1^\x82\x9a\xff\xc7[\xc9m\x03\x0fSƐ\x1e\xc2=\xf9\x03O#_D\xad\xad\x9dq\xc8q\x1a\x8emR\x1f0\x0e\xcd\x1a\xc2\xd3)\x95\ni\xa2b\x11J\x9d\xb1}\xe7\xce\xed\xf8<\xddw\xf8o\xe2a\x81\x01\x196\xba[\x9e\xf6\x81\xbb^D\x85\xde\x1c\x84Zz`\xaf\xab\x9c\xe0̶.D\xe6K\xcf\xf2\xa7\u007f\xcd\x1a=b\xb1\x05\t\x9b\xc6\xe2\xeeb\x88\x00\xe4\x9dl\xad\u07b2w헂M\xe2\x18\x9a\xd3\x067d\x18ֆ\xa5\xa3\b\x85\x80\x15\x80\xed#wQ]!\xb0\xf6\xd8˘\x98\x14\xf3g1}BJ\xda9\x89\x86\xfa\xc4\xc2Ԏ\xf1I\xae\xf3=CVR\x8d\xb9%\xceL\xd5MU\xa2]C(\xf5+#O\xf71Q\xaedj\xca2\xbe\xb9~\x12&\xc7B'٩p\xbe\xd9c\xf0Q\xde\x1c4\xcc\x1b1#\xb0\x96\x9aq\x1dʸL\x8f\xc9̮\xaeL\x9b➒\x16\b\x9b\x86\x19\x0eGZt*j\x18\x96\x1eI\xb6`\xe8\x16\xdbQ\xb5\xa2\x8d/\xd0\x02HJe\u007f\xd6l\xb9\xe8\x87\xd2\x1f豎\x95\x9b\x94x[0\x94D\xa3\u058c1\xc2\xc0STK\x89af\xd4;\xa2\f\xf8\xd93`\x17L\x98\xb0}\xe4\x8d{اJ\x11&5\xb3\x80\xb1\xc4\xd9\xeaJ\x84^\xb7\xfc\xf5\xb4G\xbd\x8f\x86\xa1\x86\xeb&\xf5\xf6\x9ex\xad\xee\xb2%n\x86q##\xe9G\xb3\xa17\x96\xa4\xffp(/8\xf9\x84\x9d\xd7ʶJ\x1bGy\xd1\x1b\xbe\xf68\xd1?\x96\xa4\xff\xb0\xc8+>I\b\xb4\xa5\xae\xf8\x8f\x10克W\xe2\xbbT\xdcm\nAj\x98\xf7/b\x88\a\xa6\x88\xb3YFNG\xffu\x17c\xfe\x04\xf7\xb5\x8e\\\xae\xc1\x8b\x88\xcf:\xebi%\xba\x96\xe1fU,p\x17\xe6\x82I\xec\x8dp \xff\x96^y\xb6\xeb\x95\x1f\b\xf7B\xc0cx\xc22\x8a\xd0\xec\x1b\xf7\xca\x16\rVb\xe0\xa76N\x01\xbfd\v\xd6ٍәT\x80\xe4\xe6\x9dl\x14\xc6W\x86{tĈT{\xf0\x96\xe8S\x11\x1e/\xa5Q\x95Y\xfe\xa5K\xfd\x8e\x15\xd57\xb7\xe4#\x12\xae\xbbp\x16QcGo\x91\xde\xf0g\xfbQ\xa0\x80G?e<\x80\xf3\xb4\xe8\x05t\x19\x86\xfd\xe7J\xa0\xf8\xe9\xac8\xb73\xd7Y\xb5\xb5ި\xfcF^:\x9e̊\xe3|\xee\x8eʚ8`r}\xe0Q\xe7\xc1hF\xe94\xd5뢺j\"\xb3:k\xa22;k\xa3\xce.,\xef&\xfe\xd6z\xdbTIF\xb7Ty\xf8=\x9dK\x99\xc2;\xc2pr\x02$\xdcѲ\x808f_\x9b\x93TI\x1fV[\x85\x8a[\x01\xb2ź`\xf6\xc2\xe6.N\x0f0\xceU\xb8\xa9\xe38I\x00Y\x9e\x97\r\xc7D5\x0f\x957\xf6o-\n\x1c!\xf3mv9\xa9\x8f\x1c\\/\xb5KR\x99\x9d\xb1\xe2!\xfd\x1e\x8c\xff6\xff\x88\f\x81b\xe9\x1e\xc9\\\xb5+'I\xe7e/\xb1\x9da\xf6\xcaFz\x1bͷ\x10\xfb\xb5{\xed\x8b\xf3\xf0P|\xf3\xb5w\x8d\xc34ej-\xa5\xa0t\xc2۠^\xc2\\\xdfSK\xd7+'\xbcJ\xe6\xfbR\x9b\x82S\xf4\x8e\x00\x1df\x99\xf0\x0e\xc8\xe6\x82\x034\xbe\x96Ԗ+\xc6e\xf9\xd0\xc7\"Ӄ\xd6j\x1a\\\x91\xf3ʌ\xe0E\xcd.\x02\xc5>p\xb6\xe6\xed\x97!\xcd\\\xec\xbe\xf5B\xf5\xe0\xb8\xc3}vچN!\a\"f\xc5\xeb\xba\xe3R\x8b0r\xd6G\xc0\u07fb\xc0*\xb9\xd0\xfd\x1f \xad\xc6\xf6\x95\x8d/J\x95\xe4\xf3\xe26\x1b\x98M\x9a\xfe\xf1n\xff\xeb\xca~\x8b\xab}}\x18<\xf1\xed\x8e\x1do\x13\xe1\xb0\xe0\x98\xe7lϸ\xfbp\xef\xfc\xbdf%\xed\xde\xff\x10n~\xdd\xd8W\xd5X\xeeU\xe1\xbcl\x11A!\xb9ˍ!ӫ\xc2\xfd\xfd8\xebiD*\xb9z\x123\xc9\xd9@\xb8\x85EYo\xca\x05J\xd2N\xf1C8f\xa4\x04\xb7\x92,\x03\xe3R\x1d\x12\t\x9cƏ\x83m\xd6w\xf0\xacE\x1b\x0e\xc1\xf1(\xc9i\xfdwL\x8c\x05\xdfe\xee\xe37\xebxЬ\xbb\xf2\xd32\xed\xe7Lz\x00\xac B\xa2\b\xc1,\xe4'\x1a\\n@Oޤl\v\xef\xf7\xff\x18o\xe6s4PcX\xa1Y\xfb\x13\x96\xc5\xdf\xcf\xef\v\xe5\x11\x8f}t\xf2\xacp\x8f-\xb4\t\x89\x8eyC\x1c&\xea\x1f\x83z\xa5\xb1\xca\n\x0eZ`7\xa1)\xaaT)\xab0\xffjJ\xa2\xf9\xd8\u05ef\x8f$7\n\xa0\xbf\x93\xa2\x80۷o\x12\xc1Uck\x97\xb1w\xf1\xd4Y;8\xa0\xb6>\xcc\xeb\x80\xf1+g\xd16w&$\x1d\xd1>ނu\xcb\xeb\xb6\xee\xfa>\x1b\xc2\n\xddVZ\xeb\xc1\x88J\xb4\x05\xa3\x91\x1a\xb4\xb8g\x82˿\xe5=\x8a\xfe\x83>O\x8b\x01\xe5i\xe9\xb6]@\x9c\xc9\x01\xff\xe5QY\xd6\xf7\x86\xf9\xa7\xf7\xd8O\xda\xe6\xda\xf2\xbf\xd2ƽ\fAI\xaeN%F(\x9d\xe0\x9a\x04Y\xfe9\xcc9\xa3\xdeJ\xd5C\b4\xceQ@J\xfd\xb8\xb69\xa0\xe1u\xae3p=\x05\x820A\xa3\x8a1\n\xb8\xe4,^\x19\xf5>\x05\x84(\xb5\xdaHR\xa9\xd4Bx\x8d\xb5Lԇ\x88j-\x18\xf0\xed\xefa\xdap3\xad\xff\xfb7ub\x03\xf0NV4|\a\x11u\x87\xa0砋ale\f\x8d\x9az\b\xa2\xf6\xa8J@\xea\xd55\xfa\xab\xe2y\xb8C\x17\a\x8dQ@RRq\x82O\xf9\xa7\xb0\x86¼\x85p\xc5\xde\x18\x85\xef1\x03\xccB\xb8\x8fj\xb0*\xbd\x0e\b\x19O\xf2\x80\xed|O\xb1\x0e\f\x14,\x82\xee\x02\x8a\xfd\x91\xee0\xc9߰\xafʹ\x02н\xf3\x88,\x1cu\ue240\xc3\xe8\x84\xfc\xc0\xc2\n\xb4Hs\xfe\x125\xbd\xdeIJ\xd9\xcaR\xa5\xd5\xea(\xa5\x87\xf3\xf5\x8d+\xa4\xd0F\xbbL\xc7\x1f?Fh#~J\x17\xf4\xf2\xbd1\x0f\xf5\x94\x96\x96\x02\x1c\v\x94\xb4\xa1\x10p)O\"\xcd-J\xc8\x12\xfdq\x10\r\x9b\x02Ƀ7\xc7u6\x95\xd7(ۄ\xa2\xbf\xf7\xab\xec\xff\xee\x96!P@\x81\xea\b>\x1aÁ1\x94\n\x00\xa4&\x14\x19'\x8es3\xadه\x86X,\xeb9Y\x83\x17|\xbfs\x1a\xab\xd3A\xc8CEvp\xc6|̺%\x14\x98\xb3\x043\xb87\x1f\u007f\x94_*xC\xeb\xe68\xcf\n<\xa3\"\x8c\x1f\x1b'\"G\xc1\xb5\xf1\xe7\xd2!\a\xdd£\xc4\x10\xa4\xe7V\xf5볩\xe0s\xc0&<6D-m\x9e\x8f\xc1\x9b\xa1\x8b\x0e\x81t\xaet\x9ez\xe8q5\xfe\xb7\"m\xf7\x8c\xaf\xbcJ\xeb\xdc\xec}_\xfc(^\x0e\xbdm\xed'V\xa0\xb3\x9b\x9bs\x12\xde\x02۴F\xf7>\x12\x0f}*s\xd6V\xc9\x15Ӈ\x03\x16\"\xb0\xa6\xa0\xcc\xf7m\xfc\xb7\xb7\xad\x06\xef\xfc\xfc\xa8\xd5\x16\xf4\xa99oq\xa8\xb9\xa7\xba\xd1\xf9{\xc1\x94o\xac\x90!\f<\x0e\xa2\u007f]w\a\xbf@a\x0e\xf0#a\x8c\xc4\xe9\xb9Y\xd7Y}i\xc1\xa2\x94\xc4|#\xd2r\xef\xd2\\\xf6\x06\xf2\x89\x97I\f\x02\x94_ߙ\x89W+\xdb\xcb\"푎\xff\xdcNܞ\x820\x97|\x97\xe7\xa79\xa78\xe8ֽ\n.\xc5yf\x90\xa4\xb8\b\xefn\xec\xfesˡ\x00\xe8b\x98\xbf\xce~\x1dp*5E#\x01\xf2\x05s\n\xcbvN\xde9>\xd0c\xc9\xe4\xe8\xb3QG\xd5!\xeb\x80Ú\xc7\x0f\x818\xfe\xfcЊ\x91y\xb36&\xaa\xca\f\xbd-2\xb3~Q\xfb\x96\xcb\x00\x81[\xf4aṖ\x98\xebо)5\xd5\x1f\xe3\xe3\xd9\xe9_[\x97\x91z\xef_i\x1e\xeft\xaa\xe5\xf3b(߭\x1e\x1aO\xa4\x8d=\xe8C/\xfa\xc9\xe0\x9c\f\xed\x0e\xb0\x19P4?\f\x0f9\xe6T\xcb,\x02\xee1\x00\xa2\xafլ\xd2\x14\x869\xd1\xcd\"\xf5f\xbd\xe0\xc9P\ueb26]S\xbb\xf5\xdb\x1fԜ\u007f(\x1f0v4\xfbs\xcfJ\asb\xb5\x99nQ\xb7{\xe9\xec\xfc\x06}\xcd\f#\xc1@\xa4\xfd\xf2\xf7\xeeɏ\xa0\xf1\x9f\x19\x98U\xd9\xc1\xfb\x13\xbd\xa6^\xbe\x9cR+\x18\x81/6\xf7'\n\x12\xa4\x97\x90\x19\x8b\x8b\x11\xc8Kh\xa7\xf7-\xed\xdfF\xf8s\x815\x93X\xfe\xb4ޖX\xfcyXQ\xf73\x88\xd5\xfe\a\xd2\xe9\r\x80\xb8\x9d\xedWK\xfd\x8a\xd4b\"\x8d\xa8&\xcbâ\xd1{\xd6[\xedm\x13\x96p\xdb\xda\x1aZ\xa2\xbe\xe2ֶ/ʲ\x96\xc3Z[\xcb\xdbZ-l$\xdeN\x8ae\x94WHW\x06\xcfM\xc8_\x18\xd1\nVӧ\xe4x\xe6s\x93䀱X\r)\xe4\xd6\x1c\x1f\x99o\xc1C&\xa96\xd9l\x98ktIp\x89\xa1]\x00.@?w\x1aS\xb9\x9e\x86h\x97s-\xe2\x86$\xe19\xec\xe8n\xb1P[\x03\xb6\x9f\xf8\xf5\xb0\x8ep\x83Y\x8fӲG\xe6\xf5\x1f:\xf5\xa5\xaf\xf5\xf5\x99E\xebt\xd1\xd7\xe7\xee\x03b&\xb8<\r\x98E\xe8_\xeb\xf1\xd1p\xd10Jtz\x1f\xc0X\f\xa7\xadB\xb4\xb2\xf5\xac.R\xf6\xed\xfa\xf5\n.E\xc2\xe2Ď\xa0\x94u-0OSBþ\x18m\t\xe2\xdb\xd5Ǣ\x9c\xa0\xf1\xe2\x93\xec\x1a\a]v\x94\x16\xdfd\x9d`\xb7\u007f\xcbÝX\x19\xffP\xff\xe0\x9c\xe2\xfa\x9b[\r\x17\x8c\xeaV\xeeC\xd34O\x10\x91\x8c\x91\xb5\x90\xbf\xf70&z\xcd\xcdu\xa0\xc04\xc6&\xd1\x10\xd4E\xa1ʙ't\xd9A\xee\xf6\xcdB\xc1\xb5%\xda+\x87DˎG\x1c\u007f~A\xedx\xd6\x1e\xf0\xbcCPKZ\xaa\x00\x97n\x16\xac\x9f\xe7\xbeRg\xbc\xbcx\xc2+\xce\xf4\x1bi|\x1b\xb8o\xf1ʜ\xe2\xf1\x928\xac\xb7o\x9c\x17qJ\xb3`\x03\x9c\x14\xeb\xfcG\x14\xdc\xe1~\f\x86\x89ɕo P\n\xe78\x10\xb0y\x0fuq\x82뢵\xd9\xc2\b\xcc\xfa\xd6𐠵\xfa\x99\xa7\x8d\x8d\x9f\x99Ռ=ƶ\x9f\x13\x9bT\xdc·n2p\xad\x12\xb9\xbfaA\x1d/\xe1F[\r]+p^\xb6\xb5F\xb5\x17\x9b\xc4(\xca\xf3\xfd\xc2?ɬ3gg\x01\xf3\xb3\xf5\xd9\x0e\x04\xecQ)\xb4\x01\xc3\xc4Ċ\xb5\x0eDLm4\xf7\x98G;\xbf?81\xd7[ѫ\xd4T\xd8> =\xb1Q8\x1a\xe3\x13\xaa)ʒ\xde5\xc1\xa8ck+gdR\xbe\xf6\x00\x86\x88\x1d\xc3\x12A|\x86v\xe4\xec\xfda\xea\xaekBcz\xff\xed\xe5[\x95\xe9\xc9C8\x94^'\xb3դ\x86\xd4\xcfO\a\x80S0\xb7\x83* )\x9b5r\x8f\xeb|\x9f\x80Ȥ\x8a\x93^\xcc?\xf8z}\xb7[\xf0\xa2\xc0\x81SW\aU\xf7\xbd\x1e\xf6\x1b\xb1\x04\xecT}\x1a\x81\x8d?L\xd7\xc0\xf6\xf9\x0eU\xcd^\xbb\xc0\x8c\xcd}\x18L\t\xd26h\xb88\xdb\r\xeeb\xe2\x8dǎEڰ\x02n\xbc/\x84M\x01\xd1\xd9A\x85\x0e\x04\xec6\xca\xe2\xeb\xfb\xb6\x936Mk\x14<\xe9\xccu9\x8do5)?q\xa9\t#\xc6019u\xa3A.\xcamX\x02\x16\xa9iȪ\xf2fg\xc6Q\u007f\x1a\x93\xb7\xbaWo\xf1\xfeg\xad@\xc6\xeb\x18u\xac;\xc3\t\xc9o\x17#\b\x96\xa5\xcc\xf5&\x8fo4\x8e\x11O\x91:on\xd3\xf4M^\xa9\x9d\xa2;>\x9e\xe7r\x820\xb6.'\x9a}\x17\xbc)X\xf5\xe4\f\"\xa29\x99\xbaO\xe7\f\xb0\x8a\x8b~\xa9.7@3\xbc\xb4\xf2\xf1\x9a\xbf_~I*\xfa\x8f\x95`\xfa\x85\x0e\xeb֣\xc1\xb1\x12q\xad\x14\xc1\xca^\fQ(T\x86\x95\xcf\x03\xd8\x04ߠ1\xf7``\x06\xc2\xf3w2\x8d\xbe\xde\xc6u\xad\xa4\xe0\xafՓ\x05\xaf\xd7\x05أ\b\xcb\xda\xc50\x06\x12\x8cF\xef\xb5(zc<\xb9\xc8mL\xa9hc\xf2\xf5-p\x13\x14\x86:\x92|m\x03\xe9\xde.Ǣ\xb9VfhJ\xe2\xeaM\xf8~\x9a \xed[е\xb4}\xfc\xf4r\x8a\xca2\x8b\x04\xb8~\xfc\xe8\xa0wzJ\x05\x90:Ս{\xe9s\t\x10\x9e3\x11\xf6\xf7xԺ\xd7,G\xb7 \x9dMKd\xbc\x9a\xb0v\x17%b\xed\xb1o\xbe\x83\u007f\a\xd6|\x02\xe0\xfc\xad\xdal6\xa5z\t^aCG;zVl\xb8\x0e |_\xf5\xc3\x0f\xa6\xfdm௷E\xa9ZQl\x9c\xeeZ\x1c\xeb\xee>g\xb7\xe9\x10sSo\x98\xac\xbfl\a\x9b\x03\x87\xf3P\x8f\xe4\xae\x1b8\xffC\xe84>@\x15\x9a\x8f\xf2\x80e1b\x14ς\x1f\xdc\x1d\x9c\xe0\t \x0e\xfe\xccz\xd0\xd7\xf7\xe0F\b]\xb55\xb6\x03Qƃ\x8c/Y\r\xe1vAfG\xdbW\x12J;\xff\xa8=\xdeyw\x16@\xbcR\xbf\xdb\xe5\xfeq\xba\x19\\\x03\x12kK0{2tv\xed0\x06=\"w\r0\u007f\xc4N\xde\x17\x94\x03\xf5\xbcr\r\xafD\xeen\xda\x06\x83J`3\xc47\xf9%/-\xc3*\x9dR\x9e\xee\x80.U+\xfc[l\xafQ\x9d\x867H\xc2\x16\u007f\xc1\xd7\xf30x\x1b\xf8/{dž\x01q\xb0\x90\xc18>6F\xb2\xbe\x0e'0*\bG\\\xf2Q\xdba\xd7$;\x03\x9eh\x89f\x14\x00EB\xd7\xfc\xa7\x99C\x12\xba\x96\x84\xb7-`\x190\x81\xdd\x01)\xf0\x8f\x83y\x94[hʑ\x91\xf6\x13\xbf\xc4V\xea\x95\nH2\x9epC\x8a\x19\xb4xQ\xb5P¥\xf0\xe89\x9a\x12>&zgိ\x8f*\x95+kɼ\x84'\xc5\x14\xbf\xcaW_\xa4~I\xf9\xb5\x8e\xc1Pg_\xf7\x10CO{b\xf1\xe2\xce̖\x89\xa3\xaaaշ\xf3\xb6N\xc9\xc8 \xf0\xd0\xf4\n\xa7\xfb~A'\x0e\x95/\x02I\xd9\xe5팟o\xb2\x99\xf5\xea\x1f\"\xa7\f\xdaܬ\x1a*0w\x02\xa7\xc1\xb9\xf3\xb0\x81\xeb\x8eK\x1a\xa3OLx\x8b\xfb\x89i1\xc0M*\u007fˀzܗ\xb1{\x99 \x9bm\xcdeJ\xba!,O'\xf6\xa8Z2N\x8am\x0e\xc2\x0f\x06\xe2:\xa8\xb4\x8eܢ*G\xc7`\xe0\xf4x]sҶ#fD\\\x98\x10\xfd\x01\xf2\xba\x15\xa3\xc4FI\x82\x9dHw\xf3\xed]\x12\xab\xaa\x00\x92I\v\xfb\xa2\x91?\xb87#\x15ȂU\x89.\xf15w5ɮ\xceR?7\xfb\xd6\x17\x90\x0f\xae\xe40\x1c\x91:\xbd3\xa9\xbfn\x13\x01p&9&\xe7Vup\xb0\x1d\xb4\xa4AFs\x90\x14\x9b\x8c\x1bUc;I}\xbb!\\\x8f\x18\xaeUv\xc2\x1b\xb4\xe5}\xa8\x84\x01b\x82\xbf\x0f\x99z:\xcd\xcd\xce9y\x1e\xdc! R\xd9\xd4\xd8\xd7ξ\x93\xee\x93\xde\xfc\xa9\xca\nN@)\x890ߗDd;(A\xb0Xr\xb4[B\xf9\x12N\xfea\x1d\x1f+\x96\xe3{\xc7\xcd?X\x81\x87\x13\xfe\xdf/\xa7\xaaJڽ՜v\xd6ݶ\xc36\xf6lҤg\x8c\xb4\x87O%\xba\xa5\xc1P\n(\xc5/V\xab\xcd \xeaj\x0e\x84\xfe>MT\x8d\xf2c74bɤ^\xec~^\xec()y\xc7\x14I\xbd\x8a\xc7\xd8Єe7a'x\x8cU$u8\x95\x91\xe6/\xa1\x9c\xe2\x9c\xf4N\xf2Ψ'\x16n\xba\xe0\xceh贑\x9e51\xdb\xe8\x19;\xbe^n4\x8b8\xeb\xbeߖS\xcdq\xcfF;\xe2 Jx\x0e\x89\xa4\xdc\xca\xf0]\xf0]\xe6\xe6\xfeY \xee\x1d\xd6MG-WM\xa8\xc6\xd5_\xc9\tK\x0f\xe3\xa6\xc7\xe9V\xa4gGg\x17\xc7\xe4\xe3\xd3>\x84\x95\xddW&\xfa\xc2\x19\x19i\xbd&\r\xfb\fəۣκ5\xcbX\x98n\xbc\x13\xd6\x17F>gla\xd1⧲\x8f0\xc3\xe6\x11\xc2x){\x93\xe5\x1b\xe28\xdc\xdc}>;|\xce\xc49\ti\xb8 7?\xc4\xc9kN\xc1\xbc\x1b\xce\xc1W\xb6\xbd\xa6\xe6\xff\x16\xe2\xb3\xfc \xf9\xd5A\xf2\xf2P\xf9Ej\xf6\x87p\xe5\xa6Y\xd2rҊ\xd2\x13\xf2\x1d\x92J\x16\xe1\x12p\x187\xc3~V\xa1\xbb\xda\xc0\xb78\xe0\xb4\xcbo\x9f?\x97\xa3\xda\xef\xbb\xcb\xd7\xfe\xeb \x87\xab\xda\xe7\xad\xfc3#JF\t;Sl6\x10QA\x80i\x12\xdd\u007f\xab\x04\xa4\xf1\x05C\xdf\x0f\xecf\u007fT0Y\xf2w\x1e\x02\xc2I\xfb\xf7\xb4+~\xd4\x1e\xb4[\x97\xb0kB\x1d\xb1\x05\xe2\x934\xd11L\xf9\xa8[\xa1*\xf3\xc6;/j\xd3\xfaL\x01AM0X\xe5}>\xfd\x10\xb1\xb9\xa4\xb2\xf5.\xe4tغu\x15\xc8\xc3t\x1fj\x8d\xb2\xc4iZ\x8d\xb8\xea6\xc4\xec\xa1)\xe3\x10\xb1\xa4u\x11\xec\x1ed\xf8\x9a\xf8n\xe3\xae\xfc\x04\xc0\xb9\x95\xab\xbf\x9e\u007f?\x94\xb4\xd9\xca\xca\x15\xee\n\x83|n4oZ\xbb\xf38H\xdb/\xa3\xd0h\xd5!\xab\xdd\x04\x06}\x83I>\xa9\xd7\x16\x1f\xde\xfc\xdfd\xfe\xe4\t\xe4\u007f_\xe3\x15\bY\xf63\xa3rD\x90wc6\xd3Z\xf9\xb5\xcfK\xe5\x05ج\xf8\xf7\xc6A\x1e\xbf;\xf8\x9fT\xc9\xf8\x9d\x05\x01 GX\x19Kb4\xeep\x00:I9\xe8\xebm\x8d\xca{#?{\xff\xc7X%\xf6\xa5C\xb0\x87KM;\xe1\x8c\xeb\xc2\x00E\x8d({vT\x126\vLa\x9bY}\xc6j\xe3O\x93\x8cѭT\xf6в\xbf`\x10u \xb1\xb9\x00\x84\x95\xed\xbb\xcb\x1fJ\xc4\xdaۃ\xf52f\x841\xf6\xdfD\x9a\xe9\xe3\xae/\x9fM\x1a\xfc\xe8R\x8d1\xb3Cb\x87\x16 @#\x0f\xc4^$yH\"\xb6c\x03\xe1%\x1b߀\x1b\xe4\xc0\x90\xe2.\x13Mt\xbe\xd8B\x9b\xc9l7 \xea\x94\xd5^\x84\xa7\xc8]]]\xbd*\x97\x02\xbf\b\x10\x18\x12e\xc2g^1:\x8e\xb3\tv\"t\xaa\xbc\xc52\xed\xe5=M@f]\xe7M\xba̟D_\x9c\xf1w`tј\xfc\xef\x02\x86\xc1\xff\xa6m\x9d\xac\xaa\x95\xc8u\x1eJw\xa5\"Bh\x9b\x96\x85\xb4O;\x93\x1b\x1b\xfcֽ\x04.\x84\x85w\x893,\xc3eJ\xfbVKm\x04\xc4C2LC\x14yӝO\xd8\a\x11L\xfd\x81U\x95{\xca/\\\"\x88\xe6\xf1\xefK\xb1\th\x81\x9e\x90\xaa\t\xbfbx\x1aZ\x88\xbf\xebLR\x12\xbe\x9a\xbai\xbdO\xc7(=\xee\xb6|\xd2\xed\xa4\xfc\xc7V}\x88\xba)\xf0\xb5\u05fe\x9d\xe0[[\x01\xe9\x1f\xdaP\xf6[\xcf\xf3\xee\xf1n\x1d\xcc\xf3\xe42\xec6Y\x17\x9dK\xaa\x95\t\xbfU\x18L\x13\x9a}\x03\x92W\x190$\u007fڃR:\xa0\xa7\f\xa5O\x00\xfd3Ij\xba(Β\x1fRօJ\x8d\x80\v\xf0\x91)\xa7\x9d\xd4\x16\xf9\xed\xb7\xa6\xb1\xb1\x05\xfb\x06H\x9bI\xfb\x83\xd9n\x9cS\xb7(\xcbg\x98K\xeap\v\xa5\xa8\xef2\x9b\\\x9f\x8f\xa6\x0eoN\xdd\xef\x81\x1dya軚\xf6\xaf\xc1\x9e8\x94'\xe4\x90\xdap\xb6\x0e\xb1%\x1b\u007f\xd7\x01K\xabEE\xa9gO\x18\xc5[:*\xcc\u05f8\x10\x00\xcf\x0fp\xba\x98ⳇ\x04W\xde\x1f\xde\xfa\xfc\x19\xc7\xc8F\xcb\xe4t\xf8\xb5!\x03W\xe5o\xe3\xf6ڧ\x82\"\xb2˲\"Cրo\x88\xc5o\xbe\xe5B\xadJ\xe6d\x86\x97;'K͒\xe0__\xf6\xfa\x9eh\xa1v\xea+\xdb\xf3\x93\x17\f\f\x81d\xc0\x81\x03\xb6\xe4\xc8ލ\x8a\x8b '\x01\u007f\x97\xac\x9c\x87\x92\x86V\x94\xaf\xe1\xb8m\xac\x19\xb3\x0e\xaaI.^\xc5˅\t\xc1\xbc\x1e8\xdf\xf0B\x9f\xe3\xafs\u007f\xadf\x89G0\xd8\xfe8\xe3ռ\x1a\xb2*ʮ \xbc\x99\x14꩐\xad\x11Tҕ\x84\xa3c\xbe\x1b\xb36\x88s~\xf8\a\xa0\xee\x02Jim\xb0\x17\x16\xe9\xb1\x16\xa4xY~\xad\xeaV\xd3)\x89I\xba\xb7ƛ\x15\xaf\xc0+\b\xd4\xe1\x1eh\x17\xfc\xf3\x81\xcaΜ\xc5;]\xf5\x9eE\x9e\xc4\xd0\x1cB\x01AА\x05Q\x99\x89l\"\x94U\xd5\xda\u007f\x86\xf0\xb5,\xdeC\xec)\xfe\x10\xe4'f\x9bC{\xdcKD\x86]\xdap#(\x1c\x05^\xf1\xce\xdf\x1e\x15\xba\xe5y\xf7\x0es=\xbc\x99\x18=U\xb9\xdcjo\x16n\xfe\x10\xf0lVe\x14\xf6u\xc9\xf8iJ+$\xcf\xdad\xc5U\xdd#\xba;\xf5\xb6\x05O\xeb\xed\x9c\n\t?9\xaf2\x9c\v\x95<\xd7;\xb2q>o\tT\xafr\xa4\x1ex&\xd6\n[\xb5\xbb'-\xd2x\xa6p\xa80j\xa7[\xf0;3\x0e\x9cIw\xe9\x8a\x0e\xbc\xb5\x806N?;\x9b\xb1\xa1\x11\xa9K\x06\x9a\xa3\x9a9YR2\xba\xf0v\xf1r\xf9D3\xef\xc4'\xfa\n\xc3\xf8\x99\x0fK\xb6gՂ?h?\xcbr_\xfa\xd4\xf8K&\f`t͡\U0005f789\xa8\xce\xedy7\x85\xd4&.\x9f>\xfdt\xf5\x01\xf4u\xe74\x98ߛ\xcd\x14G\xb7\n\xb9\xee\xdd:\xe8^\x16M\x8apv\x84\xefwڴ\xdcYz~\x1cڇձ\xf7M٪\xe5!\xc1RW\x9bd\xc5;\xb3#\xf4\xdf\t^\x83z\x1c\xd7ʈ\x83\xb4\xf0\xc5\x06Q\x15\xa9\xdb\ft\\\xa3Wy\x02\xbb\\\x14OJ\x1714\xbe\xc7:5\xd2\\\xb2\xfe\f\xf0\x97SXT\x85\xb7\xdd ݓ\x12\x1c\x9a\xf9g\xe7v\xb7\x1eV9\x8fUkX,m\xb6iM\xb2\\\xea\xe8\xb6\xfe\x0f\xc6\xee(n\x8e\x9e>E\x9dI\x0f\xa1 a\xbb\xb7\xefI\xe7i\x85_\x14\x1f\x93\xbd,\x83\x98\xda\xe2\xc7\xea\x1f(\xf7\r\x15;.s\x9e)\xb0=5\x9eA\x9eI\x9e\xe9(\xdc\xcbwX\xa1g\xa7}4Y\x93\x94\xb1\x91Dp\xc44\x97\xac{\x1a\xeajq(Q\n̷ZJ\xb2U\x8dZf\xb1K\xb1\xf5*\xc5x\x00C~p\"\xd2\x122\xaf\xacr\x83#\xeb$!\x0e\x8cJ\x1e\x86\x1d\xe4zZ\x05Y\xd1.\x0e\xa0^|\x12h\xd0\xfd}\xa0\x9d\xc8z\x8e\xc0\x1b\xb2Xa\xe3\x8e\x15I\xa7\x8b\xa8E\xaaXg\xd0t^4\xabR{\xfe\xb3f\x14\x1a\x8aL\xc9\x11y\xd3\u007fp\b\xd1ᚚ\xc9\x06\x001ި|\xb0O\a\r\xde\x142\xdb\xe05\xde\"\f\f\xf2t\xc9U\xe3\x92A\xe9ޗ\xf2\x95@\xf6\xff\x11u\xfb\x1bR\xe4\xa1\xfdP\x1a\x04N\xb6X\xc61\xa2ZN\x06\x81\xfe\xff/\xa8ܨ\xbfx\xa6\xf6\xfd\xaa\x95IQ\xaf×\a\x06\x96\xc3_\x03\x04\x8ey6\x90EK\xf8\xaa\xa1\xa5 /\xbc\xba\xa1\x11\xb5\xf7\xc7 cuD\x96o\xbf\xba\x807դ\xaf\t\xd0\xfc\a\xd6\x1d\xdb|2\xfc\xd0V\xe6\xfcC\xe5\v\xcef+H\x8c\xbd\n\xb5:`\xbew\x9f\xf9\x01i\xf2\xc4y\xdb\xff~wk\xb8\xe5\x93\xd6t@\xcb4OE],\xfb<\xbb\xfa\xff\xc9ͦ?\x0fs\xe6\x12\xa1b\x181-\xab\x84\r\xf2J\xbf\x92\xdf\xc3A\x9c\xb4\xa7\xa8\x8c\xd2\xf1\xfeA2\xe0\xd2-=\x86\xc9t\xed칙C\xc2õ̍\xe0\u007f:\xf0\xc0\x0f\n\xe9\x9dBa\xb3;\x05\xf5W\x17\xe9\x92CE\xa2Ξ\x16r\xff\xe5{\xe7`\xc9&\x89\xc4,\x1f'\xf4\xdbt\xff\xdd\xec\x15\x8e\x8a[8\xc1\x17q\xe1\x89u\xee\xf8\n-(\xc7J\xec]\xbb\x984\r\xa8\xda\xf3\x99\xb2\xebʹ5\xab\xe7\xf0ay\xfc\xb7\nhh\xfaY\xb1\xfd\x99\xb8.\xef\xfe\xcb4\x9d\aj&\xb0\xb6\x1a\x934\xdf\xf2\x82\xb6a\xf6\x1c\xa2\xf6\v\x83q\xcb'(\x9a\v\x855\xe0\x97\x15\x13\x1d\x84\xf2\xb8\x14s\x1a\x8aX\xc3G\xf4jWB\x99\xec\x86\xde~\xad\x92\x85\xc9cm\b۶\x18\x8c/\xfd\x99.\x016\x1d\xcaa\xff_\x1bA5\xbc\xfd\xfb+=d\xbc\xdc\xe3\f>Ĺ_.\x19\xee\xaah\xcf\xcf\xc8\xe88tB\xe1s\xb8\xe80\xc4\x0fHJ\xc6\x1f\x8al\x9c\xe1\xa1l[UH4\xf6v.\t\xbb\xca>]\xc6(\nk\x8c9.\xa0 U\x94A:,A-\x15\xac\xbf\xc6w\xe6\x85yʰ\x90҉\xcb\xf1V\xe0jVU\f\x9c^\xbe\x98\x81}\xb0|w\u007fTH\xc1Ә,\x1f\x03Aq\xc80;,\xf3ZD*\xae\xdc#{\x9f\xbc\xadl\xccH7\xe0\xd5b\x1eRX\xef0C\x81\xc7d\xcduBѢ\xf55\xd2d\xa8=\xcdV\xb0\\T=\x9bQ3\x00\x13\x8b7o\v\xedq\x13A̐A\xfb\x8c\xebO\xfc\xfc\x06l\xeeܿ\xa2\x9f\xe7!\xfb\xad{_uD\fG_\x93\xad\xcerk\xf6\xafߘT\x94^\x98\x90\xa2}W\xd0o)\x18.8\x1a\x98\x98\xac\xa5|gW\x0fP\x95Ce\xeeJ\x9f\xbd\xf6\x9cx\xee6N\xb2\xd3\xfe\xff\a\xdf\x1f(\xc3~v\a\xfc_\x99;\xa2Ξ\x0e\xaa\xfe\xe0S?\b\x8b\x99\x8bW#\x18M\xfc˿\xdf\xd7^\x8a\xdb\u007fS\xe9\xc8\x16\xa1\xcfmG\xff\r\x1bθJ\u007f\x9f\xedQ50\a\x06 \xe5\x99i\xba<\xa5&+\xae\xc8;\x17\x1e\x85\xf1V=\xf4K\xaerU\x84\xbc\n\x9c\x1fe\x0f\x93\xb6\x83\xa0\xe6\xc4#\xf6\x02\xa7,\xcb\x10t\xac\x9eF\xa4jë\xaa\xc2Γ\x1a\x98U\xb2\x04\xc9|N'uL\xa4\xe2\xc3\x1c\xa1\xd1x\xa5\x87&\x8a)\n\xa96wrroG\xe6\xa04\x01\x17\r\xb1\xbe\xdeL\xdbR\xb7\xba\tgn\x94\x88Za\x9f\xa3\xb9\xc0\x94#t+\x152\xe4>if!\b\u007f\x12ϥ\xbd\x1c\x11)Ǿ\xf9>0$&\xdb\xcb\x04q\xa4\xc0\xbc\xd8\xedqJY\\\x92\xa7\xdaI\x02\xd6S(\xa5ˤ7\xb8^\x1c+\x0f\xad'\xd5\xc0\xd6\x19\x83\xc4w\x94ٚ\xeaze\f\x02\x8d!\xf8e\x95\x86-\xcb\xe1\xcfݙ{\x98\x85a\xba\x05\x8ew\x1c\x03τ\xc4\xfc\x18 \xa4\xed\xbdK\x1c\"\xabJd\r\xc1\xe6\x1dLy\"F\x89\xcdջ\x0f\xe3P\x8c\x00\x1cn\x88)\x0f\x87ж\xf3\xdc\xf5\fw\x97-YU\xb8\xff6L\xfa8\"\xb8!ѡ\xff\x19\xde|\xceF\x15\xfcj=c\xf4\xe8Ƞ\xec\xc0\x80\xec\xe0\x81E\x9d\xed\xf6\xc8\xceR\xfa\xd0\xc3z!\xf9<\xabnU\x17<\xa4Qc\xaa\xe6\x8c\xe7\xf0\xda\xf0\xf7\xf7o+\xf1\xfc-`(|ɍ \x87\xc8\xee\xa1O,\xf0\x8at\x1c\v\x16cR҇\x13\x9fӆ\xae\x9e\x05\x8a/j\xe4n\xed@<\x97Q\xa0g\xd8\x1a\x9b\x18\xab\xf9\xf74\xf4\xfc6\x9f\xa1\x9fW=Z\x8dڒ\x929\x99\xae\x9d4cK\xa8\xb6\xd6&{\x9e\xdb\xde}\xee8#Z\xf3X\xf3\x1e\xedWU\x17U+\xe9\xfcQG\xce\xd1\xf9Q\xf3\xdc\xc6\xdf\xe43,\xe4\xeb/\xe0%\x8aEo\x9c\xa3\x02\x8e\xdf\xc3އ\x0e\x14ռ\xe8\x0e\xe7\xf4\x95d\xcd7z}\x04\r#\x1dO\xb7t{yD\"3\xe1\xac\v\xbb\xc2\xf4K\x9e\xced\xae\x95\xf0 {Cu7\xfd\x90'\xd2\r\x1aC)n\x840{\x1e\xcf4\xack\xa6\xad\x90(|\tu(5\xfd\x95u)\"\xeb|\xb6\x14V \xfe\x94Wr\x14\x9e\x9c\xf0e\xae\x14\xf1n\xdd\u007fn\x93\xde\xebXW\x84O\x1e\xa4{\x8f\x84\x92Bu\x99WU\x87\x06\x1f\xa9\x92,2L!\x8d(\x8bK}\xb8\xa2\xe4\x8a\xf6=\xef\xf3\xa3\x86\t\xb2[\xffMP)\xe2s2\xf1\xdbl\xa26%\xe0\x18j\r#\\J\u007fg1a^\x1c9Q\xec\x1a\x1f\x1e\x17.\x99\xfd\xd8F\xce/\n\xf6\ny|x\xa4\xe4\xf8&\x8e>z\xd4|%%N\xa9\x88{\x90\x069\xb4\xb5c\u05c9S'I\xe6#\xe6\xfa\xc0ܳ&\x91QF\xbe\xe5\x8cn\xb6๕\x92\x12\x19\xa1\f!\x1aJƄe\x03\x99e\x91o\x1c},\xdd\xd0X\xd6M0c\xec\u007f\x02s9]\xe9\x98\xc3e\x0308u\xf8x\xac\xe4\xe3\xc1\u07be\xfdB䦂\xc0\xe2@h~T$\xc5%\n?\xee\xcf-&\xec\xb9=\xa5\xdd\xc4Es\x9b\x02\xa6nϨ\xdb\xecf'$\x82\xf6Є`9\xe5\xcfw\xa7\xa3\xdf\xe5\xfbvȒ\x9cߖ\xd3\xd2\xe2$sNy\xb17zԯ\xe93.ɉA\xbb>\x85\xf2c\xbe\x9f\xf2\xb1,v\x99\xfcA\xe8\xe2\xc5?p-?\xda\xf5#\xfeG\xcev˧\xa6hm,\xdd\x14Qv\x96\xa6G\xa2=KԾ\t\x86\xffn\xbck@p*\x83;r\xf4\xdeQ\xfb\xfc\xb3w\x9cZ\xba*ړ\xf8Ǥ\xcd\xe6\xf4 \xfa3ν\x93եwR\xf2\x01-\x85`Qz\\\xefӧ\x8dv\xe9\x00\x81c\xf4\x8f<\x80s\b\x00\x89\xb8\xd0*)\u007f\xe2\xc6\xdf%m\xe7\xbfgNܦ\ueeadIy\xb2~#\xe7\xe5+U`\uedf9~\x82U\x8f\xce\xed\xf2\xaf獫l'\xe3\u007f-\aq\x12\xf4'\x12\x89\x84֣\xa2\xd5\x01\x8f\xdbh&ɚ\x02,\xd8B\xbfL\x13\xa4\a\xc0<\xafg\xe4MIM\u007f\t\x00٧\x00\xe5\xfb\x8e\x12\x18\b\xe1\xce\xc2@nf\xe0\x00\x86\\\xa0\xf8}\xc1\xb4d\x1e\x1co\x98\u0087\x89\x8c\xed\x8c[\x176[\xaeB$\xac\xba9-\xb7\x9eR]Ղ\x93\xe2\x06\x06T\xcd}\xedu\x12A$\x9b+\xc1eҢ\x144\xc6k\x00\xfa\xbb\x8ev'\xef\xea\xe9\xfc\x9f\x96^K\b\xce\xec\xd2\xca\x1c\x186\ra;8d-x+\xb5\xd5\xe1J\a_\x86u\x15_2\f\u03a2G\xaf\x01\a\xcar\x03e=\x1d\x9d?\xc0\xdc\xfb\xdb(\xb6\xfd\xfd\x03\x81\x8a\x13w\x87\x94\x1b//\x94(\xc7\x02_`\xbd5\xfaw\xce/\x9e/+:X}\xb7Z\xfcX\xd6\xc2.ruȐQ\x96\x80\x97\x81W&\xed\x03\xdceUs?\u007f\x81z\xf0\u007fN\x83\xd2|jj\x04\x1a_\xc8Mw31\x87\xe4\xc7\x11\x1f\x0f#q\x16J[u\xffWF\xf0x\xf9Ԏ\xb0}\b\a\xday}M\x85r\xbd.)r\xe8\xbe1+\x89\x1b\xb5\x17)\t\xf3\xa5Qn\xb5\"|D\x1f\xc2U\x17)^8s6\xdc\xfe\xed\f\xfdc\xab\xc4#\xfb\x92\x0f\xa8A\xec;}\x97/\v\xdf\n\xa3\xc2\t\xcf\x1b\xb9\xd2?\xef\x1b\xd6K\u007f\xe4\xf0\x80θĻ\xecG\x9f\x9f\xfaMg\xddi\xbd\xa0\x0f9^#0\xf3\xcf;؎\x97\x12Jb\x18\x8b\x8fꘙ\xd8\xda\xf6#\xb2<\x9f\xe8\xebM\xebz}\x1etum\xfe\xb8k\xfb\x8ep\x87\x96aS\x16\xac\x98\xae\x9e\xd3\x16 2\xf3p\x18.A^S1\x9e_.wG\x1fao%7\xae,SUW\xa9\x94Օ\n7\xe7md\xb4%E\xf6=,\xdbP\x85\xde\xea\xa9[Ұ\xd3劚\xaa\xf5\xedl\x8a\xed\xe7\xf1K\x90=3\xba>h:pZ7\u007fן\x1f\xbbg~\xff\xde#\xef\x8a\xd4;\x1cxD\xaft\xdb\xdfO\xbb\xa6\xfe|\xd9\xdetҺ}\xd4\xd5&Y9\xfd\xe7\xe7\x14\xbaƮpbuU[]\x90\x89\xf1\x98T\xba\xa2\xd8ι#\xc2\xe1\xaaU\xd6Fo\u007f~\xf9\x16y\xceե\xaa\xa5j\xd8\xcc`a\xee\xb2\xea\xe5\x85\xcb~\xaa.;\x15&\\UB\xc1D\xae\xc8\b\x19\xbd\x93<\xe1\xa2\x12\xf0\x03j\xc0\x9a\xc15y\xa4уo\xe5)]\xba\x8d\xef\xb1,\xbd\x84\xb6+\xe8]\xc7*\xd1D\x8c\xac89\xbbż\xe2\x9a\xf6\x15\xa6\xa0mS\x8a\xddT\xa5I\xcc\xf69⺹\x03\xe3\xec\xdb\"\xaa\xfe\xad\xc4_KKgh\xc5\xf0&\xc3\\^a=\xa4\v\x12X\x86\xa7\x1e\x10\xc6\xfd(\x89\x1cu`\xee\xb3\x1d\xa5mgO\x1b,\x8bӉ\x86\x02h}\x81\xfb\x92\xdey\xa8\x06$\x99\x03ے\x12\xa4$\f\xdfE\xc6\xfb[\xd3\xe9b\x92\xc7\xe6\f\xb3\\\x1dڊ\xc8xl~[\xc5\xf0\xbe\x00\xd1\xd3l:\xb2\x0e鈼\xf6,\xb5\x12\xb3\xdd\xcdg\x03\x9f\\j\x81\x1b\x11\xadgY\x13\xea\t\x8e\x88'\a\xb4\x1c\xe5&f)\xe1\x8bGL|\x9fƭ*\xe1\x87\x1cQ\xdb\xdcpr\xa5\xa3\x83~\xee\x1a;\xceZ\xf1\xb4\x92\u007f\xc3I]\xac\xdd\r!<\xf9aP\u007fB\xb7I\xee\xf3\x0eb\xb8CUxЏ\x1c\x0e\xf6\xfdEg\xff\xc6C\u007f\xff(\xa6<\x15\u007fg\xb7d\xef\xdb\xd7РrM{LWҮG\ah\x127\xfc9\xb3W\xf7Fɜ,sR\x06\x85\xcbߕzH7\xd2zϙ\xccFrcHK\xfc\xff\xf8\x1a\xdfo\x19S\xae\xe1\xe3Fa0\x19\xc3\x16\xadz\xb2\x81\x95h\xc7C\xaa\x1c\xce\xd7:+\x06/\xa1\x9d\xaf\xd5ҭ\xfd[-W\x98\xc0 p\x02\x94\x04\xc0\xd03\x14v\xe8\xed\\uq\xc7GG+ԛDX)\xdd\xe0\x9e\x03'\xd6\x06\xe3\xb7&M\xebu\x19Ɨ\xd3Û~E\xad\xbcވ\x8cW\u007f\x17p\xa7\xf6\xdb5\x02J\xd9pG\u0560\xd3\xd2\xf4\xb40\xcc\xea\x8c_\xd5ԍ\xaa\x8e\x00\xdfqW\xffĘ\x94\x98\n\u007f]5\x98x\f\x92\x00\xc9\xf6\xa0\x9e\x16\xe0\xf91\xcbyu\xd2&\xe6\xa7\x0e\xaf8Hȏ'\x13\x9f\xfe;\xa4\xd2@\xbbq\xa2\xa6٘\xec\xee\v\xaf>\xc4\xea0S|\xdb_Ae\x91g\xae<2\xcc8\x10\xfd@\xad+\xe9\xb15\x94\t3\xfbgKp:\xd6\xe9\xf0\xacE\a\xeaL\xde\xffBv\xffK\xaf\xae\x8b\x89j\xfb:\xe2\xbd\xee*&z\x85\x94\xdd\xe0\xa9\xfa0\xe2\x0eV \v>\x0e\xa1\xcdG\xb4X\x1d\xfeCJ\xa3\xeaI\xf2O\xb2\xf7Er\xb2\x03\xb2\xf0\xe3\x10\x13W\xdf\xed\xc6\x02\xedb\x95$\x9fW+\xc2^j\x92ɒ\xac\xfb\xfb\xf6\xf5ϖ\xf6\x9e\x10\x88\x856\xe0\x1dH\xd3X#18\v\x8dˌ5\x98\x91\x15\xd6\x03\x14\x97ԋ\xa2\xf4\x96\xd9`\xa2֩\x8ewG\xaeU\x17\xca\x03,\xf0\xb7\x9f\xfe03\t\x8f\xa0\xab\xec\xab\xf4\xda\xe7̵1\v\xc1\xd0Q\x99&\xc8\x1e\xa2\x9cg;!\x8f\xd0]v\x9aX\xe6\xeb~0\x9ca\xf6\xb9\v\xb9\x9b\xc1\xd5\t\x8f\xf8\\\xbdM\x81\xb8\xfc\xa1\x86F4C&h\xe2\x99 \x8dV\xd4Ӿӗ|\x8e\xac\xae怙w9\xea\xa3}\xc1\x9c9\x8d/\xb5\xedH\x86\x14Y\xbc\xb4\xa5\x9a1\xea\xe6\x95˚\xb5W\x05\x85(\xd4u2ig\x16o\xd4}9\xa8~!V7\x1b\xd6;\x9d:H\xa9\t\xf3xǗ\xd7\x13~\b㲿\xa7\x8a\x0fv\x05W\xdcز\xfbj\xa1\xcb\r\xfbw\x8f$\x19\xe2\xc4kʪe\x9a\xbe\x881Z^\x9dW$S\xd7+ļњ,\xa9-\xab3\xad\xd6\a!\xeccm\xee\x99h\x16\xfc\xba9\x95\x8e\x9b\xa1%\x06 Q*;%\x81_\x96\x0f\xee\x00\xa88\x88FV(\xb3\xd5\xf8\x86\x9bs\xf8߷f\xcc8\x14d\xf5\x9b\x9d\x17\x9f\x10\x9cشgm5@@7V։\xb5\xc9!)\x91\xde\xc2^`\xac\xd6#m\x8c\x13܊\xa5\xbb\xbe\x87G\xb1k\x82!\xbd\x06\xe3\x06y\xc3u訦\x19\xb3\xe4\xd4(+\xcbq\xfe\xd1:\xde\u00ad\xd1D݉5/\x80\xcbb\x8d\xb3w\x19\xed\x9e\xeb\xf0\xf2\x89\xf9\xd4\xc8b+\x19\xedb\x0f\x16\x9f\xf8ᎁ\x9a\xed\xbb\xd76\xce}\xebH\xafЛ\x87m$\x9c\x9ate\xd61-\x1eě\n\xee\xfc\xb5\xbc\xbb\bG]i\xb9ܘ\xf0\xa8\x99\xe0\xb9$\xbb\xbaQ:n\x1apy\xeb\xfes\x86ǩ\x89\xe9B\xd9\xe0q8\xf9\xa6\u007fH\xafr-;\xa1-c\xffN\xbf*\uf68d\xa5\x12r\xb3J]\x15c\xc4\xf2\xf3\xe8\xfdG\xd6\x1bY\xf9\xce\xeducyUk\xdbu\f\xd4\xca\x18\xbfDQ\xa0\x1a)\x8d\x9f:4^\x9c\x9e\xadK<|\xe7XE\x95ޚ.\x14Hx\xa3r亞\xa9j\xc9\xf8Κơ\xf1\x86\x05\xfb\xe3-\x9b]\xfd\xc9eU6\xa5\xff\xa3x\xacbk\xae\x17\x13\xe4\x1e\xa0_lo\x9f\x18\xd3\u2c2fuv\xa6\xb8oL\x0e\x94zA+\xd4$^ҕ\\w\xea\x02%>\xea[\xa1P\xa0\x8fG<\xaa\x9a\x99\xa92\x1a\x95\xd3\xe2\xf6\x8f<\xbdU\xc7\xe4\xe5\x8e\xeew\xb0\x95\x9c\x98\xae+=ܧT\xf32bwݠwx\xb6\xbd\x9f\xf2\n\xc8ay\x99#G\xe5\xe5\xc1\xa8\xe7t\xc6s+\xc7s\xaa\xe4\x8a\xca\xca\xf1\x0f\x96[\xf2\xabU\xd1Y1\x8b\xcdn\x1e,\xa6,(\xa74\x9c\xf7c$\xa1U\xccS\x99\xeb9\x93\x91\x9dB\xe7\x8c%\xc5Z\xfdH\xab\\R\xe8\xb7\x15\u05ee\xf5\xc2\x19m\xe8YZ\x84,]\xe1KH\x92[\xdaE\xb7\x10ÿ\xc7\xe4/l;\xdff\xbd\xeb\x12\n\xe8\x9f$\x806\xa8\xc2![aB\x85r\xef\xeb\xd6d\a\xb7Z\xf5\f\x8c\xccV\xcfzoْ\x88\x04\x81n\xd0H\xef\xa5\xf6\xa5\x1dK\xb0V\x16U\x85%\xb6\xce\x0f\xd2\xc3)G\x92\x8eB\x99$\xbeE7\\f\xfcYֵT\xe4\xae\xed\xb8\xc7\n\xf5\x06Kg\xde\xdfɷ;\xa27\x1b\xef w\xaf\xa9Bh\xfe)\xf9k\x85\xcd\xcd4\xb2\x8d\x97\xff\xe9\\\xf3\xb3r<\xc2zu\xc1\xabt\xabS\xe5o\xd7\xf9?(\x18#\xad\b\"\xa4*G\x84\x99\f\xb6\x1d\xba\a\xeb\x0f\xa7\xaa\x19\x8bF\xa1\xacn\xe3D!\xea$\x01S\xabx8\x90\xa0;\xad\x8a\xc4\xcf;\xc5(\xba\x93\x00\xa5~\x1b\r\xaaWou\xba\\\x18\xcb\x1d\aHt\xda*GĞ\x0ev\xca:\xaa\xd3[\xe3\xbeL\xd7r\x98\xde-\xa0\xab\xa9y\xfcG\xd0m\nk\x83-6K\x17\xbf=\x829\x01\xd8D>\xb9Gk\xf6\xbe\xe2\x0e\x9baD\x18\xeel9\xe0\xab*K2\x83\xcd\x14\x8b\xedJ8Os\xfc\xd3\x1e\xbf\x8f\xb2\xf5P\"偙\x13\xf3bN\xdb%\xae\r\xbe\x16\x04p\xee\x06xc\xc8\xccN\x92&a\by\x8d{\u007fM\x8blƪ\a3\x1e#L\x8dmN̕&\xd5>\x18\xec\xf4\xb34w\x12\xcd\x10\xd8ՙި\xc3\x17\x86\x96\x18|3\x91\xe0\xe4\x96\xda}+\xade\xd5\xff}\x87\xe8\xfe\xa6\xe1\x8d\xf8\xfa_\x83\xc8\x10\xd7,\xbe,A\xcbL\xe8\xe3u\xb4[\x99\x9a\x9c\xf9\x1dϲQJ5\xda'z\x99\x95\x0f\x9a@Nԝ\xcfZ̉\xa7ED\xce@\xa3(PVdl\x93\xac\\8N\xe9&,\x9c\xb0)I]\xb6d\xab\xe6\xa4N\xf3\xfe\xcf\xdeY\x168+\xbbʞ\xea_\xbb\x06w\xa0\x04\xce\xfb\xec\xffu⥊\xec8\xd7#\xfb\xe4+\xf31\x02d\xed8s6\x81\x92\x03\xf5\x9eǬ\x1b}壯\f\x9f\xe2\xd1\xf4Uy\x8b\xf2fc\x90\xc1\x99\xb8+\xca\xd4\xfb!)\x8dȦ\xb3\xde1\x9b\xb7\x15\xbe[\xe7\xb2N\xeb\xb0\xf4\xea\xd7}3ǮIG\xac\xdbu]\x8e\xdbx~\xde^\x85ʔ\x984\n\x9d\x99\x9bqd\xe9\xe6\x98\x03\xb8[\x1e>\x94,{\xec\xae1#\xf1^3\xaa\xefID\xef\x9b\xeb=\xebq\a$\xb1%\xf2\xa0ɥ\xc2\xf3:A*\x81\xdeCg\n\vR\xc9\xc1\xc4@\f\x95B\x94\x86H\xfd\x8e\x98@\xe4!\x1eTn\xfd\x9b\x15\xdaw\xb6l\xe2\xcd˭\xf0\x15\xd8a\b\x14\xb1]\xee\xcd\xf3ɬ\xb2\xc3\x11\xf4\x03z5\x13\x9b\v\xb5\xd2\x18\xf1\b{z\xdf\x16\xc5\xf11\xd2\x04R&\x80\x8fl\x9e\\Wџ\x94\xfbg\x82\xf0\x98\x00\x92EIّt)\x87\x1e\xa2\b\x848\x90R\xa8Tp*\x03YM\x9bڋ\x9bFfR\xbe8V\x97Y\xc2bJir\x165Fč\tN4e\xacgH%\xa7<\x90ټ\xa5\r\x84\xbc\bn\x8aj\xccc*v\x84\x9d<᧼\x15 /\xef\xab\xe3\xe2U\xf6\xdbjao.lG\x05\x8b\xe5\x92vA\xb3vP\xc0\x02\xb2\xf2\x04ؠ\x84Z\xabj\xaa\x89\xfb\xea9\xb7IdA\xe0\xe7v\xeaƉ<\x9f\x8f\vjO\xef\xeb3\xb5\xafj\x1a\x0f\x895\xcfKh\xf4i\x03Mt|\xb2\x06\xa8\aen\xdf*=-A\x00B\x8a\xf3\x98\x05Q\xf5\xf8\x95\xf0\x1e\u05cd.|\xa7\"?\xa9\xe3Ïs\xb9\xee\x9d\xd8\\Z\xde\xe5\xfb\x1b%\xd2\xfe\x1bg\x92\xf3t2^L\x90#;K\x9e0>;\xb2\x1f\xc3\xce!\x90\x93\x12\xf9SSI\xd5\xc7\xfc\x04!!\xaf\xd5\aH\x87>\xa0S\xd5\x14\xce|\xbcB\xbeϵŵ\x1eQN\xaf\b,$\xab\x16,J\xef\xcb,\x01\xad\x9fy\xf3a\x8e>A\xa2\xf0\x02\xf7\"T\a\xe0S\xe8\x83M\x9d\xcf\xd6\x0eK\x96\xbe\xfe\xd1\xed\a\"\xc3I쫈\x9c+\xa9;;\xa5Ӽ\xe8\xa5[\xef\xe9\xe15\x90\xad*^\xe5\x9e1!\x89\xdd;\x00m\xc9--?wb^e\x99\xa2Ci\xe8O\x15{\xe5*\x82\x9d\x03\xd9N\xf8C/\xfa\x8d\xef.M\u007f\xe3s'\xf8\xce\v\x1f\xb5\f\xb6\xf4\xd0f+v\x9aS\xf8'\xeb̘\x88\f\x81\x02\nT\xebkO\xf4H\x8cL\x96\xc4T\xdapR\xa4\x8fs\x19\x87#2\x04\x1c\x94Y\xdf\xd6\x14@\xb02\xbc\xe6\x81N\xf76^T\x9a\xbf)u[\xcc\x15>4(n#\xe3\x11*w\x9f²Jb\x9e\xd2\xdd\xff\xae$Ȥ\x95\xd6F\x0f\xfaTxM3\x04\x13,\"&\r\xf4ܴy\xb6\xcfWm\x1b\xc2\x01\x02\xc7\xc0\x81\xce\f\xe7\xaa\xfek!o\xbf \xaa\x84\t\xe5\x16\xfa,\v\x12˒\xd2e\xbe\xaa\x8d\xac6\x99G\x8cG\\r]U2%\xb6\xe88\xccWH\xef\x85\xe5\xb0\nC\xfd\xd9\x1c\xa2\xc4Qo娣\x96)\xb3\x9f\xc0*\xe9[zb\xc32\xe5n\xa3\xae\xfc\xb5ʹ\xa8.CL?\x9b\xdcg\xfa\x9fl\xd32\xdb\\\xf5\x94#\xa7.W\x98\xaa\xf2Y`\xe9\x1d\x1eWG\x81\xc1>r8\xf4\x8e\xa6\x13\xeee1\x1b\x8a\xba\xcf\xfa\xeej\xae\xc9B\xf3\xcd\xe3\xfd\xf3\r\xff\xd5U\x95\x98\xbfq8\xa5`{\x1fl_d\x98\xe79)\\\xbe<\xad\xba\xfe\xb1r\xc1.-\x95\x0f\a^\x88\r\xa0BtR@\xe4\xbb͓\xc6f\x9d\x048\xf1w\xf1\xd1\x05\x01<_I\xc8\xee\x82\xc0\xad\x18\x05a\xce\xc0\xb7\xc2Ɵ\x10\x18̢\x04\xf8\xb3(\xc1\x81\x11C\x9bU\x82\x03\xdc/)\xab\\R\xd6\x0e~\xfb\xde\x1f\x82?~ۨ\nÿ\xb7dZ\f\xeb\xed\xabZەGƐ\x83\xde\x18\x11\x91\x80\xfbrg\xc2\x0f\xd9\xf1\xb7Jp_\xfd\"}\xfbIe\xcf\xf5g\xa6\xac\xba\xae\xbd̒\x166-\x17\x04G\xee;\x9b\xd1\xcb\xe2\x0eK\v\xc6>\xa9\x01$n\xdf\x1c\xde\xd6\xed\xf8\f\xca+\xff\xb2L\xc1[\x80\x91o\xdd\"\xa0N\x9f>\xf4\x89\x8d\xf1\xb6\xafe\xeb\xd0Y\x91f\x1a\x82\x9bC-\x9b\xbd\x02\\Qz\x84\xf4%\x81\xecse\xec\x1d\x1dg\xb4\xa7\x83\xac@\x9f\xb9%\xed\xa9\xf0\xf3\xf9\a \x16I\xf3\xc5\xfe\xb6^\u0604\xad\xbc\xcf\xfc\x8b\xd8\xf3\xb9*\xcdӬ\x88\x95\x1c\xe5\xec\x1eD\xe7\x80\x06\x98<\x92\xad\xc3\xf5\x8a\xe5!\xaa\xd80\xe9O!\r\xf4w!\xf5\x95\x86\xa9ޞ{\xfb\u007f\xc1\x1b\xc0\xbcD\xebS\x9a\xe3\xec\xd3r.\xa0\xfa~\xa7\xff\xfeB\xb6z\xe3\xe6+\x85\x1fB\x1a\xeamA\xea*\xf6+y\xbd\xaf\v\xfb\x1d\xd9(k\x00\xc3\xc8\x13\xf8\xf5w\xeb_\xed3d\xdc\x1f\xde\xe2\x16V\xae\xbby\xfe\xd4\xf94/ܺ\xc2\xdfY\xad\x80\x99hs\x92v\x84zJ\xde\x050\xefa\xe1\x14p6\x1b7\x9f\x9aX\xbd\xde6\xa4\x9e\xaf\xc5\t\x9e\xe9y\xc5n\x01\xceo\x15\xa3\xff\x9b}l\xa7\x86k\x01\xf2\x83\x8en\x9er7\nyyh\x10\xddD\xa5bK\xa5\xf4S\xebOR5p\xa58\x1f\xec\xa7.T\xaca[\f\xab\x91Y\xbbhKHCJ]c@\xb9/\xe5\x89s\x01-\x1d`ϼ\xb8\xa2\x8bE\xb6\x8ea\xa4Gk\xa6Yr\x9a\x01ʇ\x85K<\xf3E\xc3\xc1\be\x8e\x9bW\xf0V\x03\x90RP\xad\x85\xfct\xacG+$\xef\x8dд\xf7 \xb4\x8a\xf1\xe5R\xb0\x93b\xa0\xcd͇\x1eP\xe0\xc7TE[j҅\x8f\r\xde\x0e\xf4\xe8\xbd\x10\x18*\xb1\x85\xb5NU\xb6\xa6Z\x9a\xf2{\x01\xa6V<\xca\xd5\xf7\x8e\xf4\xb6\f\xad\x1cQ\xf1\xe6\xca\xfe\xe0\xad\xd8w\xfc*\x93?\x9bӃ7N\xea\x95\fs\xfbO\xa3\x82\x14\tj\x93$\x800`۱\xfb\xc1\x97/\x1c\x0e\x91N\x9cK\x1d\x9f]ϫ\x92]\riZ?;\x1a:w\x88\x81\xd9\xfe\x1f<\x82\xc6\xf4\x87\xa7\xf5\xd3\xfa7҆\xc3҇\x95\x1f\xbcߦ\xb4٨\x1fnV\xeewl\xe7}D\xc5\xc9A\x84%\xfcyv\x8f\x98\x04\x88+\x84w$,\xc6\xc8Xl\x1b\x0f>\xdd/j\xfd\x1d1\xc3'\x0f$Y\xa7\x10F\x9d\x97\x0f\xf5\\\xfc\x83(\b\xfd\xf8\xc8AЃ\xea]x\xef\xc1i\xf1Zk\x90\xb0\xe3$5\xa0\xec\x05U܈\x88?\x03Z\xaa\xb5N\xfe\x03:5\xdcZ\xbf\xbf\x01\x02C\xe6\x05'Z\xeaܤ\xca}\x1f\x14w\xa1\xa7\xda~HE\xe3\xde\x01\xadVN'\xf3O:\xa9R\xc5\xfd\x18\xa8|J%\xac\x12\x14ء\x18\x02\xcc\xd4C.^\xe0\xb9\xc7ڎ\xe5`\xcb\xdag͐(3!\xb6\x8fa\r\x8c[0ɘ\x0e\x10»\x00#\xa0\xa8c]j\xa1\xdb\x1b)\x98\x81`\x12\x1b\xef\xd2rsJ!\xa5*j\xb6\x05\x12\x13c\xf5\bf`\x14\x94\xbdo\xcb+\xe6\r\xae\xef\xed\x1d\x19\x19\x1b;mx\xa8\xbc\xb8x\xff\x81 \xb5\x1c2=\r}\bJKo\xab\x9b\x95\x19\ra\n\xe5\xa9\xeaXN\xe6\xba-\xe1\x04\xbeK\xba\x03;\x14xL@@\x1d\xc1\xb6\x89\x94a\x1d\x8b\xf0,\x04\xe2\x89\xc8\x11\xa8\xaa\xccu]\x1dϺ\xa9\x9dU,Y\xf6;I\xeda\xd8˯\xac%\x16y\xcb\xc2\\\t\x88\x1c\xc0#\xb92\"\xa0d\xb9\xc1\x11\x89aE\u07b5>P\x95~\xaf?nŠv]wZ\xc4\xef\xccY\u05ec\x02\xce\uf3b1\xb0\xf0\x80\xb7a)\x88\xe6\xde3\x9d3t2\xd0\xf1\xe3\xef\x0f\xf7\xadT\xfe\xfd۷MN\xef\xf86=\xed\x9c?Cݹ\xd3ސ\x81\ad\xff}1\xf0\x19y\"9\xf5gV\xe0\x15\x0e\xca˚!Z1\x03\xb1qz&\xdfW\xba\xb1w\x95\x8d-f\xa3R\x9c\b\x84C|K\x0f\xc2>\x1d\x0e\xc1\xfe\xa8'\xdfcw\x00A?`6$,\xd8|C\xc3kٝ\xed\xe40\xe9->\\\xf7#\xa8˽\xc8\xf7\xc2\xd5\xef\x9f\xf45K\x1c\xef\xb0Li\xd2Tom\xf1\xcc\\[کNJXu\x8e}ꕵ\aۡ\x18\x92x\xfd\xc6\xc3[@4\xabu\xab\t\xabg\x86\xf7\xf7\xf2\xfb\xa1\x00\xe2@\xc0\x1d\x8b\xfc+\xfa\"\x80\x05\x93R.\x13AS\x90T\x9b+\xae\a8S\a\x80\x99\xb13r\nP,qݕV^\x84f\x05\xba\x00\xdd\xd3b\x99\xf6ڝ]d|k\xb0\n\x1axtQ\v\xdcä=\xa2\x13:\xe2\b\x04qC/Ѿ\xdfK\xfa6\xe49@\xce\x11̦\xb4\xff8ۃ\x8d)\xaf\xe36\x06m\xd5k\x8fϋ\x1f\x85\x12z{\x89v\xfd\xb5\xb5\xc5C\x12\v\xeb\xedG\x13\xad\xfa\x1f\xd6v\xdb̠d\xf8\xbc\x85\rlC\x11\x88ȇ\xe7`\x97h\x16\x96\x95r\x80\xb1\xa4\xae\xfc\x00.\xbaS\xa7\x1eF\xdbm\xeeإ>2푈\xba\x95n\xfc\x99\\\x8fy\n\x96\xbc\xd93\xc3k\xd8\x1a\x9043b\x91?\xef\x82\xecs\xcdNj\x97\x86\xe4\xe9\x87\xfaT\x85\x88\x12\x99\xe6%\xd2a\xbf)\xb4\xf9\xf62\x9f\x10\xb2}\x1e7\n\xfd\xba\xea I\x94\x9d\xec\n}A6m\x85\"o'\x82iLI\x8c\x1d\x9eI\x0f5\xf9\xbcy\xe0\x97\xe3?\x00\x81\x84\x87\x81|\xaf\xd6Ue-\x87Ң\xcchb\xeb\xe7=Ϫ\x06\x13۱_\xd2\x02*'\x80{\x9d\x88\x10h\x9d\x1e3r\xbc\xea\xd0\a\xb3y\":\x96U@>\xe7q\xc2\xdb|J\xd9\xff!\xec\xf9\xb5\x80\x95\xf6\u05ce\xba\xef\x98\xed\xa7\xb472\x10ZΝ\xbc\xcd\t]\x82p\x1f\x1b%}\x05\x8e\x19\x80,r\t\xe4T\x0f\x83\x96\xe5āe\xb3u\xda1't\x0e\x84̖X\xfbm\xe4٩X$:Dl>\x80O\xc5\xf2\xea\xea\x05\x1e\xf3\xfe\xed\x85KX\x1d[\x92;\xb6\xf4\xe1\x844E\xcbh!\xc8BA\xad\xcb\xdfj\x17\xaf\x13Z\xc9<|:f\xb1\x1b\xa1\xa2\x03\xac^\x03\x8bO\x9b\xefh5\xad\x80\x01a\x95 \xf5\xf0\xfc\x80\x84\xaf\xf9K\xb2\x93\xa9\xbd\xe5\x84u\x1b\x90\x85\x9d\xa4/b\x03z\xact\x9a\x80w~\x9b8i$\xf9\xa8oo\xa3\xeft\xb2^\x043Q?r\xd5\xedLˊ\xcbf\xac\xf7o\xcb\xcd\bI\x0fn\xcf\xf5H\xd8\x15\x99\xcd\x1di\xd9qUgg\xea\x8d\xe5)Ӈ\xa6\x14i\x1e\xf5-\x1aa\xab\xfdui\xcc\xcb4,a{\x9e n\xbeY$\xb0\xb8\x9b\xf9H\xedkJ\x19c\xd4\xceJ\b\x018@\x89t1A\x92y\x8f\xea\xfb\xa58\xa3RQ\xce)(\xe7\r\xc1qr\xfe<\xb5\xc2\xe9\xab'T\xc4\xff\x942QUE\xbe\xf3T\x88\xa8\x87\x14\xbf\x17\xa2\fԫ\n\x9e\xe9\xd2*DWV-J(\xf2\xf4\xb8YWZ~]\xcf^\xd5\x05\xcco\x1fP\xe56{\n\x9e[\xa5\xc4\xe9=\x92\x05\xf2\x00\xdfʤ\xc3\x05Ɣڗ\x8b\xf2\x89>\xfa\xa2\x19\xf9\x82\x1d\xe1!\xc1\xfe\x88C\x05\xb0/\xe19\x17\xa0\x99\x86ky\xeey\x99r\xadL+>;\xa3\x9aʒ\xb1\x98\xaf\xb5[\xe3/\xf0\xb1\xf8\t\x05\xcff\xf7n\xeb\x90\x03\xda>\xd1O<\v\x831\xe8#\x14r\xc9\xcay\x17\xeaw\x85\x00\x1970\"\x01\xa2\x90\x13\xd8a\xc1\x1aYM\x80\xb80\u007fIb\xbe8H^-r\xe4i\xad\ra\f\x05\x9b\u07b4B\x8c\xe2\x90\x007\x91N9\xb3!\xb5\xf8gI 2\xeb\x83\x04iOB\x1f\xb9\xac\v\xba*{Ȫ!\xbd&\xbaF\xdc\x10s\xa8\xc1S\xa1\x9f\xef\xe1\xe8mt\xd3*V\xc6\xea\x91ch|\xb5\x92ʢ\x8c&\x10E=\xa3\xadE\x04\x96+\x82\xd3BJ\xa0&Q\"/q\xc2d\x91\xe5\"\x8b8Yn\xd9\xfd\xa3\xb6\x84\x80$\x9e:\x10\xef\xef\x19\xa4\x8aW\x06\xbb|\x0e\xa68\x9d\x8b\x9aa\xc1%\t\xe3F\x8e\x82\xe5\xa8\xeb\xd6\xee~\xbd\\\xd7\xda\xd8\xea\\\xe3 \xca\x04\xb0\x05\x81\a=\x0f\xf6\xe9\xa1w\xc0\x8e\x16帙\xe4\"\xaa\xe4i\xaa4\xe0\xc8}B\x95\xa9W3\x99߬\xee\xe3\xee[o4Yf\xb9\xcc\"\x8b\x1d\xfe\xd2\xd231\x03D\u007foڔ\xbd\xc0r\xc1]C\x83\xaa\x84pϼAyl\xb0\xa2k\xc97S L\xae\xcdj\xc1\xaa\r\xf5@\xd9>\xfd\xf9s\xfa%\xff\xf1\xea0\xdb)u\x11\xb5A\xba \xdd9\xfd\x88-^{\x1a#x\xf8/\xa1ަL[\x16`\xe20/\xad\x96(\x89\xdc?¨Y\xcd)\x86؛a\n\x8cwI{\xe2\xadd\xcddC\b1\xaf\x95\xb6\xd9\xdd\xf8\xedڐ\xdaG\xf0\x8cd\x85\x12j\x89\xbc<\x96\xe3\x80\xf1\x1a\xf2\xa4R\xaf\xeb0\xf0*eYC\xb1NsI(~.\xe4\xb8\x11D<\x81\x9fou\x0fwϪ/۟EP\x9bq\x02\xdc\xf7{\x82\v\xdbcۉX$6\x02\xe3\xe2\xeb\x1f\x13\xd0i\xdd\xe0\x8bE\x06\x00\xf3\xec\xf7\x98\x82<\xa8-\xb6\x8d\x80\xb5o\xe5mp\xefV\xf3\x17\x05tX\xd7\xfbb\xd1K\xbdͻ\xf9\x0e\x91\xa5\x17/\xd5mjh\xf5\xe8\xa8o\xa9\xe72,;W\x9é\xccx\xbfI\x96gƭ،90s\xd9\xf4Q\xf0\xa6N\x13O\xf2\f\xf7 \xa1H\x1eP\x04\xb21\xe8\x98\xfe'\xbc\x01gK\xa4,-\xc8\xde\xcc\"\xf8z2\xf1\xf3ט\xdam\xa5\xb4\x84q\x12\nZ\x89(Ez\x92QNe\x96sD\xa4\x12\x11\x1c\xab\xa3=Ն;\xec\a,c\xabP\x98_\"bpy\xb1\x1e\aI\fk<Ɖt\x92,_\x82\xf0B\xa5\xa6\x8e\xea-\xf7q\x92\x98\x97 \xa0\xecܐ.\x98_\xb6\x15\x06\xd3\xd6\xff\xafh\x8b\"{\xd8\x18\xf9g\xf2G\xdb\x11j\xae\xdd\xe7\x14\xe1y\x10\x06\xe1\xc2\x15\xad\x87;!X\x8c;\x8a\xc6\x1b\x83\xfc\x16C\nH\xa8\x92*g\xf6r-\x90\xfe;2I;\xb2\x81\xf0d\xe3\xfaT\x92\xd7X\xea\xc4%\x12\\\xddf\x17T\xac\xf7\a\x95\x9bǚRs\xa0\xdfm\xf9\x10\xc7-\xee/,\x8e\x1d\xcb\xc2;U\xb0\xbdU\xb2\xdb\xdf\xf9\xb1\x10\xc4v-{\x85\xa7\x93=\x95nO\t9\x82\x00\x9d\xf2k\x80\x1f\x11U\xae땐\x9d\xaa\xee\xe2\x93\x12\x1e\x04\xee\x8b\x12\xe1\xff(\xfan\x17dz\xb6Ii\xfe\x13\f\xfe\xc3P_\xed\xad\r\xa6k\xad\x90a\x8a\x15\xb76d>*;\x9f\xef\x02\tڻ\xeb{\x95V\xda\xe0\xd5\xfeq\xd0\xcdS\x82\a\xfd\x1b\xea\x87\x02[\x98B\xeeO\xefl]yW\x9e\xe9MRZ\xc1$.\xa9\xdd%\x98\x92\x9b\xf8\xaf\xa7qj\"\xb6̙\xb1\xdd.\xef\xdd9*\xed\xb7\xab\xa7\a\x14\xab\x9dH*\xee:\x9cH\xa8\xc9fc\xa1Ep\xdf\xe6R\xb5\x96o\xa5\xbe\xb9Q#\"h\xd5\xe2tL\xc2\xc9\\\x97V\x97\t\xb0\xa8\xc1Of\xf5\xda\xe2\xda\xcf\xc0\x94}\x05=Q]\xaf\x9aL\xbd\xa5\xf1\xbeH\xaf\x97|\x9b\xbf\xb9\xad_~\x99kϣ\x94\xc8\U0004f214\x94\uefeav\xeerți\x82&!\xaf*)\x81\xb3\b\x1drI\xf5\xec\xd2b@\xe5쪖%M5Нs\x93!N\x9b\xbd\xeb=\xd53h\xc4%`\x81\x1dU3\x06\xb2\x8e\x8f\xf5yV|\f\x8e\x8d\xe4p\x88\x0f\b\xd3k,6\xae\xd6խ\x8a]+{\x13\xf6\xf4\xc6EΗ\\\xc0\x13\xd4^\xd9\xd3\x04\xca\xd6\x03yn۔.*\x1dQz\x95MO\xb3\xf3տ\xff\xe9\x10D\xef\x11\xee\xdd'\xecT\x95\xffS\\\xa20\x98WU'5\xfb\x94\xbe:\x99#\xe1h΅A\x15%\xcaEZ\xb7ʜ5b\xb5Ҝ\xab\x146M.\xfb^q\xe7\xd5\xedӶ\xdaX\xd7\xdb(\x92\xa6\x021\x85\xa7\xd8]l\x87\xee\xd4(4\x17\x1c\xa2\xa7A\xd4\xe6\x98\xe2\x8dҢ\xedۋ\xc0\xc2\x02\x13\xadVXkv)^ۚ\xdcn6\xe3\xabe\xa5\bQ\xa2~\xee\x80q`\xeba4E\xa4\x9b\x95\xad\xd4\xdbl\x11\xd9Z{!\x9e\xb3\xce\xdee\xa7ٹ\x10\b\f\xc2R\xbb\x96fm\xa5\x84wš\x17|\xb5\xf8\xdaN\xf6w\x00da{%Q\xf4\tc\x9fy\xd8\xd1g\x91\xfdR\xb3\x9e\xa0\x9c\xc5A9z\xef\xa0X\xb5\aBN\x9e|5\xf9ّ\xb3\x11\x87O\x9c\xfb49_w\xec\x9c\xce9\xa5\xb5\x90\xa0\xaf\xbb\x10\x1c.\a\x99\xe8\xe5\xa2\xfff\xedo\xfa\xb1(\xfb\x1bD\xdf\xe6\x99\\\x13\x03\x1cEPl\x9d\x9c~\x8bP\xbc\x84ˢA\xab'\xa5\xf7Ǐm\x9d\xb2\xa4\xc3 \x10|\xc5\xd6)\xcc]ˍ\x83\xda1\x8f\xdf<|`){\xd9\xed\xf8y?\xcbJ;|Ɠ\xe5\x15=\xed\xd8\xc8\x04\u007fJ7\xb6\xb1M\xe5\xe5\xfdMA\xbe\xbd\xef~we\xfb\x82\xa4\x8dH\xf8\xadb^;+\xe6\xce4\xd8\xf7\x96\xf5T\x1b\xb3\xe2\x891\x1a纲ѳ\xea'ZNWR\xa8f\x10\xc3\x1dZ\xa6x\xa9\x92\rR\xb7\xcd\x1e\xaf}\x1e\x93\b\xcc\xf7\xd4\xcd\x1e\xabE\xd7ڢu^\xc0\xf7\xad}\xdb\r\x99\xac\xb0\x17\xff=ּ3\xe4\xb1CA\xeclC\\\xe3\xa3'E\x0eΩ)\xd7.\x8bb.-\xfa\xc7\xf7GB\xfc\xb4\xee\x9c\u0604\xf2\xeeHA|ZE\x87y\x8c˭\xd3y\xf1H\xe7\xdc:\xff\f\xfb$\x8d\x86\x13'\x8aX\x85\xf6v\x1f\xc93&\xbby\xf3\x02VQJ/\xb9\xb9\xff\x9aI^\xe9\xd3\xc5\xdb\t\xea'4Z\xef\xffY[\x19}>\xfcēn\x16\x9f\x9c\xd8\xeb\xc4ѭ\xe6\x19ţv\xe8\xab\xfeTo\xe4w(\xf2kxǂ\xd5 \xcf\xf2Կ\xad^gWzۼ\xb8r\xc61k\r}Pc\xf0.f\xfaŝ\xe9\xf6\x12\xfbL@\xe4\xb7^\x83-\xdd\xd07\xf0pj\x84o\xa9\xb1\xbb\x9crͤ\xf0\xfaDⶴ\vppKt\xf2\x81\xc2\x03r\x14\xfa\x8fU}\xca$gmJt\x90AP\x83\xb4\xc3v\xad\xdd\xcb\f\x1ch\x13*ٲ\xe5͛-\xf7\xb5\xfdZ\xd0v&\xc5dH\xabj|4\xb7P\xc6\x0e9\xa0\xf3\xfb\xb1\xde?]]\u007fz\x05w\x1b\x18\xdb\xee\x02 \x11\x00\x80\b\x1aw\xf8\xff\xa3L\x9b\xe1\x0f\a\x98\xc0\xdaz\xcd z\xc0\x85\xe9\x1e\xb8\xa0Щ!\xd5\xf8.\x05+',z\x9cb8\xfb\xee\b\x83\xa7\x0f*߮$\x8b\xde\xea\x86\xcejΆ,\x82\xb57\xeabC\xe6\x85\x01\x15\xe3\xeb\x92o\x9e/\xda\xf7]\xc1E\xach+\x1e\xba\x12\xb7#PN\xaa\x19\xc8:\r\x1f\xd2\xc7<\x9fD\xe2S\x10_S4\x10;\x0e\xce\xd6LG\x1f\xac\xae\x99\xdd\xef\xb3\xecV_\xfd!G\xb3\xa98\x97\x88ʜ%\xb0\xf7\x02\x1d\xadgq]\xb0wX\xb9\xdc\xc2\x1b\x18\x12\\z\v]\x88B\x97W\xb0\xfb\f\x87λ\xd7z\xfd\xecTS\xf9v\xa0\xf4l\xd3\xca\xf0\xf0\xca\x10\x85\x86V\xb8+#\xfa\x8aᡜ\xaa\xb5\xa7\xa5\x06\xb7\x02\xe6\x15\xfa\x1f\f\xf2L \xf4\x94\xbe\x15\xbeW\xff\xa7\xfe\xbaϛ=\xddu5\x0e\xd2f\x1e\x86]\xeaY:\xdd5tgq8hĢ)\xa3\xaa\xa1\xa8+\xa9\xdb<\x1e5d\xac\xb4P\xaf:9\xdb?tun$\xe1\xae{`\x1c\xe7\xfb\x1eY\xac\x10\xab\xb4?!\xc5&]ܳ\x92\xdfp\xa3a\x81\x86\xbbR\xb2\x1c<\xd4ұ\xa5nk}\xcbDpzawY\x81\xd6$\xd6z\x15\xfa:\xa1ߓ\x89H\x19z\xec\xe6\xd5\x11\x1b\x83\xef\xafdY\x9c\x10Gj\xb1a\xefr\xcd>\xf1\xef\xf7q\u0378E@\xca\xd8G\xe3\xac4\x8d\xde\x13\x9b\xbf\xda+\xee\x80\xfc\xd4\xdb\xed\x93\x02\xb7\xf35|\xa8\xd9\"\xc3E@\x9f\x9f\xe2\xe0\xcf\xe28\x1f\xfdx\x8fy>\xd7\xc1X\x03qI\xa7\xa63%\xe54&\x8d\x95\xc5Ueѣx\x8cޜ+\x1f\xd6\x1bV[\nW\xb8\x0e?\xd2$\xfeU\x8c\xa4\x8b\x997\xa9\x8a\xecH\x9d\x95\xec\x902\xb1ܘ\xeem\n\x87&\x1a\xe7\xae{}\xb43\x03\xf1}\x9d\xbd\xf7\x8c\xd7\xf5\xa2\x1d\x96`R\aU\x05\xce\xd5=}ii*\xf6\xa3\"Q:\xb3\xeb, !8\xa9\xf3\xa06\x8bܤP\xa5'\xe0T\x94s\xa4\xeb\xd6rvw\xa6\xac\x83M\x12\x00DKOx\xef\xdb\xc9inM\x82'\\W\xa7\xad\tmF\x93\x88\xd9f\x8aP\x82\xaaO\xc4\x1cV\xa6\r\t\xbb\xe6\\\x84\xb3\xd3\xca`\xbe\x0e\x95\xe3\x91\x13%~\xf2J\xc2\xf9JvCm\xa28\x8fk\x1dv9\xbd\x05E\x8a\xb7g\xddfv\x9eG١\xcew2\xef\xb10\xf1$\xdb-\xa7\\\xe6\xb4\xc6I\x98MD7\x9cO\x16ۺ\xd2\xe3\xadrU\xfa\f\xca\x14:Qڃ\x9b1<;\xd2\t-\xab\x98\xeb:\x18\xe1z\xeb\xaf\xfa^%\xf1q\x90\xbcB\xbeZK\x8aQD\xeb\xe8\xc6{\x05җ\x96x\xc7oe%\xb4*p\f\xd7\x0e\x167|\xb5-t<^\xddxأ\xd0bT\xfe\xed*n\f\x95\xe5}\xceۙo\xd0\xca˞\xd7(\xf3\xdd\x01ﴲ\x83\xa7\x04\xd7\xda\\\xb6\x9f\xa7^(\xef\x1eZn\xc4\xd13\xa0f\x82\xf1\xb1Z\xa4,2\xcb\xed\x87:\x83\xa7\xaf\xaa\"\xba\x17\xd0n\xbb@{\xf3\xb6\xd58,\xa6-\xa2^\xb8\x9dw\x12Q\xb3\xb7\x83R\x1e\xeb\x93\xe0\xed\xd0E~\xa7\u007f\xea\xeb\v\x05\xc0'>\xd1\x15@^U\xb6>\xff\x92\xddW5\v\x80\xc0%3#X\x895\xf4\x06\"߶縵\xe8mw\u007f\f\xae\xb7\xe8#,\xe8\u007f,\xb1C\xf58閅\x9dW\x8e\xcfO=Ļ\xe2\x86\x18\xdcH\xf7\x1b7\xeb\xe3=ζ\xc5\xcc\x1a:+\xd1\rᓞ(N\xe5\xac<\xcd\xc2n\"];٬\xe1D\n\n\n+\x87M}\x04\xb5Y`\xd6\xe7*L\x10\x97\xe7vl \x00\x8bq\xc1\xaa\x87\x9eZf\xa3\xfc\xb6u&\xad\xca-\u007f\x98\xa3A8\xb3M\xb2\xfb\xd4\xee\x80\xc0\x10\x1c\xb7\xe6\xea\xd6\xca6u\nt\x13\x102i{\xe65\xf0\x95\xe2\xfe\x04\xc6k\x10\xbe\x1c\xf7\xf9\r\t\xc1v@\xbe\xbe\xe5\xd9Jg\x1dv;1ph\xb7\x02\x04P\x02u\xda2[\xebp\x8c\a\xbfC\x91\x95Um\xa3\x97\n\xa9^H\x85\xbfn\xaa|:\xcc}\xe5\xea\xf4J\bt\xa0\x1e8\xdd\xe12E\x9e\xa4\xb0\x9el=\xebU-\xbbӭ}\xe8\xd5\xdb\x10\x930\x15\x13\xe4\xc4s\xa9\t.>Q\xfd\x16\xa0\xa6\x1a\xcfx\xa7\xa0T\xae\xe6\x19\x16a7$\xeem\x12\xfa}\x1c\x89;aÿ\xffmk.\xc44\xd3\x1e\xdc\xe77\xaa\xf1\xb6\x03\xb8Kt\u074b\x94B\xfb{\xfc\x10\xde\xcf\x1f\xf3\x9e\xb9Z=\xa3\x91\u007f\xfb+\xf8I\xa1\x17\xfa\xa6\xe1\xe4\x97\xf7w\xf4\xfd\xe9\x93oN\xa9.\xaf\x90R\xf1\"k\xaeO5h\xb2\xbc\x15a\xb9\xbdC\x95K\x900\x1bO\xaf\x8a\xfd\x1fP\xab$\x84/\xbb{q\xcbu[\xc1\x12\xd6\xc0_f\xeb_\".\x90w\xe4y$\xec8)\"oX\x88;3\xc04Z'\xe4\xf2\x93\xa2G&\x9e\xac\xf4o\xd9\xec5\x1b\xa0\xf2gȬ\t[\xe4푂p\xaex\xa3$~VlYy\xd2?A:\xa7O0O.?Iv\xc2{\x05\xb1\xd7~\fl\x96z]%\xf2\xbe\xe0x\x81\xf9դ\xae1\x9fG2\xf5\xb2\rͯ\x1e\xf74`\v1w\xf9\xa1\xb3\xb9\x0f^\xf8\x0e\xb1\"B\xf6~\xd9\xce<\u05cek\xd5h\xfa:\xa5\xfb\xbf&\xf59D\x83ɗ\x1f\xfc\xd9@\t\xf1\xba\x81I\xb8\xc8\xe24<\xecl\x9cC\"\xed`\xbf\xc86\xe7\xfc\xa5\xc1\xde7\x16Ћ\x95콀{\uf545\xed\xa7=V\x9f+\xaf\x95\r`\x97\xe1T\x03\xf8\u007f\x0fU\x100딎\xa0\xb1s*Oʏ\x1b\x12\xed\xbc\xb0tj\x8d\xe1\xd4y\xe82\x96Ϡ\x8a\xc2|*\x05(Tw\xd8l\xa9d\xb6\xc5b\xe2nQ/\xc8\xcb7Z[\x9bi}\x0f\x9ahím^\x89\x9bW\xa3L\xb6m\xa7?\xe4\x01,/okk\x02X\xc5Ft\x06\xbb\x15\x02\x87\xb6\x13\xbb\xb1+\x9d-\xcf\xe4{V\x9a\xaa\xbaX7\x8cNFd\f\xf7\x14\xfd\x17\xce39\xc4ȑ\x85V\xbd\xd1{\a\\\x8f\x14\xa8o\xcc\x14\xaco\x1f\xfd\xca\xfd\x977*\x0f\x1f:\xc4^\xcb.f\x9d\xe2=g\xf6\xa3\xad\n;:uP[\xb0u\x9d+\xcfZ\xea\xe5\aP\x04\xc9\xeeϸ\xe5u~({\x9c\xb9\xb4\xb7\xcb\xcd\xca\xfd\x9e\bR\xa4\xfc\xeeʑг%\xa4?\xceL\xd8\xe1'm\xa3O#\x8d\xc8\x00\x1b8\xb4x\n\x80\xf4\x0f$\x1aN>\xc0|\x92ߖ^\x1e\xb9\xaa\x1fy~r\a\xdb\x16\x89\x8f\u05eeۙ|\xd6,y-\xaen\xfb\xbfQ\x11\xe9\xa0ߖB\xd3N\xcf\"n\x0f\xf7\xfc\x06\x8d%;Ts\xd3\x03\x95\x11B֭f\xec =3\xe8EXX\x997\xa4W\x17\r\xf9\xc6s\x14\t\xec\x94\xff\x12\x98i*(*+\"AC.\xc2\xd5ڥ\x18\xed\xb8+\x9d:\x8f\x82\x9f\xd3WR^m\x91SQM\xc3\xc0\x9f\x18z+\x83\f.\xa5 \xeesS\xda\xe6\x10!\xdaF]\xfe\xfbbZxL\xb7}N\xc8\xe2N\x8f\n\x81\x01$\xeb\xd0pgv\x9d\x87E\x9e\f\xe9mA~D\xaf\x8c\x82Ph#\xe3\xa2.\xe40k\xb3\xc3\x0f\xc8㲧\xc4o\xe2\xb7n\x8d\u007f\xf3?\xef\xcd֭l\xff\x0f\x8d\x89/\x15Ox\xbf\xf9$]\x93\f\xd7L\xa2`\x1a.\\(\xa6P\x00\x82+:rj{\xd4x}cO\xfa\xee\xeb\xfd#V \xa2\x06\xfb\x1d̥)\x9d:\f\xcf\xeef\xa0\x9e\xa8(ý\xf2Q\x1e\xea\xf0 \x1c\xf4ǀ\xde*\xa9\xca[\xc3յ\x9f\x92\xac\xe1~\xc4-`h\xf8\xc01):\xbf\x88\xc3\x05\x86ҙ\x9c\x18\xb7\xc2n\x0f@-\xc8\xce݁\xda'>c\x13(\xb2\x9f\xf1\xef\xcf>,\xa6\xa9\xb1\x91U0\x8e.Q\x9f\xee\xaf\u007f\xee\xdb/\x8c\xa4sU*\xb6k\xa2ޑR1&&;{\x9c=<\xa4\x1e\tQ\x01\xa5\x16\xb5\x90dÅR\x15\x18%\xa4\x95\x1d\xa5\xb1R\xaf\t\xc0\xa4\xbd\xc5\xe2\xa7F@\"\x12\x89\xce\xf8z\x86\x86EG1\xe3M\xeb}<*:Q\xdf\x155\t\x83\xd5zW\x9a\xc1\xa3\v՟\xa8\x90\xf8D\x16\x8b\x0e\xd7Kj~\x1f\xdc\a_\xbe\xf0\xff\x1f\f\x1e\xf3\xcf\xff\f\x81\xc2[#\xa9\xd7\xc7\xcc\xe1\x10\xbcZ\x06\xb7\xee\xda/\xc0\x84\x109XMF\x9d\xa8ۇ{\x12\xe0\xc1\xdc7\xf2\xfe\x1e\x02ș\x90\xb1\x9cک\xe4\xf4\xcf\xe2\x1b\xb7+\x8a\x05h\x86\xb3\xc3\xc3\xffsDf!!/\xd7\xc5\xday\xc6\xd9\v{ܸ\xf4\xd0=\xf5\xeeg0<\x89\x15\xcc\xef)\xe58\xa04\xb0\aT\xecMʦzj\xb7^K\"\x19\xc3\u007f\x03\xe2$L\x9f+\xca\u070f\xbf!^\xa5\x86\\*\x92\xfcd%\\\xc1\xff%\x1e\xa0\x8aN\xb9\x18\xccs\xbb\xe4\xc6$\x84\xcd\xcb\xf8Z\x1b\x96\x94:˼\x18\x04\x8d\x86&\x85,\x13\xc0t\f'U\xdc}\x94~\xb4#\xce\xce\xe2\n\xbd\\\x11\xe8\xb2\xe9\x80\xf4ɝ\xb8\x8c/!-\xecmY\xc2V\xf3B-Ei8ɷ9\xac\xd0\xc92<\xc7\xc8S~N\tK۩\xc4p\xd3'\x87Â\xa0\x87\a\x80*\x91\x15֜\xd6wcWF\xdf\xf6c\xa7\x1e\xa8\x9eK?\xc2ZAJ\x10\xd9ƺ\xa5p7Է\xbc\xf3b \xd1i\x87\xf8\xf6\xcbKL\xd2`]\xc7\xebgɎp$l)\x87q\xfc\v\xb9\xa2\xc1\xb1ҍV\xb1B\x1f\xa6C\x8f*c\xef\x80\xfcK\xafirz\u007f!\x913\xe8ڇ\xb6\x1c\xb6\xb3|0\xe3\xdfF\xb3\x8a\r`\xf4\aZ\x9bB\x04\x99Q^\x9e\xf6z}\"!թM\x8f\xae\xf8r\"\v\xbf[\xde\x19R\xb2\x8c\x1a\xef\x91\xc0M?\xed\xc7\xf0\x0f\x86\xb8 \x13\xbd\x1f7\x96\xec\v\xe1\t\x87dLd\x1cH+X\xd3\xe9\xf7Tp\x9d\xbb\xb6\xf5\x97\x1f;\x9d\x8c\u07fbW\xb5\xcf\xcf\xdb3\x8f\x86k>j\xfa\xa7W]\xa0[\xf7\x05\x01\xfaт\x97QT~\xf8\a79\xb5E\x9d<\x9br\x05\x95\xa3\xa3jO\x02>\xc23\xafSѧ\x8aB0\x8fn+\xf9\x0f\\q\xc4\\Xh\x1d\xc0;ed\x91\x87\xe0I\xe6x\xf6\xe56\xe5>\xf1\xa7 \xa1\xa1XC\xa7\xfd\xa0V\x1dr\x01\x93pN\xa6F\xaf\x13\x95K\xef|99QP\xe7\x98\xf6\x1aba-\xfd~\n$\x15\x02\x91G\x16nX\x90\x80?:a.p\x01f.\x1f\x1e\x02\v!®C\xe1f\x88\x00\x84߄Z\x0f$\xf9\xdc\xef\x80\xfa\xbe\x17\n\xea\xe1\xd6ݞ\\؉j\xb6\xb4\xab\x8drv\xd2b\x9b1\xfa\xe4\xc0F4\v\n%B \x10\b\x1f\xb9B\rk\"\xbdr\xb2,\x1d$\xa7\xf4$\xec\xc9\xfd\\\x897K\x95\xad5\xdes\xf7\xf3n_\xc4\f\xbe\xd1+\xf5\xf5\xb1\xa3\x15v\xb5\xbd\xa7 \x8a\xf2P$\x92ϩ3\xcc/\xa1\xa5\x18x\xbe\x1d>J\x82\x86aw/\xcb\xf2T\xcei\xbbX\xea\x86F\x91N\xad\x87)@\x1f\xd7\xcc\x1e\x1eԅA\xfc\xa1\x02\xf5\xa4K$r>\xfaG\xd7nc\tQ\xeeR]\r\xa1\xbf]e\\\x15C \x10w\x10^\xeaʺ\xcd\x00\U000117afW6ު}LB|\xf9\xe8ұ\x99\xa8\xb361\xf3\x9dR\f\r\xb4\xd1pn=\x92\x87\f\x1d\fb\x10\x94\x1d>@k\x06\xb3\xfe\x16D\xb6R\xd7\xd7ƌB\f\xc0\xedM\x19Q\xfb\x81\x9b\x82n\x85h\xe0\xee\xa9\x1e5\xeb0\xad\x16qb9j\vC_\xc0~P\xeao\xd6\xf5\xf0a\xad\x99ʀ\xc01\xf0\x94>bש\x8a\x91\xd3\xdci\xd6v\x86\xff\x9b63\x19u_\b\x9c\xc9;fj\x1e\x03\xb8/1'y\xb0\x199\xb7D8\x9ba\xd1 \x05\xad\xban+\x16.Z\xc0\xf2\x18fq\xff\xb9>\xc1Z\x0e\xcc\xc3\xf3T\x90\x9a\x16Οά\x04\xf5s6\xa7\xea\xe9\xcb\x1a\r\xd7\xee\x1f\xed\xa0w\xa3V\f\x1f\xac@)\xf8\xc1\xea\b\x81\xf6\xe0w\x171\xa8\x11\xfe\xbb\xb3`\xd2h\xef\t\x03\xa6|Zw\xb2\x90\x8b\xaa\x86\xf7U\xb3\xffi\xf3\xb7\x0f\x1ea\xae\u007f{\xf8]\xe7\xb2\xfe\"\xaa\x97\x105\v\x88X\xf7 \xafM\xf7\xa1DXfl|6\xcfb\xa6\xc93\xcf\xd2Z\x1f=c\xa1d\xf8dž/\xc0\xe2bWO\xfc\xd0\xc5\xe2\xdag\x16\xc4L \x15\v\f\xd8Á^\xb0\f~Їo\x94;Lx\x9f\xd40e\xb7_\b\xcaZ\x9a\x92,\x99\x90\xbbCõݷ%\xf7\"\x98\xc4\b\x87\xb9\x11(\x1b{\xc1\x16\x9a\xcc>\xd4\xed9\x826\a?\xc2\xc1\x83\x04\xa5\x03\x98\xbc\x05\xfc\xfb\xef\x85\xe9C\x87\x8e`\x06\x19\x19/\x87\xa0\xc6}\xbdG\xd7(\x10\x01\x06?\x04\xa4\x00\x11\x94\f\x9aZi\xb4\x17\t\xb96\xfdm\xfd\xf2\xb9\tv{L\xaf\xc73\xecZ\xab[a\xa3\x90x\xb7\xca\xd9\xfa'\xb096\x12!\xa7\xb41\xb62\xb1\x17'\xe9p\xbd\xc0\xc8ͥ\xe6[\xa4˔\xc6\x1e)\xcd)\xb1L@ƙV~+r\x98\x9e\xae2\x9f\xd5ʑ\akk\x83\xb59\xf2\x03Z\xed\xe6\t0NG\xbb\x85\x86\xcb2\x835r\xd9aQJ\x16\v\x0e\xc3#\xce\xfd\u007f+\x8e\x16Z\xc1,\xaaO\xa8\xe9\xcfh\xedO\r\xe8:\xfa\x1a\xd6X\x15\a=`\xa7O\xbf\xe60\x88\xc1\f\x8e\x14ߋ\x1c\x1c\x8c\xbcW<\xf2N\x1d\xcc;\xc0\xca{[\xb3\xbe\x1e\x9c\xfc\x1c\xd3e0\xc5^\xb7G\xe7\xc8\xceݬ\xc0-{\f:\xbe&\x1cܖ\xf5V\xa1\x16\x19O\x1e=t]\x86\xf3\xbc\xb5\xc7\xd1\xf64ƏKF}1Q\xacW\x01P\xcay\xe2\x13@O\xa5~k\xf7\xf1\xa6[\xef+\x81\xb9c\x9f\x11\f\x04\xc0\x14D\x99\xc6\xca\xf7\xb7\xde@\xf9\x8dk,\xbf\x15UB\xd4#ű&\xd6rC\x8c\xb8e\xd6,\xe4/at[\x10XOd\xebԚ{-\xfe@\xf2a\v\xa4\x14\x19i` Q\xee\xbc/\xb0\r\xa2\x06\xa9B\x82X\xee\x18I\xf5HU\x88,}\xa3Ȥ]\xb4\vOy\xaa,\xae\xaa\xde\xed\xf4\xb9\x1btGd\b\x14\xb7\x8a\x9f.@\xe7\x87뾄\x8c\xac\x00\xf6}\xefۀ\xf9\xee\x1a\xc7\x0f9S\xadU\x12\xafW\x00\x81!O\xca\x1a\xa2ҕ\xa4\xe9`h\xc0\xba?\x9b/\x98=\x9f\xa4\xf3\n \xf0o\xc7\xf9\"\xf7\x99\x1a\x06\x8f:8\x82\xf8A6\x02VK\xc6#\xa6\x91X\xae\x1f\xb6\x88\xa0\x89Iq\xf4q\x8fK\x85\x8e\xed\xdcy,Ѹ\x83:^PAu\x10~\xdf\xdd\xf2[\xb0\x01\xb95\xa0\x80\xdf<\x8b`d\x91\x99l2u\xd8\xda\x1d\xffv\r6\x9d5b\xd2\xfd\v\x99ǭ\xad\xb0\x81K\xd3\xf7v\xeb\xfc\xed\xd1\x16\x8fo\v\x88\x80\x8a\xae\xcb\r\x9do\x13\xa3\x99\nIѐ\xa58\x10\x8a\xe8\x100\x8a\xe8\xc8M\x8c\xfc\xf9\xed\t\u007fS\u007f\xc9\xd8\x17\x12N\x1f\xf6\xfc\x05\x96\xd4&Q\xfd%\xc2\xc2\xd9\xf8\xb6\xb6x[\x1e\"\xba\xa5:\x86v\xcbE\bb\x0eJړ\xf50\x90\x94K\"\x90`\xe4G\u007f^\xba\xa4\xe0!\xf1ܾ\xf5\x143#G\xb2\xcc\xc7\xfd\x8bWT\xa0b\xf8Aý'\x9a\xf2\xf8\xef4\x14I\xce\xc3Io\xbe\xa15\xf5K@\xb3d)ƻ\xa2H9eW\x1a\x99`\x9c\xa3p\x92[\xcb\xf1':\xed\xf1q\xce\\}\xde\x01\x8e\xc74=\xee\xb0@D7\u007f\xe0Z\xc0\xf3\x13\x99w\xb6\x16Y5\xe5\xe6\x9e\xde\xe9\x1b0\x146\x93\xff\xbeӘ\xcd\xeaВ\x81 \xb4*)\x03\xb3\xe8\xec\x80\xf3z\xb7G\x16\xeaS<\x01.F9\"\xe7\xe0Ca\xce!z\x84\xae\xa3\x8a[\xbe~\xc5P>\x9a\x92ݴc\x03\x91\xd8ZB\xff\x8fb\xcc4l\x1e\x10\u0092ٟ\xe3\xdds\x9f\x9d\xeb\x9bԳܻY\x89\x16\xa7\x81j(J\x95\xb4՜\x1b\xb2:\x88qZo%9\" \x8c\x15\x9f\xc9\xe2\x85]c,:\xb7Zr\x15\xf4\xa0PA<\xd3\x05@p\x11\xc4/\x8e\"\xfb\x9c\xc6\xd4\r\x9f\x8fg\xcb]\xbf[u\x11\xb3o\xc5W\x9c(\xbeAǸ3aI\x83L\x1c/\xb1\b\x8f)^j\xc1\x8b_\x13\xd9\xees\x13\x93\xc7;\x91_\x13\"\xfe\x80\xad\xd5\x14K\x95Y\xb5\t\tm\x11Ą\x9a\"\xb8oj\xe9\xcd=1H\xf6\x9ef\xc6Τ;F \xcf\xd9\rU\\V>\xb3\xf0\x1f{\xc0\xc59Yc6J\x9c?x\xdèW\xf30M-\xab\xa57\xd2\x1a\x1fؙ\x9e\xa2\xeeHrV\xa82\n\xb7\x91\x14\x1dI\xea\xb4\xee<\xfb\xe0\b\xeb\xe2\xe6(\xb7\xdc\xe6\xb9\x15\x06\xed\x0f\x9c\r5uywjBt\x85\xcb\xff\xe5\x1c\x8a\x06A\x91\xb0\xaf֏o\x17\x0f\x86\xf5\\e\x1b3Y\xe1\x8e\xfa\xb5L\\\xeeʺkl#s\xffs\xd0\xcb\u007f\x94\x0e˯\xcc\x1b\x14G\x13\x0e\xe8b\xff/k\xe6\xd0\xc4BZ0\x96\xf2r\x15\xceD\xb9h\x85D\xd8\x1aq9\xe1\xfeW\xeb\xf3\x9f\xd2z\xb3C\x1d\x8c\x1d8 @\xac\xc9\x13\x00\xd3C\x17\xea\x054\x91\x84\xb6\xe2\x9c\xf1\x15\x8a.7\xa3\xc2U\x9b{_\xa7\\\xd1\x10\x80\x8f_}#!|z\x94(12\xb8O\x87\x8f\x9d\xaf\x04\xba\xb1d\xd9@\xfaC?\xf9x7\xee\vN.?y\x93jvGC\xf4\xfd\x02\xe5Ҍ\x8a\xb9\"\x05\xfbʚ\x14Y\xbclC\xaa`\xbd\x86\xc82\xeb'%\x12\xc6\xf7\xec\x80b[iܫ6\x87\x89\xe9hLF\x92\n\xad\x19HO]\xbd\xfe\x84\x86\xde\xe7\xa3\r\x8dM\x15\x9d\xe1\xee\"\xdb\xdcU\xed\xd21\x9fP\xe0\xd5\n\x0f[\x10\xf2\x1e\xb9\x8d9\xaf\xb2\xa4\xc8\x13\x06\xfb\xfd\x96\xd2\xc2X\xac\x9d\r\x14\xb9|U\uebf5\xea\xc3B\xd8\xf1\xb9\x1c\x89\xe9 S~z|.\xc24\xfc\xd3\xefTP\xbe\x83{.\xf5\xa5b9\x8ep\xdey\xcc-\xbe~\x00^z\xac\xb3\n\xfa\\\xfa\xd6@\x15J\xa8\xcaX`n\xeeb\x10DWpk\x0e9_c,\x1a:\xb12\xe3Ya\x01\x11\x88\xcaFμҦ\u05ed\x14b\xd41\xba\xfa\xf6DLc\xf6a\xf5u\"ҝT\xe9T\f\x937+ov\xfd\x04z\xa0\x1fӀƣ\f<\x8en\xcbsiDw\x1e١/\xb3ţ\a\xc3\xfa\x9b\xb1\xf0\xd5\x133mW.\xc9{2+\aا\xac\xee\xcbt\x92\x17b\xf0\x80\x95\xc5J\x9d\x82\x04\x96c\xd7\v\x04\"\xea\xbd\xcb\x059\v\xc5\xce\xc3\xe4ʓ\x19\x9b\xa2\xf3\v\xb9\xd38\xe3lɭ@\xb5\x9cѤ̤%\xae>i\xf0\xeb\x16\xfa\x8e\x05\xa7O\x17\xe0\xf4\x01\x02\xc7\xc0\x81\xde\xd9\xdf\x14\xf6~\x97\xd9}$\xb9\xe8\xfaf}e\xa6\xf3\xe7]\xa6Է\x0e\xbb\xef9\x93\xa49y2\xa96WL\xe2\xba\xff\xf8\xb7u\xe5S\vMv\xfa\x89\xc6\xdaq\xa1\xd29t\xd9)iG\u05c9\xe3\xe80\xa6\xce\xef\x876\xf8\xf2\xa5\xa7G\t-0I\xe5\x00#\xc8\x17\x19u\xe0\xc9\x131\x97\x8d}ŭ[c\xb4\x02\xc1\x93z\xa9\x94\xa16\x12WŁ!-pi?\x16K\xa1\xa4\xa4\x9c8\xfe'`\xb8PCrr\xbb\xf1\xec\x19\xd3\x13\xc7\xcfp\\\xfc\x8d\x9bB;\xf9k\x16\xc9\x03i\xfe\x85~8\xd4߯I\x88\x87{'\xd1D\x05\x89\xf1\x83\xd1\xf2ʪ\xf1\x9cJ\xe0\x13\"am@!\xafB\x95\xb6S҂\xb1\xb1\xfc \x8f?\x1f\x1f{\xbe\xe3\x1d\x01\xe6ł\x1ak}\xee\xa4Mq\xbaW\x85\xc5\xceW\xde,/\xbf\xf5\x1b\xa0R+O\xd8\xecC\xfd[\x12\xc6\xfc\x91Yw3|c\u007f\xf8\xcd\xc2\xfc\xe4k=}\vQ\xbe\xff\xb6\xdbc;Y\xa94\xc0\xe5\xe2\x19\xfb\xf6\xce\xcc\x15\x87\a\xfbed6n\xaa\u007f\x91\xed\x93\xfbگlc`\xe3\xd7,\xbdɩߤ@\x15\a\x0f7iM\x8f\x91=\x99\xcb\xe2Gs\x9e\xad4g\x03\xea\xe7\x85%\xd6rG\x8e\x06\xa6\xddp\xf4H\xea\xaaC\x1c\x03\b5p\xbe#\xb3\x82S/ڝ*\x91\xa6\xe4\tϓ]\x056\xf2\x0f\x83\x1f\x1c}\x17\xfcN\xe0x\xfe\x9c\xbc\xed\xbb\xa1\xcb\xf7\xbd\xbc\x8d\x8b\xcbEr\xaeP?Sr\xca\xeeb\xb7\xfd\x8fO\xd6\x1c{\x16Q\x80\xadp\x89\xc9\xd8h*L\xb5\xfe\xd4\x16\x0fb\xce\xfd\xef\x8e\xcc\xfcY\fS\xebn\xcb\r/\xfbBZ\xfc;\v}\xd6m~9a\xb94\xb2\x99\x1d\xac\xa2-\xc2h\xac[\x87\v\xb2\xd7\xf4\xe9͎\x1fϭ\x96J$\xc51\xb3\x05\x98\x00N\xc7&\xcd|'\xbbc\xc7䬥/ʺ\xe9\xe7\xfc&᧥\xb3,\xa7\x1a\xb9/\x9e94\xec\x9d\n\xe2\xb3g\x87\x91)\x19^D\x06\x14\x82\x0e\b\xc7/\xad\x15P\"\xb8܈Edӽ\v\x1f&\x1d\bS#\x96\xd5\x02pK\xa0\xc8\xef\x80D\x1e\x98\xdb\x01D\xfc\xa4\n\xfbȚ\v\xfc\xf0\xea\x1aM\x889B\xd6\xc54G\xe1\x1e\xf3e@\xf1f\x8e~\u07bb;\x03a~\xb7WOk\n\xd7CL\x01\xe8\xf1\x8e T\x86\xe7\x95|\xa0;\x96\xddv\xe8)\u2433aH\x16\x92\xb7\f\x96\xc0\xb9\xf0z\xae=lyN\xfa\x14\xa2S^\xfa\xeb\x06\xdfxG\x87\xe9\xaf0\x18\xaa\x05f\xdf\xc6x!e\xb8\x03Ƹ.\x9a9\x95\xa6\xc0\xe2\\(\n\a\xff(noAiO\xf9@ut:)\x93S\xd8P\xd6U6\xbf&*\xbd\xdf\xf6B\xf2v\xf5\xdd\xedp\fF~\xb3[\xc5\xc3\xc1\x1a\xba\xa3@\x0e\x8b\b\x87\xe1\x1c]\x1c\xdc\xcf\xedJ\x81\x15\x18\x98a0\xc8\xc8dT\xa5x͊Z\xadС\v\x8d\x98\xe4q\x1c0.\x8eW2v\xe1\xcd\xf7\xc21hd\x8d-CZ\xf1\xa4\xbfV\xd5A@\xb5G\x84ñ|g;\xee\xe5=\x19E\xd6\x184\xca'K<\xfc@\xad\xba|\b\x8b\x984^\x80q\t|\xe5\\\xe5\u007f\xfb\x86V\x15\x1f\xe2\xed\x1b\x9f1p\xa0\x0f%[\xc6#S\xd4\xef\xe0#\xecF\xe9\x8b\xfa\xe2\xf7\xcf\xd8#\xb2\xa8-\xa6C\xa4I\xf1\xda\xcc\xed̥\xbe+\\\x16),\xedWyy\xf2:#\xec\xdfs\xed\xf7Q\xa5\xbc\xa8\x98\xe5P^<\xf1\xf2\xdfE\xfe/\xebP\x98\x9e\xac\x94Ny\x87\x84\xba\xf3\x88\xffߞ\x92?)\x81\xe8e\xc0\xfdS\xfd\x92\u007fb:\tj\x1ew\xa5na\xa6\x8d\xd2\xee\\\xb8T\xc7\xf7]n>,\xb2\xe6Jz\xa3\xbb\x8dF \"穼\xa2ƹ0-\xbc\xc9\xe1h\x8b\x00\x87\x96\xfa\xcbq\xf3\xb4\xb3(B?\xd6\xe9\xe6Z\b{)\xb2\xb1\xcb6{\xb3o\xab\x8d\x9bݔ\xee\x98\xda2WC\xc1\x06\xddtˋ\x82\xddg\x825\xf3T8\xbe\xc3\xf6\x8e\xb0\xbe,+O\xcde0\x1bHU\xe0ܺ\a\xb7vRrA\xd6D\x8f\r\x99\xa76\x91\x86\x12\xdbř\xa9\xff!\x16\xe8\x02\x04\x86D)n:\xa9\x9fnc\t\xa5a\x8b\xea\xb5=2\xb6ݫ\xef\xea\x1dws9\xf4O\xddY\xd8V@^\x8d\xe3XI\xfb\x03{+\x8b\x12\xea\xfb\v\xd5#\x96\xe7b\x9f\xae\x9e\x89\xed\xb7\xaaW\xf5\x16\x1b\xa0y\x15+\x02@%\r\xb1\xaa0.\xb9{\xba'~{d\x84z\xd2r\xed\xd3/\x11\xddێl\xf3\u007f\x9e\xbf\xe5\x9dL\x8d\xfe\x18*b\xdb\xd9d\xd2_\a\xbd\xbf\xa0\x12\x9c\x0eEc\xbdf\xff\xd7\xee\xe1\x15a\x93\"\xc3sص\xe2-\t\xfb\x9dv\x05\x14\xe7$\x95\x0e95\x86]\xdc&,\xa7̋\xdfP\x17\xac\xcbL\xaeY\xe1\xdf$8\xf0\xc0\xa0>\xf6\xd2\x0f\xd1=\xf8\xc2[\xc7\xd6w\xdc<\x06*\tC\x18~\xce$\x02\\\x98\xa5\x9eY\xc9Y7\xff\x9bW$Y\xe1\x93\u007f\xb1\xac^\x90\x9cq\xe2F%E\x85\xd6\xd9\xd7A\xd3\x14W\x13\xb2Q\xa9\x147\xca{\xd5\xf0\xe8\xad\xd1EH2\x87C\x06\xe6)C\xda\x1b\x8eu͔\xbc\xe7\xfa\x12.w9A\xc5Y\x14ȓ\x92K\x9a\xb1\x12\xd6\xff\x81\x9c\xb8c\xea\xeb\x99\xeb\xc9\xe7\xe5d\n\xd1Ị\x97<\xe5\x1b\f\xf1\x8e\xd7\xe3\x1dw\x82\x94\x1aTPN\xe5\x90\xfd\bwb\xb2\x8f\xbbԡ\xbc\xa2\xb2\"~H\xa7\xd06\xc86\xca_\x02\x10\xde0wnDKAAN\x8e\x91\xdee9\xb8\xbe\xce\xd2\x18\xa9\xd3iFVg\x04\xb4?\xfc\xf8\xac\x0f\xc2#\xc0\xd1\xde|\x9f\xcf\xe7\xda\xe0ּ^\x0e2\xa5|\x88Ś{\xe8\x84A&\xf0X\x10\x84|\xb4\xe3\xac[QhY\x88^\xa1\x90\xcboG|\xbe\x9d\xe1#W*\x83\x8afe`-\xc6ޣ\xac\\\x06\a\x16\x00\x856\xc6i\xf5\x85˺\xaf.tu/^\xed\xb2\xd1\x1ey\xfc\xf9\xe0\xb5kA\xa8\x94\xf5\xed\xc9\x05\x02\x1e\x9f\xaf/\xe1˙\x82\xd45\x99\xecn\xd1nמz\xd7]1\xe7\xda\xdaZ[ϝom\x15V95\x0f˅\b_\xe16\xe3\x9c\te^\xe5^\xc1\xcf!M\xe5\xea\x1b\x19\x06\xcdM\xb1\xfd\xe9H\xa1\bчVx]m$\xef\xdaՏ\x91KJM\xcf\x0f4F-\xab\x97\x18oQ\xebC\x1b\x9d\xaa\xb6\xda2\xd1\xc7\xed\xb3\x06\xba3q/\x83T\x9f]\xbd)\xf1\x1d\x16<6.jxo\xbf/|CA^\xa6[cB\xea2\xa9\xe3|A\t\xb9{o\u007f\xd01\xad\x95K{\xf1\x062A\x15`O\xad\xf1\f\x1bF8\xbb\xc2;\xa7\xd5' \xbe\x8b9\x12\x04\x12ƀ@bR\xc3]\ue523ʷ\xd1q,V\xdao\x17\x9f<*\xf0\x92\xfa\xf8l\xbd\x11^\x94ܫ\xb5\x18QcT\xa4\x8a_\x14\x91\x145?$\xb3U\xd8\x100_9\u05ca f\xc9\xd1)\x16\xfc\x03\x1c\x86\x12C\xc2\xc5\x05ץ\x95\xb4)\xa7\x8c\v\xf3י\xe8\x84P\xa6[\"q,6\x99\x17\xc6\n\x16\xba\xa8\xdd\x84#\xcca\xc8\x00\xe6\xea\x9b\x00cd$\xa0\\\x1e\xc7ـ\x87\xee\x9d\xf8\xb5\xefݻ\xfa\x8a\xe1g\xe3\xb5y\xb4Z\xbag\x8b\xebv\x8cb\x9f\xbc\xf7Էaz\x028\x16\xa9{ț}\x0eBh\xd2A\xb7{mD\x03\xfe\x86\xae\x85\x85.\x83\x1c\xf4'*K\xb8\xdbO\x1bik;\xa2\x9dD \x96#\x99\x13\x81\x80\x9d\x1c\xae/\x00h\x90\x86\x90\xba;\x93@\x1a\xff\xe0±\r!\xf4\xdb+\xffګ\x0e\xcc-\xb2\x16c\x9ckn.\xfa\xcb\xefv\x19\x96$?:\x8b\uf266\x81\xefܗ\xdf\xc5\xc0\xfeb\xc7{\xdf\x13\xcdaz\x03\xc0K\xc0\xc3\xeaޣd\x99GkyVֶ\xbc\xc1\x85\xa7Z\xf9\xafͥ:\xb7\xcc'Z\x8e\x15sg\x9b.\x02\xbb\x01O\\\x17/+\xdfi\xfb.\x84\xa55j\xca>(\xa1\x8e\v=\x82\xff>\xf2\b\xcbv\x1e\n\xdb\xf4w=7\\\x834\xbe\x1f\xd9\xe0߈y\xf1\xfa~)\xd8\xc9q\x19NK\x01\x02\x17\x02s\xa9s~\xf29\u007f<\xa2\xd8\vk\r\x9c\xe0\xb7{d\x01\x86\xa6\xdf\xd6o\xf9Þ;\x9f\xb5\xc7Z荄\xb0\x04\xe6A\xc4R\x894\xa7vríḾ\x96Ѳ\xf9\x12ʀ\x9e\x97\x8b&\xf2_>\xb5p9U\xc7F(#eI\x94|\x95K!\xba\xda\xe1В\x93l0\xa8\xa436\xb1\xd9n\xc7LG\x97e*6Ne\r/ˌ\x1a\xedԎ\xd7Ūjj՚\xe3w\xfa\xb4\xad\xf3e\xf5\xc57r|т\x90\xe0\x84\x94\xe4֔\x94\xd6\xe4\xe4\x04\x99\xa8讞\xec\xdd\r\x83A\xea\x9aZ\xcdS\xaaCr\n֔B\xe3I\x9b\xb2nt\x87\xda\xd6~\xb5-\xcd#Z\xe3V\xbb\u007f\xbb\xda\xc8v\xfa\xd6\x1d\x1bL\xb2\xacB\x01\x1br\xf9\xa7\"9ŗ5\x9e\xd8\xc39\xe0\x1e\x808V\x06\xbe\xea\xb8x\xac\ah\xea_d^\xcb:\x93|xmW\x01(\x9f\xb7~\xab\xdf\r\xfaM\xeay\x81+\xa5)#\x12%ʂ\xb5\x99\x1fu\xfd\xaa\x85\x9d\x82~ޯ\xbe\x16\xfb\x87щ\x8b*\xb7\xf4\xa4\xb7\xc5K\x13\xa3\x94X\x8e\x83\xaf\xef<\xf8\xcf\xd1g\xab\xfb7\x00|`\x10\x80\xcd\xda\xd6z\x12\xb0\xc6H0\x95\x1c\xb4\xcfikY\x98=2\xc7\x16\x16\xe4\xe1\xef\xfb\xe5n\r_\xfb\xd7u\xffX\xbf\xfeGWVҹ\x8e\x8e\xb3\x81Y]/K\x06\xf68[\x84\xe6\xc0\xeb4XL\xef\xfd\xf0\xfb\x87{\xa2\xc0J.\xfe\x17\xca\x14.\n5|E\xbc\xcf^]sҝc\x9dC\x11~\xe9\xe1\x1b\a\xd8\x12L@\xfe!=\xe1I\xa5\x14\x17u\u007fz\xeam\x0e\x9aʐ^\xbd\xdbIU:\x94\x10\x80\xe9\x98d\xff\x8d\xc3\u074c\x12a\x0e?a2h\x02/\x90\xb0\xc4i\xeey\xc5;\xd8\xd7n\x06Q\xba\x89\xf8\xe7o \xd8\uf413(\x8b\xfe\x81\xf9\xd1\x1b&\v\x9f=X;-\xd9?\x8fvkC\xca)\xfc\x9f\x9d\v\x1bfm9\xd9\xdcҟE\xf3\x95\xecf^\x1d\x1a\xa2\xf0\x85-MזJ\xcb\xe7=\xee4o,q\x97˒\xa1i^\x81X\\lX\u07b3\xdcۓ\x86\x91\x97\x97\x0f{-:\u007f\xae\x9d\xb2\xe5\xc3\xfb\xed\xfd\xe7V{\x14\xe2\x0f\xda??\xf5&\xdc\x0e\xf3*_i\xf8\xf0\xaf\x92]\xa2Ţ@\xb7\x90\xc1\xe3T~\x11\xdc9\x19{\xcc\xec\x1dU\xb4p\xad\xfcM\xfd\xd9X\x1dא\xa1\x05j\xfa\xc4\xc9S雩W::\xef\xd1@V\x14\x93Vپ\xaf\xaa=-\xbd\xbd}_e\xfb\x9b\xe3y\x0e\x03{\x8aĎ\x9d^\xbfg\x1e\xd4if\xe7h\xe8j\xa2r\x0f\x96Ԯ\f\x9d\xf2\xd70(\x89\xc7w\x1490\xb3\x8e\xa4{\xe6T\xd6,OT\xe1<~\r\x8a\x8a\xc8\f\x11\x12\x8e>ϷX\x18VX\x15\xd0\x17\x9d\x18\xb08\xbc\xb3^tΪ\xac\xf1\xbc\x99\xc4/\xad\x98\xa4\xa7\x86y\n\xb7F\x1e&\xc0\x91$ZL\xc4\xed\x03\xa4\xe4ȏ!D\b\xe2\xe6\xc6\a\xcaHn˃8\xe1m\xb1\xc9\x1e\x12\xb7\xd6\xe8L\xba\x90\xf9\xb7:\x8fd\xedJ\x04'\xaa!\x06c\\?\xd3<ƶ}\xc4\x1c\xbf\x8e@}\xe1\xdf\x1d\xce\x00\xde\xc9\xda\xce\xe6\xd1݁\n\"\x02'\xe1||\xcb2\xf9_}\xb0\xf8W\t3:\x98\xe4\xeb\xa9\a\xa0}6)X\xb4.\xb8邈\x97I\x93\x02\x9f\xabe\x8cm\x06ś\xcd\x00[\xd0:ޝ\x17\xb7\xe6r\x88m\xac\x8cL#hd \x98\x96c^o\xa5\x80\x11\xa6\x00\xa0;\xd16\xe1\xc0\xe1\x8aa\xd4\xf8!m\xac\xf7\x18\xb5\xd3L\xdaS\x89\x85\x1d\xe3\n>\x96n\xc4\xcaN-\xba\xe6\xf0\x00j'\xdc9\x18BP\xf9B\xdf\xdf\"7\xd5%\x1c\"\xa6\xcc\xcfJ\x9f<\xf4\x8b\x93\xe1\x0e\x05\x14Z\xa7\xaf\xdf)\x8c\n}\xa7\x06B\t\xe2[\x01S\xfd\x84\x8a\xf9\xf4gԓd%\x81\x91\xa3\x1c7\r\xd9O\xb2\vM\xa0\x10\x14mf\xf1\x9bZ\x8ddQ?\xc1\xf2\xa78k\x94\x9e\xd0\xe7\r\xb0\xb38V\xe2\x80\x1a\xd0jW\xbb\xbb{z\xda\x00\n\x935\x1b\xb9zՄ\x91\x94\xf1\xff\u007fff2!\x0f\x83]\xf3J\xc5\x187\xba\xfc\x97\xed\xe53\xc6\xdf\x01\x02Cƅ2P\a\xb7\xef\xf4\xd6,\xa8Mw\x88\x8fǹ\x9f\xd7\xd6*)\xa9\xa95H\xd8\xe9\xf9\xf3\x18\xa0\xc0%\x01 s\x829ҏt\xeeI\xf1T\vH\xe6\xc9'\x05\b\x89\x0e~\x1c\xa3\x06ic\x87\xddK\x01\x16\xdb\x1c\"\xba~X\xb0\xeb=~KH\xa0^\xe9!O\xfc\x00\x04\x19q&\xfe\n\xe4\"\x8a\x1a^\xae\xf8\xf2\u007fS9c*l`t\xc9\xea\x8112\xba2\xcaQ\x85d\x16\xf9\f@\x1a\xc0\xbf\xd9Z1\xd0N\x96\xff\xa3[\n:\xfe\xa8\x90\xacH\\\xc1\xcct܆\xd0\x02\xe3\x1a\xe8\x83Ce\x97S\xacS\xf0R|D\x16\xcb\x0e\x15\xe2\x90XECyd\xe9\x83hp\xe19@\x06\x00<(\xf9+\xf9\xf3\xdf\xf8\xdd\xc8$̙4\xa6\xc0\xc5;.\x199댋)5\x99\xf7d\xa7e\x19\xa5s\u05f7z$\x01\xbf\xb2\xdf\xfeU\x9b\xd7f\x1f\xea\xdd\xd0\xd2{\u007f\xfe\xe5<&\xddv\b\xd2$\x94\b\xa2\xe9b\xf2)K\xbf\x81\vW\xf3\x89\xe4T\xff\xb1\xcc\xf2\xdf\x12\x12R\xba8Y\xc1j\x93\xa5\xf9'\xa9\xbc?\u007fK^GW\x81\xd8{\x98o\x0e%8\xee\xf3\x8c\xf9\xd5dw\xb5\a\xa3\xb2\xc3\u007f\xb5\xcdJ\xeb\a\x06g\xdcM\xfcz\t3.\x9c\x8a7S\xcd[\xfd^\xa8n\x87?\xc1ԣ\x03\xd0\x01\x8al\xbe\xde\xcdC9\xa0Xd\xbf\x13\xd2C?\x1c\x04\x92\xcb5{/\xf6\xc2\xed\x95\xcc\xec{/\xee\xdb\xd5{\xc2 \xc3\x162D{D\ru\xe7wo\x8c\xe9\xaf\xc5\xea\xff̧\x0f\xe0\x1b\x82\x90\r\xf4\x81\xfc\u007fC\x1cj\x9bc\x86\xeb\x94\xf9\xd8T\xdc#Ț\f\xdb\x13\x06\xbd\xae\xeby+L\x91\xf3@w1\xc8\xf0\xfd\xe9\xd1\xf5\x9dc\xc0@\xcf]\xdd\xe9?\xec\xa5|\xfe\x9d\xc3K\f\xf6\x8b9\xaf\x83d\xccX\xb1\x83\x89\xdb\xdbe,r\x8c\xf7\xba755\x85\xe7\xcf뼼\xd0ِ\x98\xd1\xd7\\\\5A\xb3\xd4\xeb\t\xde7\x8a\t\x81[\xf3\xcdB\xfe~\xb8\xb5\xc1\xd1b\xe9\x05\x8ds\x1c\xcf^w\xf9E\x1e)`sOrя)eަ\x05lCZ\xdc@Kg\xfe\xb1\x9eߝ\x9d\xbfz\x8e\xe6/mi\xb1M)\x1b\xba|\x19D\x11\xdfR\x9dѿ\x93\xaf=\xa5\xa8\xca/\xec\x0e\xfc|\xba\x04\xc7pzW\xa4PC<\xc1\xfcx\xd9u\x1f=(9\x96\x16m8m؊\xb7-LW\xae\xb0.n:\xb1Z}w杠6\xba\nw\xe0\x82$\"\x9d\x05\xd9O5\xa6\xf0t\x885\xff\xbe\xe9\x8c\xc0\xe5Nց\xf4;&̢\xed\xa5\x03 '|^0\xdf\xfc\xea\f\xd5\xf5R\xab.\xf2T(|$p\x82\xf9Ȳ\x9b\x18\xa7\xcb!\xbe\x85M:\xc0\rtoTĦK\xfe\x99\x94MH'\x82\xd2\x1d\x93\xba\x95\xe9O\x8a\x8b|2\xb56N\xaf5\xef\x89k 1J-\xd91\x11\xeaYYs\xf5\xba\x1dViU\xdb8o\x18\xf9\x04\xc2fYp\xc9s\x1b\xb0*\x95l\t\xc9/\xd6Evs2J\xaa\xe2/\x80?\x1d|\xb0\xb7Ÿ\x83F\xa4b-\xd1VAcF\xef\xeb:\xa2\xd4\xc1\xccl\xeal\xcd\xef{类\x13\xfb\x15.K\xf4\xf9\xbeM(\x186MY\x17W\xbf\xd5,3\xba\x1e\xabw\f\x97\x97\x97Ec©\x19Q\x9d\xe1\xc1\x8b\xec\x1b<\n\x91\xa9\xd8CT?\xdfl\xfc7UZ\xb6\xdf\x1c\xf7\xad\x8a*\xd1\x1a\xcc{\x04E\x8d\xf2ipCT\xb44\xbec)f\xd9(1/\x06\xf6\bZ\x11,\xf1O\xa0\xa2\x10,\v\xbc\xc8T\x9aeE\xd6\xfb\xc6\x16C\x95\xfa\xd0kؖ\x12\x1c\xf7\xcd\x12K\xfc,\xf1\x0eKH:\xa7&\xc8\xf0#\x1bH\xf7\xb1\x00\xe9D5mrH\xaf\xf1\xc1\xe3?3\xb1Q\xdfF\"\xad\xbf\xbcD\xd3Љ\x8f\xa4\xc26\xd8\xf1\x8aŷP\xcf>\xb8\xdf\xe2\t!\xbc\x15Uq\x86u\xf2.\xef\xddf\xdcc\xe7^\xe4\xb4t\xdd\xef\xc0\x80X\xac\\ZZ\xe3J\xb3\xb09\x00V]\xadбو+\x0f|\xf3f\xef\xe4q\x81,\xc4\xe7ҏ\xf1\xe5A\xae_/儘\xe5(#\xeb :\x94Γ\x89\x95k\x80Q\xdcn\xcf\xcb~C\xa1\n\x99\x9b\x9b\x9a\x16<\xafϳM\xf7f\x8d\x81ɥ\xa6$\x04<;\x13\x85\xe5\xeb\x94\x0ee\x8f\xa2\xe4\xceڤ1\x18\x1d%\x89\x89i\xcb\xf3\xd1EU\x0eg\xf1q*;\xf3\x8fR\xe6\xe61=X\x8e\xc3hW`\x87VU\xd8r7\xb7\xef\xce.Y\x12\"\xceq\xf7\xa6\x02y\xcdW\xb3(\x9f\x03M\xac\xee&\x9f\xfeq\xb4\xfeψ\xf7\x97\ab\xf2\xbe\xfe\x15)\xffc\x0f\x80\xb6\xf2\xd6\xd5Anj\xdeI\xdbW4y\xa5\x1a\x99t\aҝ\xd71\xa8\xda\xecQ\xca\x16\x02܃\x8a\u007f\xecj\xf6\t6\x03\xcb\x1c\x8c\xf7W!h\xeed7\x17\x177\xf2\x8b\"N\xb8\xbc\xaf˴\xf8\xf4\x8e:\xeeC\xf1M\\\x00t\x84\xbbi1r\xb1\xa8[\x1e?Ѓo\xcc{\xe3\x8dTEz\xbdr\xb2\t\xe36\xab\x17\xe3k?Z\xba\xfc\xacQ[\xbb\xeb\xdf7\xcf/\x8c\x88\xc0\x8a\x19\xc8V\xff{.\xd7\b=ծ\xdc\"\xb2\x15+\x9b\xaa\xf6\xd39=\xeb K\xd3Le,`S\xe9\f\xb2w\xcd9oW͡ɓ\xfcl\xc6\xda\n\x1d\xb8\x19_\xd4\xd2G\x97׆aR\x920\xba\x98e\xc3\xe2\xc9\xd2\x1a_ǁ\x1fu\xf6\x89\xb6\x035\x05\x93\xcbX2\x85\xeck\x9e>\x16\b\xa6\x99\xd3[\xb7:\u007f\x82\x05\x12\xfek\xe1ї/7:\xf3YÒ\x94\xf4\xf4+W.1Ad\xd6\x0fe;\xc1f\xed\xf3\x9d4\xf6\xb8\x89\xad\x8dY.\x94\xca\xdb\xe6H:\xa6\xe8\x01^\x9e\xc3\xca\xcaθ`\"\x1a<\x9dH\xe4\xa7\xfcW\x9f\xdd\xf6G!\x97u\xb8M\xc7,\x19\x1d\xea\xa6Z@L\x14T7\xddcC\x83\xc2\xdd\x12\xafގ\x86\xc0\x92\n\xb9\x1e\xde>\xd1\x1c7%1\xb5\xb0$E5\x94\x9a:D\x96kP\xa9\xbc\xe0\x8d\x85\x8c2r\xa2\x13@\x88\xa6\x83\xd8\xfb5\u007f\x85\x13\xb6\xfd\xaa\x92ݕ+\x8aZ\x85\xfa\x98\x12\xabf}\xa4\xcaG\xc6\r\v7\x9b\x9a\xe2\x8cR\x1d=\xb94GOb\xfa\xe7T˷\xb2\n\u007f\xb9\xe3ώ\x93\a#_\xfbw\xab\fTaҳ\xa6j\xfa\xa6\xa3t\xbd\xc3[\x9a\xcc\xfd\x8c\xc9\xfaH\xbf\t\x81-\x04ys\x89\xee\xe2G\xb0d\x18\xc8\x13h\x99Au.Z\x9154N^\xbe\x03\xb2\xfa\xeb\xeb\xb3R\xe1Ӳ\x13G\xdb2Qё\xf5\xfa\\I\x16\x87\x98\x1f\xbd\xde>\x19\xf3\x8e]z\x1cP\xcf\xc5\xe0\xd7=\xe8>';\xb4\xbdr\x9b\xcb\xea\x98?\xbe8D\xc5x[k5j\x934I\b\xbaT\xa7U\t\xb3W\xeb0\xb0*\xab\xa3\xa7\xaa\x16hڬ\xd8Fg\xa5\xfdLRg\xfaX,\xcd\xc7\xdccA\x8c!\x8a\xef\xec\xe6*\xfc\xec}%\x93\xe4\vs\x15\xf7Y|\xfa{\x04\xc8F\xbb\xdd\xeb\xe7+\x91\xfc\xceu]\xf8$\xd8_oI\xacr\x12+\asź\x19\xfdv8\xbd\x98\uee68s\xbb\xe7\u007f\x8f\x96R\x82\xa8\xdc?,%\x18_\x8a\xb9'N,\x17\x838+ \xcb\xd9\x04\xb1kħ\xf1F\xdfgd/$[\x865\x97\x0e'\x9c\xaeZ\xceǡ\x1e)\x95\x9b\xb4\x1aA\xe2{P\x93\xa0\xe8\r{\xad2d\xfe\xd6fܥ\xe9\xb7C(\xa8\x83\xbfQU\x99g1\xcer\xf9\\;\xe2H\xf9\x8b\bb\xbe\xcd\x15b\xd7\v\aτ\xf4\x85\xff\x1f\xae\xe0\x1e\x94\xa3e+lI\x8f\"\xdc\"\xf7Ӝ\xa4\x95\r\xac\u007f.\xbc?\b\x93\xa9>ik\xed\xe7\xd1\xe5V2Y\xd6r\x14.\x8f\xc26\xe9ы\xcf<\x1a\xdcOF}K\xdf\xe5lc\xc6+$\xa7#˧\b{ɘ\n6S\xb09Ґu\xb4\xd3\xe6\xe1d\x84\xe9\xd1`\xfb\xee\xe9*\xb4\x12ٕ\x04X\xcf\xec\xb9\xd55\xdc=\xfa\xfce\xe7\xe8\xf4\xbf\x12ou7~\xff4\xd4-\xd2x\xfd\xc8f\xb9\xcb&\x9f|ۼc\xe5\xad\xff\xa3\xb7;¼\xa5,\xbbZ\xed\x9c_ݥ\xc3&k㯩\xc2\xfd\xe9\xed\v\\&\xf5\xafcwF\xf0\b\x91c\x16렮7\xea\x1e\x87ؔ\xfe\xfc\xceWK\xc5\xf7\x8b]\xda}Q\x81Y\xa7:\xd2\xdcH\f\x12A=r/KuWT\xd2\x167\xfd\xb2\xccVoi\xa5\x01\xb0\x9e\xf9\xe0\xad\xcc\xed;\xe4\aՍ\x8c\xbd\x1c\x18+\xac\x19ݖO?e\x93\xbe\x8f\xbf\xea\xcam\x8b+\xd79W\x96\xa7\xff*\x863\xad\x8b\xd5\x06M\xaa\x93u=\x02\x17\x9b\xbb-\xf8ZR)\xc2\xc7\xe7\xc0\x86\x88Q\x89v!E\x10\xa0Qa\xb8(9\x97\x15P+Bv\xc7{@\xd4\x05E\x1c\x125\x96*\x13q\xad]?\xac\xd3\x1f\xff\xc9\xcfvS\x92\xd8\x0e\x89!W㐸\xc47\x19\x14g!\xdaN\x8c\x82\xe7£Ir\xb8\x86WO\xb0\xe6\xbc\xc7\x04ԇd\x16mb\x83\xae\x92W\xd0B\xbb\x94\xbeM\xc4!\xe3\xb8\xfd\xf5*I\x98\xb0>\x05t\xd33\xe79\xa1 \xf33\xf7\xe8D\xa0\xd6˓\xb5\u007f\x98\x1e\x1c\x86ʬ\b\xef\xdf\xea\x06\x1e\xa3\x83\xd1\xe0y\x02\xec*\x1f{+\f\xeeI\x19\xf4fD$\x025w\xbf\b\x18\x94\xa0\xa2[E\x06\x8bG\x13\xa6e\x93\x86L\xdfe\xbeur\x80H\xf2\xe0\xba\x0f\xc9\xe7\x021\x8c\x9d\x11\xb4\x1b\x95\x1f\xbcT\xff~Χ\x1dtWyw\xb3$vsj\x18\x12\xacf2(\xfdd\xe8\xdb\xefF\xd7g]kSz!~\xa0']\x1e:4\x05`\x04\x89lyi1\x9fYʸ\x80\xc07y\xf3\b\xadT\xe1\xa3\xc4)\x12IJ\xd1\xf2\x9bu\x8b\xcd \x96\xb2\xa5\xbe^\xc4\xc2\x03ճ\x12\x83ķ\x98'^D\xa1\x1f\xe7v\xd2\xd4\xd0\xd1\xf7\x83\xd3IwN{+$>\xc7|\f\xf2\xd4ؿ\xf3z\xecFd\xf9\x17\xde\x19\x9c\xdea\f\xed\x1e\xba\x91\xcc\xe6\xa2\x04O\xbc\xdfbDL\x1f\xd1{̬\xf7\xb5o\xc0\xbe\x9d<5|\xffʐ\x96\x80-DI\x9f\xa0ߚk\xf9\xad\xd7y\xeb\xb5BoW\xc5+\xf7o\x95\xcb\xc9^\xe8\xc4'^N?\xf1\xc1\xe8 \x16=8\\|7rp0\xe2~Iq\xc0\v\x87X\xbc\xf6\x8a\x9a\xec\xaa\xfa\xb3\xa3\xca3\xad\nX\x94\x9e\xdadyz\xc0\xacl\x99\xc9\xc90\xadE\x18\x98\vp)\xf5\xdbK\x15\x8cd\xad\x1e\xcaBĔ,\x8bD\xe5K\x84\xa1\vΞk\x83\xb9\xfdm\xff\xf1\xee?^$\x87\ffRd9M\"Q\xa8\xc8%\xf8\xeb\xa7ƨѣf\xf4H\xaa\xc7ç\x87]\xe99_R\xdc\xf9U\x9b\xb0Aq\xf3}<\xdc\xd8\xf9\x84\xd6=\x80^\xf1\xc6F-ڋ\xd4V\x9a\xbb\xf2\xbc\x06욽Vq\xbe*ĝ\xaa/\u007fs\xdc\x00r\x94\x9a\xe7\xfc\xdd\a\x0f\xa4\xb0\xeb\xcd\x19u!`D\xeb\xdc\xde\xf2[I\xebw\xf8=)\tEk\x8av\xde\x1a\xab\xd6kȿgou\xfdS\x94,`\xf9\xe7\xeb\xd1*\x0e糣:\x88\vg<\x84N\xb7\xa3\x89\x91Ͼ${֩ڗm\x98\xbeߕ\x9d˻:7m\xcaL̝VP\xa8\t\x89\xf9\x0f\x84Zo\x9dx\xe3\x86\xf4\\\xd9b'C\xf8\xdaL}zq!=\x15Ew\xa2\nh8\xaa\x98\x93t\x8a\x92[\xc1F3Xc\x84\xd5\xe1Xru\xf0.\xbd$\x04K|\xd83\x8ab\x93\xd38\xa5\xf5\x99r\x05\xa5ҋ\xab\xfd\xdb?M\x1czbި\xaaA\x1f\xe3ԧ?\xcak+Q\xb3\x19\xea\x10=\x8aJZ;T\xf8gr\xf9\xbf]M\x1a\x13{C\xd4}BK\xc4\xd4\x15&0\x9f\x8cF~~\xa2Y\xeb\xe3:\x8dP]\x9a\\\xc8\xe4\nB\xb6\x8c\x92T\xa4*&\xb1\xfd,F\x1f\x9fu\x04\xf4U\xb7y\x97\xa6\xe3`H\x81\xfdn\xb3\rn\x1e\xb1\x9a\r\vF\xfe\xe3\xc0|\xcaK\x8fln\x86\xd1x\xc0\x8a\x19\\.\xe5\x8d\xf0\x98\xdeH|\xae\xc3\xd2Im\x8e,\xc5i]\xb3&\x1a\xa7\x01+C\x8a\xb99\xf3\xf8\xa7\x1bD\x0eZ\x89\x86\xe8\x817\x83+\xe6\xfbg\xfd\x8f\x90\xc7Ds\xc1\xee>\x9c\xa9\x85\xf0\x01\x9e\x04\x86\x8a\xe4\xb3\xd6\fmb\x98\u007f|{\xec\x86{q\x80Ouye\xe2\x87ڬ(+7\x04\xdf\xe4oʈz0'\xf0#2\xb1VQ\a\xb2\x9e\xd8Ǘ\x14M\x86E\xb3\xaf}\x9e\n\x1c\x1f\xab\x87LK\xef4\xd4\b\xd6~\xf6I\x89:\x9dֲnj5'J\xd0e9wse>{hP\x99\x8ag\x8d\x8b\x16\x94,\xab\x88f!\xa6k\xe5\xcb\xd8土^\xd8\xc2Ɔ\x8c\xe8l|\xc0w\xfcu|Ñ߬\xba\xc9\x1b\xa6\xa6D\x91Q\x93x\x053Ck\xdfp\x16)\xbb\x9c\xf3e\x0e\xaf\x9e\x8dC>\xa8\xe5Ԟ$\x1e\xda2f=\xe1\xe4\xfc\xe6\xf1:H\xca\xfah5ڢ\b\x12\xa1\xfahF\xec\xfc\x9c\xe1L\xb6,@\x98\xbe:\x9c\x90\x9f\xa3\xb2\x18E\x98\xb2~7\x81\xe6BV?Q#\x91\x98\xbc3QA\xe6.јڬ\x90\xeexW\xeduj\xcdT\x03\x82a7\x1c`N\xba\"\xa3*\x8ckKbY\xc0\xcbJD\x1c\xb5:\n\x9e\x89\x14,T\xfa\xb3\xbf\xce3sq\xc8%̓!L\x8eo\f\x04\x12oP\x8cM\xbcZ~8_\x1eBU\xeb\x9eh\xbd2|\xa5\xf5H\x14@\x95\x87\x84\xf3\xbd\xf2m\xe2\xadEj]<\x14\xaf\xd6m\x1f\xc8\x18\xee\xbb\twFɇ\xbb|\xea![\xa3\xca$\xac\x05\xe6Q\x8b\xa5#\xcfz\xf5\x96\x98\xeb\x00T\xde\x1a֞N\xe8\xca6\x12\x84\t\t\xef讎\xa1H\x0f\x1dNb!\x1bb'\x16r\xc8V\xe1\xca\xc5!R\x05\x95n\x1e\xaf&>w\xbe\x89\xddw\xfe\xac\xbb\xda\x1e\x98\xb8\xaa)\xa4rR\x19`\xf2><\\\xba\xe7|\xf1\xa6a\x00\x91 \t\xc1\x10\x90+\x8f\x8eQ\u007f۹o\xa3\xee\xf0\xbe=\u007f\x02b$Jh\x93\x99ܒ\"A丄\xa3uu?\xf9\x04\x04\\\x1e\xef\x9e\xc4hG!\xee7\x15\xca˽&K>\xaa\xaep50\xabE\x99\xab*\xe5\xd4\xda~#>ĤR\x94>p8%\xdf\x1dq\xfc\x9b{\xff\xcd}\xcb#\v\xbb\xf2p\x87\x89\xd3\xc4q\x93Ϳ\xc6fOG[pVa\xa0\xe6r\x11N\xe0v\xc8\xff\n@`H\x94r\xear\xb7\x9dUHk\x9aέ|z\xac\x98g,t\xff\xf0Q\xb2\xf0\xe0\xecͭ\xe8Nb\xfc\a\x0e\xb4)\xe5\xedY\x18\xc40G\xdf}ws=\x97\u007f?\x111\xfd]\x06\xf8Ο\x1e.:\xe7\xd3\xe6\xd1X\f\x01\x89\xefӻ$\xa3\xcc\x1cV\xb7ލځsw\xd7\x05/\x8c\xe2@\xad@\x01\x05\xea\xee\xde{W,}v✥\"Ըz\xd0\x03\xf4\xd4\xd6EI\x1f\aIK\x90\x1dU\xed\x00\x81ŏIe\x9bP\x00\x91`\x89\x9bfq\x984ꒀ\xd9y]%]\xf0\xba \x9a\b-\x1c\"Փ9\x11\xe1s\x87\xe6z\x10\x18Ri\x11\x95 \r٪\x1fӍ럤1\x13\x8c!\xa4Sj\xf13\r\xf7\xc7^\xac\xa7-S`Y9\x00\x04\x84\x9c\x1f\xb1\x04\x80%̥ʒ\x81>\xa22\x97.\xbe-}\xb7pѷ\xe9\xf37\xf7\xb9^\x16\xe6-R\xb8\xd52\xe9U\xef\xb3[\xe2\xf2\xf7\x0eKV\x8f\x1f^\xb5\xb6\x8f\xbbj\xf1\xd0]\x12\xeeN牅\x1e\x81a\x8e\xc6\"}\xfa\xb6\xba-\xe9\xec|\xf6\xb2\xfa\xb2\xba k\x1f\xdd2a\xfa\x02^\xa6\xa0\x9e\x94!b)-D\xb4\xd2\x15*5\x0f\xcf7ho\xd9Ѡ\xfb\xe8\x82J\xfe\xf2\xd2?\\ζn<\x1a\xf4o\xff\xf1Q\x9b\xfe\xb40^\xa606\x9e%\x06g\xf2\x15>)\xc0f\xde\xc7U\xcc*7\x05\xdd\xc2\xc7U\xe8\xfd\x9c\xff'\xb9\u007f\x88M$+\xeb\xcf\xfd\xc66_7\tԤ\xa0\xfa\x1fY\xd5\a|j\xf5\xf4\xf3\x8c\xc1ip\xfa\xffUzǵA\x90\xdb\x13\xaa\xc8\xfb\xcf\xd6\xf2\x8f\xb4\x0e[\xd2\f\f\x93\x92.\x10`\b\xf4{\ff\xbb\"[ꨃ\xa3\xf6\x9c\xdfH17\xd60\x83\xaeu eeɲH\xb9k.\x92\xbe\xc2a0<\xd1bGQ\xd0Ji\x99%\xb9\x91_\xca+!\xd7\xd3\xe8}W\xf7jۑu(Gkf\xe2\xdcEsF\x98/\xa3r\xd9\x01yy\xc5#\x8aX\u007f5\xdaF\x99\xcf\x13H\xe2Ʈ5\x10\xfb\x9f\x1aY\xcbe\x99\xea8<\xf21\x1eg휨\x1a\x98}fP\xab}\xd5,-\xa6^_\x8aJ\xda\xc6\x1eϷ&}$\xf1\xdb6\xc7vƸ\xdb\xee\xa4\x02\xb1\xffe\xd7\xfe\xd6\xc4o\x910\xaf\x8b\x1e?\xeb\x1f\n\x01{\xd4d\u0096\xe1\"\x00\xe2\xf6+\x06\x95\x14=\x99\xf8\x92\xbe*\xa7\xdac\x8c\x14y\xaa\xe2xy\xcbZ%\xad=vS#C\xc6\xe99\np\"8*\xec^\x1dZx\xc4\xdd7S\xd6͊;\xcf\xd9\xc5\xfas\xbc\xb9\xb8_\"\x95̯i\xbf\xd7#'\xc9+*\xc7q2\x1a\x13I\x05\xd2\x1e\x94yl%\v\x97\x8aE\x8e\xb8\xa4\xa3^[Ɖ\xf8\x857\xb08A\xac-\x02\xd3\x164\x1c\xf3㋲\xfc.\xab\xf8A\xd3u\x1eF\xea\x8dEOZ\x9aa\xde\x18;R3G\x05\xd5F\xe7\xe4\xc6\x18\x18\xe9~\x14\x03#\x91\u009e\x18\xe8\x89T\xba]\\{jg\xa1W\xf4\x8c\x0fX\a\xb3\b~\xf6<\f\x9bpDm\xb1E\xcaݭ\xe2\xf4\xedQ\x86\x1a\x8eG\xbd\fC\x04\x1b\x0f\xf2\xf0\x88\xf8\xe7=p\x89$sC\xabT\"\xbb\x91\x8cY\x1f\xb4uG?\xdc\xd61zˠx\xab\xfci\x01\xb5v\x915:\xe8h\xac`\xd2\b\x87亟#\x9f*\x1d\x90\x90\x91\x9a\x8c,\xf7\xba\xa3\x18\xeb\x92f\x06\x10\xf8#\x15>3e\xb3Tu\xed\x93\xd4u+(\xef\x81l\x85:\xd3\xcb*o\xd8w\xc6\xe4\xd0\xfe\x03\xfaQ\x93\xfb\xe5ʑ\x8f\xd3GwE\xbf\x02\xad8\xf8\x85\xf1\xb0w\xae\x9b\xaf\xbfU\x95\xb2՛\xfcn\xeb\xa7\x0fK\x8c-\xb7 \xdb\v͎K\xa1M\xed\xb2\xe3r\x869\xbf]\xaday\xfa\xb6+\xf4\xd02\xb6\xb6\xdep+ҹ\xee\x1f\xac\xba\xa8x\xa4\x97?\xe4_Q{\xf8\x8c(Ƕ\x0e;\u007f\n\xdd-\x17!\x98\xe41FR\x1b9n\xff\x14f\x8b\f\xf7!\xadК\xda\xc7\x0f\x9a\xaa\x11\xeb\x91?n\xeb\xf8\b\xe6\x8c\n\x00 c\x03D$=K\x8e\xb6n,P\x89Yg\xfe\xcb\x1axq\xcfͩ\xd1'C\xf1\xd0\x06 \n\xde}\xd6G\xe1%3Cg\xadQ\xf9Ӝc\x0e$\xd6n\xf7%lcf\xe8\xacUˌ\xa0N\xea\xb7\x0e^\xf6ޤ\x1e\xba\b\xa3M\x86-\xee'KV\xbcϚ\xcd9\xb8y\x91\xf3e\xf2z\xb1bQ\x03\xa6\xbeȵ\xa1\x10\xb3ƏxT\xe3R\xd0Q\xa6\x97\xa65~\r^\x9d\x8du9g\x11\xe6\xf03\xff\x1cf \xcc{\x89\xae&#T\x8a\x88u\xd3H\x9d\u007f\x048%\x15\xf8\xa6\xdd2t\xf2):\xf5N#\xe3\x87s\x9a??%\x92\xeb\xa8?05\xa5\x12\xa7\xb6\xd2љ\xb4T*\xad\x03R\xbb\x03\xacg\xd3)Sאy\x1a\"҇SAܻ\xca錪\xaf\x17)q\xfe\xf7\xa5R\xd3K=W\x10\x97H\xc4\x12\x90\x9d=\xb0\xbc.(<\xbf\xd4\xcb>L}\xff,\xce\x197\xf0汫\xcdƎ\x1a\x97\xb8P\xa7\x9e\x9f \u007fs\xed+\x1e\xe6fI\x02\xbd\xd0X\\h\x96\x8f\x9e;s\xc6b)\xf4\xbd.V\x00\xe1\xaf\xd3Ħ,\xec\xd5|pU\xf7\xfc\x99\xe9YY\xb5\x18\r\xb5\xae}\xd20ӐT\xa4z\x16\xfb\xadq\xdaM\x9eeRp\f\xfc\v\x11\xc0\xcf\x16-N\x02S\\ \xe0\xc0.\xe3]\xf0\v\x93\xed\xf9H\x87d\x8fv\a\xc7i\xdfdK9}\xefdqz\x81\x0f\xe2\xe2K\xca\x105\xf3nX e\x87\xe7\x10\xfc5bF\xbf\xa0\xc16\xa9ʍm\x87C\xca\xd4@;\xe5?\xb7{\uf22eR,l\xb0=\xde\xfa\x9a\x86p\xc4\xfde\x99\xf0\x88(\xef\x16\xafFM-\xdf\xd7c\x16\xc4<\xbb:\vG\xc8Н\x1bn\xc8\xd1喊\x05\xde\xe6\x14\xdb\xdc&\x18R\xc6aRV\xce\xd5z\x14*/\x83ҴT\x99#\xf3\x9cH6\b\xac\x80\xf1\xa1\xecv\xd9\xf4\xad\xb4\xdb#\xca\x0fI\xdd(\xd7\xe1\xdb\xe9V!QҠ\x84\xcd\x18G\xe7\xf0\u007f\xe9߄\x9d\x04\x17+x\xc4m2k3\xa8\xa6\x03\x18\xbb\xe1zU\xe635հ\xa7\x03\x85\xf7\xb22o\x1a\x99~Gq\x88\xebr\x94v \x0f\x04\xc1\xb3\xbe\x82\xf3\x0f*\xe3\r\xa5\xb5[Ւ\xe1C\xea\xac[~:\xebm&\x95\xdd$\xde\a4ij\xa5\xefB8\xaf4|\x97\xba\xfa؍pH\xdc\xe6r\x9f\x1b\xd7\xd5+ƺQ)\xa9\xda\xfb\u0602\x99I\xde\n\xf2\xc9\xd0g\xb2H\xa5S\a\xcb\xea\xaeba-ui-\x81\x1f\xc6l\xff\xa1\xdb\xf4\xf8/о\xd00\xa6\\M\xcb}K\xf8?\xe4FdD\x93\x96{=\xc8{<\aԍ\x1f\u007f\xe5\xef\b\x8a^Ѡ\x92\xef\x8c;\xf0\x8a\x15\xf7|x\xbb\u074b\t\x97\x1a\xf2\xf9]\x1d94j\xfb\xcc\xdc\x1b\x11F\x11a\xfa\xa1f\xdf|\x12\xc6l\\\x16\x1b\xbcQ\xb3!\x8er5\xb9\xf43L\xdd\x1fc\x1b6\x9a?a\xe3a\xf6\xb9\xc35\xdfc\x8d\xcdG|\xaf-\xf8\x01\xc7\xc0\x87\xd9ls^\xd7\xf3\xab\xc48\x9a%\xcb\x176u\xe0\x9bO\x86\xe79\xe3Q\xb8\xbeǟ\v\x97\x8enXIx\xaf\xfd\x8d\xf24paܽ\x1af\xbdζ\xdd\xf6K~\xca?\x1c+2yI\x05b)\xa2\xb1;\xe6(\xf9\x1a\xe5J\xfc\x91\x8eΕ\xd0FH\xba\xea\x91\xf8\xf1\xce\xd8+\xe0\x84*1&\"ɰ\xe1\xe1ɍ\xac\xb0\xddP\x02\xc6a\xce%'o\x06\x91f?\xbd\x1c\x95\x84cO\xcaO\xc1K\v\xe4\xec\x1d\xdf\xc28\x9cVz\xea\xecM\x95\x8cé\x91cg\x88\xce֧\x13\xf5\x1c6Y_}\xf7\t\xdb\x0eo\xfc\x94m\xbc\xf3\xff+zgT|\xee\x85VQ?'\xa9\xf5\x11\x8e\xe9\x99\"\x91x\xa6\x18\x17\xe4R\x8f;gO^\xd4L\xdb\xc48;\xd4\xdeq\xc6\xdc\xdea\xb0\x87ߘl\xadLb\x8cL\\\xfaWw\xc8>k\xb0\xf9\x86~[gwk\xe3\xf1\x05:\xdb\xd1>\x042}Z\x8bB\x9f{\x9d\xa3W\x13\n,\xf2\x91w\xbd&\xdaS\xae k\xd7\xcb\x16\x17a@\x96Ը\xf3?\xb96>3\xa3\xa1\xb6\x91n=)?{\xc02\xf8\xdc\x01\xa5\x84\xca\xee\xf0\xf4\x86\x9a\xc6H2\x1d,\v)q\x93\xc2H\b`\f\xfa\xbeޕ\xba3jkTĞB\x19\x1e\xfa\x98\xc8?\x92\x12\xdeQm$%\xdc)\xfa\x90\x94\xf4\xe1}bU\xdaq_\xe5\xb1c\xbeqY\t-\x84\x1b\xd7\xd4\xcb\x13\b_\xcc1Ӂ\xbe)j\xd6?\x15\xa8\xa7\x87E=7>\xa7\xe3-9\xe46\xe5l\x9f\x90\x04\x93.\xaa\x9b s\xf1\x96\x82x\"\xe1h\xe0\x96\x82\x8dc\xbe\xb7\xb8[\xc0\xcfy\x9e\xbb7\x87?\xacN\r-\xfe\x16\xb1\x80\xd5\x12\xb4\x18\xa2 T\xe4\xf1\x10K\xcd\xf8\xd2\xc5\x05\x82\xf4\xf77\xf7\x049\xe5|\xb1Ѱx\x18z\x94j\xd2gmh\x1c\xe4I\xf7n\xb7H\xdfo\x92g)\xeb\x88v\x87\xaa\xd9~\xda\x16\xf5\xef\xb3\x1b\xeb\rC\xff;\x10L\x9aJq\xed\x9d\x1au\v\xf3\x9b\xd2p\xaf\x05\xfdmW\xe7<\x15\xf7\xb6\xb3˗=\x17l+(\x84lCP\xfc\xf1\x19\x9em-\x97[I\xb3H\xf7HK(\x85\x93|LQk\xe0g\x0f\x81ª?C\xf8E\x11Bx\xb8\xbf}QN\xe0\"\xcd\xf1;\xb6\xb0FNU\xb1\x8acE\x0f\xec\xa9\\k5E\xe1G\nн\xc8\x12^Jv\xd8<\x84+\x97\xa7Dk\xbd\v\x85\xcfr\xaeK\xecC\xadN\r\u007f\xbdw¹*\xae{\x8c\xf1\xc1\u007f\xc2\xf6\xb8\xabϚ\xf1\xa9>\xe8\x06\x16\x8dj\xa1\xe3h\xf8\xffÉ\xbdW~\u007f{\xaf|\xf4k\x9bÿ\xab\xcf$\x06a\xff=\xb9\xb1\xfe\xc8\xe3g\xf51\xd9i\x0fz\xe7\xdd\xc0\x83f҆M\xac\x8bm\xb3\xa5\x06 \x01\xeb\f\xf0\xd1\x1fz`\xd2\xfb\xac0\x1aX\x10\xff*\xb4\xcb+G\xe3\u007f\xa8n\x1a\xd1\xd1 ?J\x0f\x1d\f\xeb>\x03\xc8\x06\x00[St\x81d\xb0>)\x17\x8d\x12\x03`zdM\x1f\x91\xb8\xb4+\xc89\x82\xc1\xae,Z', į>\x19\x10cu}n\xc0\xaamĐ\xd8N\xe9\x90=\x99z8\x01$\x11R\x02գ\xcc3\xf2c\f\xb1\xa8\x171\x01ME\x10\xac\xc4K\xa4Y\xbd$\xb7\xb6\x8d\x8b\xa3\xd3\xf0\x86\xd8\x04\xa1\xd4\r5\xea\n\xe4]\x1cY^=\x15xܠ\xe6\x88KHUNy\x18\x8f\x9c\xaa\x88xU\xb4\xc1\xf6\x04q\x9a\xe6Y\xc9\x02\xc8\xf8d*\xd5gg\xebm\x02nL\x15\xb8%\xae\x83r\x16䰼!\xda@\x94\xd4Z\"\x13\xc6\xf2\x9c[\x1e\"(\xf2͘pf\xea\xcfk\xae\x96\x1b\"v\x87\x82\xe0\x1b$\x0e\xbeρ9&\u007fL\x9bI\xb4Q\x1c\xa1\x91\xef\xe0V\xfc:\xbe\xbd\xb2WIZ\xd4k\x8a7\xe6\x02\xe3TT\xbe!\xccX\x9b52Q\xa9\xa8\xdcI\xc1\xe9\xc1e(\x8bZ\x84\x05\xa6\x86P\x9b\xf8\x04\x15\nb\xa7\xc5}LL\xddϰ\xdf:\xd6.'\xaf\xcf\x02\x81\x18T\x12/\f\x89k\x88S\x16-\x8b>\xaa\xc1\x9cl\xac\x91T\x12\xd1\x12\xc75\xd1}T\x04\xd7r\x03\x05\x8a\xea#\xc4e\xe4(\xa7\xfcS\x9cG\x8f\x9c:\x16\xae'W\x11m\x9aP \x008\xf9\xe1\x9foV\x95V\xc7\xf5\xbf\xd0\x1d\x1a\xee\x8e7S\u007f*\xaa\x8a\x02\x176⋫\x83\x92-\x82\xff\xa87k\xc3I\xe05P|-\xe7w\xd1\x0f\x98\x85\xe0S\x9cX\xaa\xd1\xc9\xed\xbd\xe8-\x12g\xa4\xd5\xf2\v`(\b\xdaT\xac\x8fzI\u007f(\x13j\x12\xdbaZ\x92c^\x94w.\x99\x968\xaf\x9a\x14g-\xc9fV\x99\xc2\xf6\xac]hl\xf63.yO\x85u\x1c\xe22&\xf6\xda\xdb\xf7\xae\x17\xba\xa5\a8EAD|L|Z\xda3\xb8ɡ\xa5\xd0\xd12\xd6]\xe9ۑ\xf55\xecKqO\x9f[\xa1شܵ,\x04\x1fՄ>\xddk*\x99\xd5\xc4j\xd6\x1e\xb4\x0esέ\x9a\t*\x8d\xdeѮ|\\\xed\x0fA[\n\x96\xc7T\xef\xae\xcb\x05\v\x89\xa9O\xcc\xdd=5\xae@'\xfd\x0f\xe1\xd2\xd6z\x9c\xe6\x02=]Z(C\x1bG\x06E\xe9\xdff\x11M\xb6\xed8\x1d\x94G\xf2\x83W\x87\xc9P+q\xb1NE\x80\xb7m\xefF06\xe38Z:\x12b7\xb9\xcf\xc5-\x8c\x1aЬ\x9b\xb4%\u007f\xc6{\x98\xcdCh\xc7\x19\xb0\xa3\xef\x841\x9d\xf7^t\xc5\xdem,R\xac\xa9\x1f\\\x8f\x05\xe8H\xe2\fT\x01\xa3Z#x\xb0㮽\x89\x97\xc8`\xdf\xecY\xb3'\xee\xdc\xf7\xb2}?\xb1\xbc\xf6\x9e\x18}\x01\xa3\xeciou8\xccK\xd8\xd6P1\xeb\xc2\xf2\b\xbb\xbd㥙夆C\xb2\xb9\xca\x00\x9a\x1e\xbf\xed\xe2\xdb\xeb\xb0\xc0\x92Z\x91\"\xb38\x06\x8d\xb3\xac\xa7\xd6\xd8@x\xd7\n\x18µ-\xcf``\x9cPj\x8c}6Ll\x97R\x9a\xf9\xfb\xf4U\\\xee\xfb\x836[\f\xcd\xd1CZ\xad\xb7\x9f\xbb\x88N\xdc\"\x1d\xf4\xc8*Y\xb3\xd1\x1b\xf5=\x1e\x1d3C\x93Ⱦ3\xc5\xf3\xf4\x96ڣ\x81\xddx~\xaf\xd0\x12\xfb,c\x1fe\x1b\xbdG\a\x8a\x9e\x14\v;\x97,5\xceR>U\xb3w\xe6\x886Լ\xb4SAR7|\x04aq\xf7\xe9u\x04\x87\xf0^\xd8ځ\x18;V\xb2`ۼ<\xae\xaeV\x91\xf6\xbd\xf1\x92\xef\xa0V\xd3HɪE-\xea3\xe2\x12\x8ft9Ʌh\x96\x11\x86G\xeb;\xc6\xe1\x9a~\x19\x13V\xe8n:\x97\x98\x84\x99{\xd8~۔x\xfd\b9:\xd67N\xdb\xfb+m1\xdd\xde\xd6\xe3f75d\x19G\x17r\xcf\xc7z\xd9\xef\x97ZFݬ(:\xdb\xdf%\xb7P\x9f\x16\n9\xf2\xbb\xa8G\xac\x86a\x9cxLI\xe0\x03rl2}\x89\xd1\xda>\x16M\xacn?\xd6\xcfK\xfbwE/\xd9\x13\x92:T\xe3@\xd7\x02\xbfY_\xb7\xc7\xef\x93a\xee\xee\xef^O\x00\xfa\x05ME^3\xa0\t\xbf\x88\x8f\x98O\xa7\x90\\\x10\xb8\xd0\x03\x81\x93\x9c\xc0\x81\x97s\n\r_\xe6\f^\x9c\xc99\x1c$-\x17\xf0\x91\x91Q\xe6\x0e\xad\xc95\x8c\xa5y\xb9\x0e'\xad\xcbm\xb0\xd3\x0fs\a\x12\xe9\xc9\xe7\xbaс\r\x02\xc3c\xdcv\xe1V \xe5\x04I\xa8\x89\xb4\xc2߇\x9c!\x13?\xe6\x1cI\x84\xe6\x02\xd9$7\xcaܡ\xea\\ód[\xae#\x85\xae\xcbmH\xa0\xe1܁\xce\xf4\xb3\xff\xeeF\u007f\xc6\xde&8\x1c\xef$\x10*\xb5\xa4\xb0\x00\xf6p\xca\xd6w,意\xechi\x1bḩt\xdf-\x06,6\x11\xc3\x00i0\xb2\xaa\x0eI\x1c\xe9^\xaf,`\x8fŚ\x067\xa4\xf0{~\xaa5Q\xfcR\v]\x81\x88\xfa5\x9dj\x81\x9d^\x1dF\xe5i\xb5T\\?8E|ӕ\x89\xb1_\x93e\xd5\xefoH{U\x8e\x8fĠ\xfd\xa7T\xe9&L\xa1-3\xe0QW\xcdn\xbd\x92Ԥ\x02\x11u\x05\xfe\xeb\xb5\a\xab\x8eM\xb5\xfe\x91\x88\xbf\xfa*\nۥ\xb7\xa3\xaa\ue8b6\xabD\xdc\xd6+\x1e\x88%\xbbj;\xe8b\xe0ͮ\xa0\a' Y\x0f\xb2>\r(؟\x964\x8e\xee\v\x17w\xf3]|\x17\xf4\x1f\xf8\xac/\x99\xc2\xfb\x86JW#Ȥ\x00\xc6\xf5Zca7\xc4\xc1\x9e\x88\x92\xbbB'8:{\xde} \x91\xdaN\x1d\xec\xf5$\x828\xa5o\x92\x98\x13Q|W\x81\xbf\x9e\xfc \xd0mOnL\xb7\x14)\xf8\x8cQ^!\x1dW\x9c\xb0CM8\x87}:N\x8fhۑc&4ٝq\xb6o\x90\u007f\xbf\xa6_\xee\xd6@\x96xމ\x1b\x01\xfbɐ\xbb\xc55\x05\xb2\xef\x86\xc8\xda\rQ\xb7+\x14\x96\x06t\xef*\\\xda\x01\xc1]\x03\x8bw\t\xd4\xfaC!\xc3W\xd1\xc3^\"\x80yw\xc6\xden\xfe\xd0\xf2\a\x85\xc2\xe6\x97\x11e\xec\xab/\xeb\xf8\xdcR\xaa=\x98`\xbf\x1a\xb6\xee*\xa5\xe2\x865b\xfdJ\xae\x04\xd1\xf7\x92\x9dz\xaf\x03MwZ\xaa\x81\xf8\x1eN\th\xdd\xc1\f\xfeP\b\x0eQ\x997\u007f\u07b4\x14\xd6\xe1\x16\x84-\xbd␜\xa1E\xd2\xdfg\xf6\xbc\x8f\x9c\x01\xd9C\xa529\xca\xf2*X\xdf\xdd\u007f\x13\xc6\xf7\xeeYK\xb8Uk\xc4&\x05D\xf2\x0f\x03\x8d\xed\b\\\xcc4\x9e\xaa\x80\xfc]\xcd\aa\u007fw\x8f-\x9e\x0e5\xc4&_kD\xf0\x89@\xc6;\x83\x8d\xafI1f\xb5ͫ\xb3{\xceC\x8a[ŏY}E\xa9\x03\x81x\x15d\xf5S\xcf9ɇ\x88\xdc\xfd@\xf4~\xb2\xba$\x1e\xef\x97`\x83K\xfc\xdcP\xb8\xa3\xf3\x05\x98K}\xc8\xf4\x92\xca=\x05\x92wv\x17\x8d\xd5\xfeZR\n?P\xba\xa9h{\xa7%\xb0\x9e\xbfZdϙ\xe6'\x1f\xb6bi\xa6\x11\x01\x83ys-KhO\x94ü\x9e\xf6\x1a\x00\xd5\x17.\xfc\xe6 [\u007f4/%0y\x95]\xd4|\x14\xe1\x1f(\x85\x94珫D\x9d\xf7\xce\x05Bˀ(\x9eD\x8d\xd3\x15뺹\xf2\x1d\"\xf1c\xc5\xe5\x9ffw\x86\x888\xb1\xb5Ng\xa2P\x17\x94m\xfb\x91\x1c\x87zd\xeeo\f*Ģj6h\xe9\x89n\xcei[\x01\xd0}\xd7iY\nL\xe8ٱ\xf1E\x8ef\xfc9\xdd\xf3\x1aeF\xba8\xe3\xa3d\xfdǣ\x93\xd7O\xf3\xa2k\x9f@\x97p\x94\xc2\xed\xeb#\x1dB\\\xfb\x19\xa9\xe4'\x02Mo\x06\xfe=\xb4)\x05\xa7\ruĐE\xbdB>:\xea\xcd\xfa6Qlo\x85\x9b\xaa\xcc\x15\x946\xb5\xf4\x90]\xa7Z* \xa4)\xe4\r˸k\xc9\x01\x11ֿ\xf8\x90\xf5\xc1\xe9 \xdd/\x86d?6\x1c\xee\rQ\xd7\x1b\xd2\xc87D\x90\u007f\xd6x\xaa\xf6\xe3\xe3'ey:\xf3\xca\x1fK\xfd\xef\xba\x15CaM\x81۽\xd5T&\xfduf\xcf\xebT\x81\xc9\x04\xe3\xccx_\x81\xaf\xbe\x9a\x17\xbaW\xfeD\xc5){5\xeaPJ7\x9bA\xb6\x05\x86\xcc\xef\xb7\f\x832\x83\xbawW\x96q\x94\xfbo-C\xb4\xefg*\x93\xd2\xdf\xd4\xd9t\x1be\xff\r\xf4\x97\x8a\xd7\xc4j\v^\"\xdd~\xef4\xe8{;fo-\xbdW\xf2?\x83\x93*w\xa3W\xe41\xb8{\xc5\xcb\x12\xf3|\xd5\xc4\xf6\xf1k\xa9.Q\xb8Z\"\xc6\xfc\nX\xf2-\xf4\x92\xe8J\xc8\xfe\x92/~\xad\x19\xe6\xcf\f\x98\xfd\x0f\xdc۵\x8fdp\xb8\x91;\xf1\x00\xe2}\x9e\x03\x00\x00\x00\vWAD\xf4|Qķ\x8d\xe6~\xda\xfa\x8a\x94\x86\x0e\x85\x8aX\x9b\xb1\xbbC\x02\xde\xed\xfc\xf8\xde\xce\xef}\xc2\xf3\xdf\x14\xa0\xa2\xe5\x03\xd7\xef\xcf\x19\x856c\x0e\x00T\xc4\xda\xcc;k\xad\xdd\xf6\x9b#7.{7c\xae\xea\xa28\x9c\x04T\xc4\xda\xfc\xdd\xd3\xfd_\x9b\xe3\xfc\xcc4\x80\x8aX\x9b\xb1;B\x02*bm\xc6\xee\x8c\xe9#\"\"\"*\xa5\x94RJ)EDDDD\xc4\xcc\xcc\xcc̛?9\xaa\xa77\xcd\xd6\xc7t3Zk\xadg\x81\x13\x11\x11\x11\x11\x11с\xa8hz\xf6\x8a\xbf\x1c\xfd\xb7\x8c\xfet&ޯw.\x8e\xc3\xe1Y\x9bN\xf9ˋվ\x19\xbbgH@E\xac\xcd\xd8\x1d!\x01\x15\xb16\x8f\x8d\xf6\xf5\x16~\x19b\x95rݴ\xc1\x9f\xc8z\xdb\xc9]DDDDDDDfffffffVUUUUUUU\xb3i\xba\xba{z\xfb\xa6\x93\x9c\u007f\x846\xbdNd\xad\x01\x00"), + } + fileb := &embedded.EmbeddedFile{ + Filename: "assets/.gitignore", + FileModTime: time.Unix(1576651902, 0), + + Content: string(""), + } + filec := &embedded.EmbeddedFile{ + Filename: "assets/.npmignore", + FileModTime: time.Unix(1576651902, 0), + + Content: string(""), + } + filed := &embedded.EmbeddedFile{ + Filename: "b06871f281fee6b241d60582ae9369b9.ttf", + FileModTime: time.Unix(1576651902, 0), + + Content: string("\x00\x01\x00\x00\x00\r\x00\x80\x00\x03\x00PFFTMk\xbeG\xb9\x00\x02\x86\x90\x00\x00\x00\x1cGDEF\x02\xf0\x00\x04\x00\x02\x86p\x00\x00\x00 OS/2\x882z@\x00\x00\x01X\x00\x00\x00`cmap\n\xbf:\u007f\x00\x00\f\xa8\x00\x00\x02\xf2gasp\xff\xff\x00\x03\x00\x02\x86h\x00\x00\x00\bglyf\x8f\xf7\xaeM\x00\x00\x1a\xac\x00\x02L\xbchead\x10\x89\xe5-\x00\x00\x00\xdc\x00\x00\x006hhea\x0f\x03\n\xb5\x00\x00\x01\x14\x00\x00\x00$hmtxEy\x18\x85\x00\x00\x01\xb8\x00\x00\n\xf0loca\x02\xf5\xa2\\\x00\x00\x0f\x9c\x00\x00\v\x10maxp\x03,\x02\x1c\x00\x00\x018\x00\x00\x00 name㗋\xac\x00\x02gh\x00\x00\x04\x86post\xaf\x8f\x9b\xa1\x00\x02k\xf0\x00\x00\x1au\x00\x01\x00\x00\x00\x04\x01ː\xcfxY_\x0f<\xf5\x00\v\a\x00\x00\x00\x00\x00\xd43\xcd2\x00\x00\x00\x00\xd43\xcd2\xff\xff\xff\x00\t\x01\x06\x00\x00\x00\x00\b\x00\x02\x00\x01\x00\x00\x00\x00\x00\x01\x00\x00\x06\x00\xff\x00\x00\x00\t\x00\xff\xff\xff\xff\t\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xb5\x00\x01\x00\x00\x02\xc3\x02\x19\x00'\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x01\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x00\x03\x06i\x01\x90\x00\x05\x00\x00\x04\x8c\x043\x00\x00\x00\x86\x04\x8c\x043\x00\x00\x02s\x00\x00\x01\x8a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00pyrs\x00@\x00 \xf5\x00\x06\x00\xff\x00\x00\x00\x06\x00\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x01\x03\x80\x00p\x00\x00\x00\x00\x02U\x00\x00\x01\xc0\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00]\x06\x00\x00\x00\x06\x80\x00\x00\a\x00\x00\x00\a\x00\x00\x00\x06\x80\x00\x00\x06\x80\x00\x00\x05\x00\x00\x00\a\x80\x00\x00\x06\x80\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00y\x05\x80\x00n\x06\x80\x00\x00\x06\x80\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x05\x80\x00\x00\x06\x80\x00\x1a\x06\x00\x00\x00\x06\x00\x00\x00\a\x80\x002\x06\x80\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\x04\x80\x00\x00\a\x00\x00@\x06\x80\x00\x00\x03\x00\x00\x00\x04\x80\x00\x00\x06\x80\x00\x00\x05\x80\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\a\x80\x00\x00\x06\x80\x00\n\x05\x00\x00\x00\x06\x80\x00\x00\a\x80\x00\x00\x06\x80\x00\x00\x05\x80\x00\x00\x04\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x80\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\a\x00\x00\x00\x06\x80\x00\x00\x06\x80\x00\x00\a\x00\x00\x00\x04\x00\x00\x00\a\x00\x00\x00\x06\x80\x00z\x05\x80\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x80\x00\x00\a\x00\x00\x00\x04\x00\x00\x00\x06\x02\x00\x01\x05\x00\x00\x9a\x05\x00\x00Z\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00@\x06\x00\x00\x00\x06\x80\x005\x06\x80\x005\a\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\r\x05\x80\x00\x00\x05\x80\x00\x00\x06\x80\x00z\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\x05\x80\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x10\x05\x80\x00\x00\x06\x80\x00\x00\a\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\a\x00\x00Z\a\x00\x00Z\a\x80\x00\x00\x06\x80\x00\x00\x06\x80\x00\x00\a\x80\x00\x00\x03\x00\x00@\a\x00\x00\x00\b\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x80\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x03\x80\x00\x00\a\x00\x00\x00\x06\x80\x00\x00\x06\x00\x00\x00\x04\x80\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x06\x80\x00\x00\x06\x00\x00\x00\x06\x80\x00\x00\x06\x00\x00\x00\x05\x80\x00\x00\x05\x80\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\x06\x80\x00,\x04\x00\x00_\x06\x00\x00\x00\x06\x80\x00\x00\a\x80\x00\x00\x05\x80\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\a\x00\x00@\x06\x00\x00\x02\a\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x80\x00\x15\a\x00\x00\x00\x05\x80\x00\x05\a\x00\x00\x00\x06\x00\x00\x00\a\x80\x00\x00\x06\x80\x00\x10\a\x80\x00\x00\x06\x80\x00s\a\x00\x00\x01\a\x00\x00\x00\x05\x80\x00\x04\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x0f\a\x00\x00\x00\x06\x00\x00\x00\x06\x80\x00\x00\x06\x80\x00\x1b\a\x00\x00@\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\t\x00\x00\x00\a\x80\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x02\x80\x00@\x02\x80\x00\x00\x06\x80\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00(\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\x03\x80\x00\x01\a\x00\x00\x00\x06\x80\x00\x00\a\x00\x00\x00\x04\x00\x00\x00\a\x00\x00\x00\a\x80\x00\x00\a\x80\x00\x00\x05\x80\x00\x00\x05\x80\x00\x00\a\x00\x00\x00\a\x00\x00@\a\x80\x00\x00\x05\x80\x00\x00\x06\x00\x00\x00\x05\x80\x00\x00\x05\x80\x00\x00\a\x80\x00@\a\x00\x00\x00\a\x80\x00\x00\x06\x80\x00@\x06\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00-\x04\x00\x00\r\x04\x80\x00M\x04\x80\x00M\x02\x80\x00-\x02\x80\x00\r\x04\x80\x00M\x04\x80\x00M\a\x80\x00\x00\a\x80\x00\x00\x04\x80\x00\x00\x03\x00\x00\x00\x06\x00\x00\x00\x06\x80\x00\x00\x06\x80\x00\x00\a\x00\x00@\x06\x00\x00\x00\a\x00\x00\x00\x06\x80\x00\x00\x06\x80\x00\x00\a\x80\x00\x00\a\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x80\x00\x00\a\x80\x00\x00\a\x00\x00@\a\x00\x00@\x06\x80\x00\r\a\x80\x00-\a\x00\x00\x00\x06\x80\x00\x02\x05\x80\x00\x02\x06\x80\x00\x00\x04\x00\x00\x00\x06\x80\x00\x00\x04\x00\x00`\x02\x80\x00\x00\x02\x80\x00b\x06\x00\x00\x05\x06\x00\x00\x05\a\x80\x00\x01\x06\x80\x00\x00\x04\x80\x00\x00\x05\x80\x00\r\x05\x00\x00\x00\x06\x80\x00\x00\x05\x80\x00\x03\x06\x80\x00$\a\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x05\x80\x00\x00\a\x00\x00\f\a\x00\x00\x00\x04\x80\x00\x00\x06\x00\x00\x00\x05\x80\x00\x00\x01\x80\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x006\x06\x00\x00\x00\x05\x80\x00\x00\x04\x00\x00\x03\x04\x00\x00\x03\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x04\x00\x004\x03\x82\x00\x00\x04\x03\x00\x04\x05\x00\x00\x00\a\x00\x00\x00\x05\x00\x008\x06\x00\x00\x00\x06\x00\x00\x00\x06\x80\x00\"\x06\x80\x00\"\a\x00\x00\"\a\x00\x00\"\x06\x00\x00\"\x06\x00\x00\"\x06\x80\x00\x00\x06\x80\x00\x00\x06\x00\x00\x00\x06\x00\x00\x1b\x05\x80\x00\x05\x06\x00\x00\x00\a\x00\x00\x00\a\x00\x00@\x06\x00\x00\v\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x05\x80\x00\x00\x06\x00\x00\x00\x04\x00\x00D\x06\x00\x00\x00\x03\x00\x00\x03\x03\x00\x00\x03\a\x00\x00@\a\x00\x00\x00\x05\x80\x00\x00\x06\x80\x00\x00\x05\x80\x00\x00\x06\x00\x00\v\x06\x00\x00\x00\x06\x00\x00\x00\x05\x00\x00,\x06\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\x06\x00\x00\x00\a\x00\x00,\x06\x00\x00\x00\a\x00\x00@\x06\x80\x00 \a\x80\xff\xff\a\x00\x00\x00\x06\x00\x00\x00\x05\x80\x00\x00\x05\x00\x00\x15\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x80\x00\x00\x06\x00\x00\x00\x04\x80\x00\x00\x05\x80\x00\x00\b\x80\x00\x00\x06\x80\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\b\x00\x00\x00\t\x00\x00\x00\x06\x00\x00m\x06\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x80\x00\x00\x06\x00\x00\x00\b\x00\x00\x00\x06\x00\x00\x00\a\xf6\x00)\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x05\x00\x00@\x06\x80\x00\x00\x03\x00\x00@\a\x00\x00\x00\t\x00\x00\x00\b\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x10\b\x00\x00\x00\b\x00\x00\x00\x06\x00\x00 \x06\x00\x00\x00\x04\x00\x00\x00\t\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00'\a\x00\x00\x00\b\x00\x00\x00\a\x00\x00\x00\a\x00\x00 \a\x00\x00\x13\a\x00\x00\x00\x06\x00\x00\x00\a\x00\x00D\x06\x00\x00\x00\x05\x00\x009\a\x00\x00\x12\b\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00>\x05\x00\x00\x18\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x19\a\x00\x00d\x06\x00\x00Y\b\x00\x00\x00\b\x00\x00*\a\x00\x00\x00\x06\x00\x00\t\a\x00\x00'\t\x00\x00\x00\t\x00\x00\x00\t\x00\x00\x00\t\x00\x00\x00\t\x00\x00\x00\t\x00\x00\x00\b\x00\x00\x0e\b\x00\x00\x0e\x05\x80\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\b\x00\x00\x00\a\x00\x00\x00\b\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\b\x00\x00\x00\b\x00\x00\x00\t\x00\x00\x00\x06\x00\x00\x00\b\x00\x00\x00\x05\x00\x00\v\b\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\b\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\b\x00\x00\x00\b\x00\x00\x00\x06\x00\x00\x00\b\x00\x00\x00\b\x00\x00\x00\x06\x80\x00\x00\x06\x80\x00\x00\b\x00\x00\x00\b\x00\x00\x13\x06\x00\x00\x00\t\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\x05\x00\x00\x02\x06\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x02\a\x00\x00\x00\a\x00\x00\x02\a\x80\x00\x01\b\x00\x00\x06\x06\x00\x00\x00\x05\x00\x00\x02\b\x00\x00\x04\x05\x00\x00\x00\x05\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\b\x00\x00\x00\b\x00\x00\x00\b\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\b\xf8\x00T\t\x00\x00\x00\a\x00\x00\x00\t\x00\x00\x00\t\x00\x00\x00\t\x00\x00\x00\t\x00\x00\x00\t\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\b\x00\x00\x00\t\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\t\x00\x00\x00\t\x00\x00\x00\a\x00\x00\x00\t\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\b\x00\x00\x00\b\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\a\xb5\x00\x00\a\x00\x00\x00\a\x00\x00\x00\b\x00\x00@\a\x00\x00\x00\t\x00\x00\x00\x05\x00\x00f\x06\x00\x00\x00\x06\xb8\x00\x00\t\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x02\a\x00\x00\x00\a\x00\x00\x00\b\x00\x00\x00\a\x00\x00\x16\x06\x00\x00\x0e\a\x00\x00\x1d\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\x04\x00\x00\x00\a\x00\x00%\b\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\x04\x00\x00\x00\a\x00\x00R\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\a\x00\x00E\t\x00\x00\x00\a\x00\x00\x00\a\x00\x00 \a\x00\x00\x00\t\x00\x00\x00\a\x00\x00\x00\t\x00\x00\x00\x06\x00\x00$\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\b\x00\x00\x00\a\x00\x00!\x06\x00\x00k\x04\x00\x00(\x06\x00\x00\x00\a\x00\x00\x03\a\x00\x00\x00\x06\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\x06\x00\x00D\x06\x00\x00\x00\x05\x80\x00'\t\x00\x00\x03\x05\x80\x00\x00\b\x80\x00\x00\a\x00\x00\x00\t\x00\x00\x03\a\x00\x00\x00\x06\x00\x00\x00\x05\xff\x00%\x06\x80\x00\x01\a\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x06\x80\x00\x0f\x06\x00\x00\x00\t\x00\x00\x00\x06\x00\x00\x00\x06\x80\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00%\t\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x15\x06\x80\x00\x00\x06\x80\x00\x00\b\x00\x00\x00\b\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x05\x00\x00\x00\b\x00\x00\x00\b\x00\x00\x00\a\x00\x00\x1d\t\x00\x00\x00\a\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\a\x80\x00\x00\a\x00\x00\x00\x06\x00\x00\x01\a\x00\x00\x00\a\x00\x00\x00\b\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x00\x00\x00\a\x02\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\b\x80\x000\a\x00\x00%\x06\x00\x00\x00\x06\x80\x00/\a\x00\x00\x00\a\x00\x00\x00\a\x80\x00&\a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00\x1c\x00\x01\x00\x00\x00\x00\x01\xec\x00\x03\x00\x01\x00\x00\x00\x1c\x00\x04\x01\xd0\x00\x00\x00p\x00@\x00\x05\x000\x00 \x00\xa9\x00\xae\x00\xb4\x00\xc6\x00\xd8!\"\"\x1e\"`\xf0\x0e\xf0\x1e\xf0>\xf0N\xf0^\xf0n\xf0~\xf0\x8e\xf0\x9e\xf0\xae\xf0\xb2\xf0\xce\xf0\xde\xf0\xee\xf0\xfe\xf1\x0e\xf1\x1e\xf1.\xf1>\xf1N\xf1^\xf1n\xf1~\xf1\x8e\xf1\x9e\xf1\xae\xf1\xbe\xf1\xce\xf1\xde\xf1\xee\xf1\xfe\xf2\x0e\xf2\x1e\xf2>\xf2N\xf2^\xf2n\xf2~\xf2\x8e\xf2\x9e\xf2\xae\xf2\xbe\xf2\xce\xf2\xde\xf2\xee\xf5\x00\xff\xff\x00\x00\x00 \x00\xa8\x00\xae\x00\xb4\x00\xc6\x00\xd8!\"\"\x1e\"`\xf0\x00\xf0\x10\xf0!\xf0@\xf0P\xf0`\xf0p\xf0\x80\xf0\x90\xf0\xa0\xf0\xb0\xf0\xc0\xf0\xd0\xf0\xe0\xf0\xf0\xf1\x00\xf1\x10\xf1 \xf10\xf1@\xf1P\xf1`\xf1p\xf1\x80\xf1\x90\xf1\xa0\xf1\xb0\xf1\xc0\xf1\xd0\xf1\xe0\xf1\xf0\xf2\x00\xf2\x10\xf2!\xf2@\xf2P\xf2`\xf2p\xf2\x80\xf2\x90\xf2\xa0\xf2\xb0\xf2\xc0\xf2\xd0\xf2\xe0\xf5\x00\xff\xff\xff\xe3\xff\\\xffX\xffS\xffB\xff1\xde\xe8\xdd\xedݬ\x10\r\x10\f\x10\n\x10\t\x10\b\x10\a\x10\x06\x10\x05\x10\x04\x10\x03\x10\x02\x0f\xf5\x0f\xf4\x0f\xf3\x0f\xf2\x0f\xf1\x0f\xf0\x0f\xef\x0f\xee\x0f\xed\x0f\xec\x0f\xeb\x0f\xea\x0f\xe9\x0f\xe8\x0f\xe7\x0f\xe6\x0f\xe5\x0f\xe4\x0f\xe3\x0f\xe2\x0f\xe1\x0f\xe0\x0f\xde\x0f\xdd\x0f\xdc\x0f\xdb\x0f\xda\x0f\xd9\x0f\xd8\x0f\xd7\x0f\xd6\x0f\xd5\x0f\xd4\x0f\xd3\r\xc2\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x06\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x05\n\a\x04\f\b\t\v\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,\x00\x00\x00,\x00\x00\x00,\x00\x00\x00,\x00\x00\x00,\x00\x00\x00,\x00\x00\x00,\x00\x00\x00,\x00\x00\x00,\x00\x00\x00,\x00\x00\x00,\x00\x00\x00,\x00\x00\x00,\x00\x00\x00\x90\x00\x00\x01\x14\x00\x00\x01\x98\x00\x00\x02t\x00\x00\x02\xd0\x00\x00\x03L\x00\x00\x03\xf0\x00\x00\x04T\x00\x00\x06$\x00\x00\x06\xe0\x00\x00\bl\x00\x00\tx\x00\x00\t\xd0\x00\x00\nT\x00\x00\v(\x00\x00\v\xd4\x00\x00\f\x84\x00\x00\rd\x00\x00\x0e\xa8\x00\x00\x0f\xd4\x00\x00\x10\x84\x00\x00\x11\x00\x00\x00\x11\x9c\x00\x00\x12l\x00\x00\x13,\x00\x00\x13\xd8\x00\x00\x14\x80\x00\x00\x14\xfc\x00\x00\x15\x90\x00\x00\x164\x00\x00\x17\x10\x00\x00\x18d\x00\x00\x18\xcc\x00\x00\x19p\x00\x00\x1aH\x00\x00\x1a\x94\x00\x00\x1b$\x00\x00\x1cd\x00\x00\x1d,\x00\x00\x1e\b\x00\x00\x1et\x00\x00\x1f(\x00\x00 \x8c\x00\x00 \xf0\x00\x00!\xa0\x00\x00\"0\x00\x00# \x00\x00$,\x00\x00$\xe0\x00\x00&D\x00\x00'\xe4\x00\x00(\x9c\x00\x00)T\x00\x00*\b\x00\x00*\xbc\x00\x00,\x10\x00\x00,\xf4\x00\x00-\xd8\x00\x00.@\x00\x00.\xd8\x00\x00/`\x00\x00/\xbc\x00\x000\x14\x00\x000\xa4\x00\x001\x94\x00\x002\x90\x00\x003d\x00\x0044\x00\x004\x94\x00\x005 \x00\x005\x80\x00\x005\xb8\x00\x006 \x00\x006\\\x00\x006\xbc\x00\x007H\x00\x007\xa8\x00\x008\f\x00\x008`\x00\x008\xb4\x00\x009L\x00\x009\xb4\x00\x00:h\x00\x00:\xec\x00\x00;\xc0\x00\x00<\x00\x00>\xe4\x00\x00?h\x00\x00?\xd8\x00\x00@H\x00\x00@\xbc\x00\x00A0\x00\x00A\xb8\x00\x00BX\x00\x00B\xf8\x00\x00Cd\x00\x00C\x9c\x00\x00DL\x00\x00D\xe4\x00\x00E\xb8\x00\x00F\x9c\x00\x00G0\x00\x00G\xdc\x00\x00H\xec\x00\x00I\x8c\x00\x00J8\x00\x00K\xac\x00\x00L\xe4\x00\x00Md\x00\x00N,\x00\x00N\x80\x00\x00N\xd4\x00\x00O\xb0\x00\x00P`\x00\x00P\xa8\x00\x00Q4\x00\x00Q\xa0\x00\x00R\f\x00\x00Rl\x00\x00S,\x00\x00S\x98\x00\x00T`\x00\x00U0\x00\x00W\xf0\x00\x00X\xdc\x00\x00Z\b\x00\x00[@\x00\x00[\x8c\x00\x00\\<\x00\x00\\\xf8\x00\x00]\x98\x00\x00^(\x00\x00^\xe4\x00\x00_\xa0\x00\x00`p\x00\x00b,\x00\x00b\xf4\x00\x00d\x04\x00\x00d\xec\x00\x00eP\x00\x00e\xd0\x00\x00f\xc4\x00\x00g`\x00\x00g\xa8\x00\x00iL\x00\x00i\xc0\x00\x00jD\x00\x00k\f\x00\x00k\xd4\x00\x00l\x80\x00\x00m@\x00\x00n,\x00\x00oL\x00\x00p\x84\x00\x00q\xa4\x00\x00r\xdc\x00\x00sx\x00\x00t\x10\x00\x00t\xa8\x00\x00uD\x00\x00{`\x00\x00|\x00\x00\x00|\xbc\x00\x00}\x10\x00\x00}\xa4\x00\x00~\x88\x00\x00\u007f\x94\x00\x00\x80\xbc\x00\x00\x81\x18\x00\x00\x81\x8c\x00\x00\x83H\x00\x00\x84\x14\x00\x00\x84\xd4\x00\x00\x85\xa8\x00\x00\x85\xe4\x00\x00\x86l\x00\x00\x87@\x00\x00\x88\x98\x00\x00\x89\xc0\x00\x00\x8b\x10\x00\x00\x8c\xc8\x00\x00\x8d\x8c\x00\x00\x8el\x00\x00\x8fH\x00\x00\x90 \x00\x00\x90\xc0\x00\x00\x91T\x00\x00\x92\f\x00\x00\x92H\x00\x00\x92\x84\x00\x00\x92\xc0\x00\x00\x92\xfc\x00\x00\x93`\x00\x00\x93\xc8\x00\x00\x94\x04\x00\x00\x94@\x00\x00\x94\xf0\x00\x00\x95\x80\x00\x00\x96$\x00\x00\x97\\\x00\x00\x98X\x00\x00\x99\x1c\x00\x00\x9aD\x00\x00\x9a\xb8\x00\x00\x9b\x98\x00\x00\x9c\xa0\x00\x00\x9dT\x00\x00\x9eX\x00\x00\x9e\xf8\x00\x00\x9f\x9c\x00\x00\xa0D\x00\x00\xa1P\x00\x00\xa2,\x00\x00\xa2\xa4\x00\x00\xa38\x00\x00\xa3\xa8\x00\x00\xa4d\x00\x00\xa5\\\x00\x00\xa8\x90\x00\x00\xab\b\x00\x00\xac\x1c\x00\x00\xac\xec\x00\x00\xad\x90\x00\x00\xad\xe8\x00\x00\xae\x80\x00\x00\xaf\x18\x00\x00\xaf\xb0\x00\x00\xb0H\x00\x00\xb0\xe0\x00\x00\xb1x\x00\x00\xb1\xcc\x00\x00\xb2 \x00\x00\xb2t\x00\x00\xb2\xc8\x00\x00\xb3X\x00\x00\xb3\xf4\x00\x00\xb4p\x00\x00\xb5\x00\x00\x00\xb5d\x00\x00\xb6\x1c\x00\x00\xb6\xd4\x00\x00\xb7\xb4\x00\x00\xb7\xf0\x00\x00\xb8x\x00\x00\xb9t\x00\x00\xb9\xf8\x00\x00\xba\xcc\x00\x00\xba\xcc\x00\x00\xba\xcc\x00\x00\xbb\xa8\x00\x00\xbc\x84\x00\x00\xbd@\x00\x00\xbe\x04\x00\x00\xbf\xc8\x00\x00\xc0\xc4\x00\x00\xc2\f\x00\x00\u008c\x00\x00\xc3\\\x00\x00\xc4 \x00\x00ļ\x00\x00\xc5\x10\x00\x00Ÿ\x00\x00Ɣ\x00\x00\xc80\x00\x00\xc8\xe0\x00\x00\xc9d\x00\x00\xc9\xcc\x00\x00ʨ\x00\x00ˀ\x00\x00\xcb\xe0\x00\x00\xcc\xf4\x00\x00͔\x00\x00\xcex\x00\x00\xce\xe8\x00\x00ϰ\x00\x00Ќ\x00\x00\xd1,\x00\x00ш\x00\x00\xd2\b\x00\x00҈\x00\x00\xd3\f\x00\x00ӌ\x00\x00\xd3\xec\x00\x00\xd48\x00\x00\xd5,\x00\x00՜\x00\x00\xd6`\x00\x00\xd6\xe8\x00\x00\xd7l\x00\x00\xd8H\x00\x00ش\x00\x00\xd9`\x00\x00\xd9\xc4\x00\x00\xdaT\x00\x00ڸ\x00\x00\xdb\x18\x00\x00۔\x00\x00\xdc@\x00\x00\xdc\xc8\x00\x00\xddl\x00\x00\xdd\xf0\x00\x00ބ\x00\x00\xdf\x18\x00\x00߬\x00\x00\xe0\xbc\x00\x00\xe1l\x00\x00\xe2p\x00\x00\xe3 \x00\x00\xe3\xe4\x00\x00\xe4\x80\x00\x00\xe5\xc8\x00\x00\xe6\xc0\x00\x00\xe7\x18\x00\x00\xe7\xec\x00\x00\xe8\xe4\x00\x00\xe9\xd8\x00\x00\xea\xd8\x00\x00\xeb\xd8\x00\x00\xec\xd4\x00\x00\xed\xd0\x00\x00\xee\xdc\x00\x00\xef\xe4\x00\x00\xf2\x04\x00\x00\xf3\xf4\x00\x00\xf4\x80\x00\x00\xf54\x00\x00\xf6\x10\x00\x00\xf6\x9c\x00\x00\xf7\x18\x00\x00\xf8X\x00\x00\xf8\xc0\x00\x00\xf9$\x00\x00\xfal\x00\x00\xfb\xbc\x00\x00\xfc(\x00\x00\xfc\xb8\x00\x00\xfd\f\x00\x00\xfd`\x00\x00\xfd\xb4\x00\x00\xfe\b\x00\x00\xfe\xb8\x00\x00\xff\b\x00\x01\x00\x14\x00\x01\x05\xb4\x00\x01\x06\xf4\x00\x01\a\xf8\x00\x01\b\xd0\x00\x01\td\x00\x01\n\x10\x00\x01\n\x98\x00\x01\v\x18\x00\x01\f\x04\x00\x01\f\xa4\x00\x01\r,\x00\x01\x0e\x00\x00\x01\x0f\x88\x00\x01\x11,\x00\x01\x11\xa0\x00\x01\x12\xcc\x00\x01\x138\x00\x01\x13\xe4\x00\x01\x14\x90\x00\x01\x15(\x00\x01\x15\xa4\x00\x01\x16X\x00\x01\x16\xfc\x00\x01\x17\xc0\x00\x01\x18\x84\x00\x01\x19x\x00\x01\x1a|\x00\x01\x1bT\x00\x01\x1c\xd4\x00\x01\x1d@\x00\x01\x1d\xd4\x00\x01\x1e\x90\x00\x01\x1f\x04\x00\x01\x1f|\x00\x01 \xa4\x00\x01!\xc0\x00\x01\"x\x00\x01#\b\x00\x01#l\x00\x01$\x04\x00\x01$\xcc\x00\x01'h\x00\x01(\xe8\x00\x01*L\x00\x01,T\x00\x01.L\x00\x011t\x00\x011\xf4\x00\x012\xe0\x00\x0130\x00\x013\xb0\x00\x014\xa8\x00\x015t\x00\x016T\x00\x017$\x00\x018\f\x00\x019H\x00\x01:\x10\x00\x01:\xf0\x00\x01;\x90\x00\x01<\x84\x00\x01<\xd8\x00\x01?X\x00\x01@\x1c\x00\x01A\xc0\x00\x01B\xc8\x00\x01C\xc8\x00\x01D\x9c\x00\x01EH\x00\x01FH\x00\x01Gp\x00\x01HH\x00\x01Ix\x00\x01J \x00\x01J\xe4\x00\x01K\xd4\x00\x01L\xa0\x00\x01M\x18\x00\x01N@\x00\x01P@\x00\x01Q\xa0\x00\x01R\xe0\x00\x01SD\x00\x01T \x00\x01UL\x00\x01V`\x00\x01V\xd4\x00\x01WX\x00\x01X4\x00\x01X\xa0\x00\x01Z\x04\x00\x01Z\x88\x00\x01[d\x00\x01[\xe0\x00\x01\\|\x00\x01]\xd8\x00\x01^\xa0\x00\x01`\x94\x00\x01aH\x00\x01a\xbc\x00\x01b\xf0\x00\x01cX\x00\x01d\xac\x00\x01et\x00\x01fh\x00\x01g\xdc\x00\x01h\xb4\x00\x01i\\\x00\x01jx\x00\x01n\x84\x00\x01p@\x00\x01s\xe0\x00\x01v\x10\x00\x01w\xc8\x00\x01x\x90\x00\x01y\x88\x00\x01z\x8c\x00\x01{h\x00\x01|\x8c\x00\x01}\x1c\x00\x01}\xa4\x00\x01\u007f\\\x00\x01\u007f\x98\x00\x01\u007f\xf8\x00\x01\x80l\x00\x01\x81t\x00\x01\x82\x90\x00\x01\x834\x00\x01\x83\xa4\x00\x01\x84\xc8\x00\x01\x85\xb0\x00\x01\x86\xa4\x00\x01\x88t\x00\x01\x89\x8c\x00\x01\x8a8\x00\x01\x8b8\x00\x01\x8b\xa0\x00\x01\x8eL\x00\x01\x8e\xa8\x00\x01\x8fT\x00\x01\x90\x10\x00\x01\x91\x14\x00\x01\x93\x90\x00\x01\x94\x14\x00\x01\x95\x04\x00\x01\x95\xfc\x00\x01\x96\xf8\x00\x01\x97\xa0\x00\x01\x99|\x00\x01\x9a\xc8\x00\x01\x9c\x10\x00\x01\x9d\b\x00\x01\x9d\xd8\x00\x01\x9e|\x00\x01\x9f\x18\x00\x01\x9f\xe8\x00\x01\xa0\xc4\x00\x01\xa2\f\x00\x01\xa34\x00\x01\xa4x\x00\x01\xa5\xb0\x00\x01\xa6\x80\x00\x01\xa7L\x00\x01\xa8\x1c\x00\x01\xa8\x90\x00\x01\xa8\xec\x00\x01\xa8\xec\x00\x01\xa8\xec\x00\x01\xa9X\x00\x01\xaa(\x00\x01\xab \x00\x01\xab\xcc\x00\x01\xac\xac\x00\x01\xad\xa8\x00\x01\xae \x00\x01\xae\x88\x00\x01\xaf\x04\x00\x01\xaf\xa8\x00\x01\xb0@\x00\x01\xb0\x88\x00\x01\xb6\xbc\x00\x01\xb7l\x00\x01\xb8\xe0\x00\x01\xb9t\x00\x01\xba\x04\x00\x01\xba\x94\x00\x01\xbb$\x00\x01\xbb\xa4\x00\x01\xbc\b\x00\x01\xbcx\x00\x01\xbdL\x00\x01\xbeL\x00\x01\xbe\xa4\x00\x01\xbf \x00\x01\xc0H\x00\x01\xc1\x18\x00\x01\xc1\xc4\x00\x01\xc3\x04\x00\x01\xc3\xe4\x00\x01Ġ\x00\x01\xc5T\x00\x01\xc6(\x00\x01\xc6\xec\x00\x01\xc8\f\x00\x01\xc9\f\x00\x01ʈ\x00\x01ˠ\x00\x01\xcc\xf8\x00\x01\xce\x1c\x00\x01ϔ\x00\x01\xd0l\x00\x01\xd1d\x00\x01\xd2\xdc\x00\x01\xd3P\x00\x01\xd3\xf8\x00\x01Մ\x00\x01\xd6x\x00\x01\xd7p\x00\x01\xd7\xfc\x00\x01\xd8\xf4\x00\x01ڬ\x00\x01\xdbT\x00\x01\xdcT\x00\x01\xdd\f\x00\x01\xdd\xf0\x00\x01ވ\x00\x01\xdfL\x00\x01\xe1\x80\x00\x01\xe2\xf8\x00\x01\xe4\x18\x00\x01\xe5\f\x00\x01\xe6<\x00\x01\xe7H\x00\x01\xe7\xa8\x00\x01\xe8$\x00\x01\xe8\xd4\x00\x01\xe9l\x00\x01\xea\x1c\x00\x01\xea\xd4\x00\x01\xeb\xe4\x00\x01\xec4\x00\x01\xec\xb8\x00\x01\xec\xf4\x00\x01\xed\xf0\x00\x01\xef\b\x00\x01\xef\xa4\x00\x01\xf0\x04\x00\x01\xf0\xcc\x00\x01\xf1 \x00\x01\xf2P\x00\x01\xf3l\x00\x01\xf3\xe8\x00\x01\xf5\f\x00\x01\xf6,\x00\x01\xf6\xc0\x00\x01\xf7x\x00\x01\xf7\xe0\x00\x01\xf8p\x00\x01\xf9,\x00\x01\xfax\x00\x01\xfbt\x00\x01\xfc\f\x00\x01\xfcd\x00\x01\xfd\f\x00\x01\xfd\x8c\x00\x01\xfe4\x00\x01\xff\b\x00\x01\xff\xd0\x00\x02\x014\x00\x02\x02\x1c\x00\x02\x03,\x00\x02\x04h\x00\x02\x05\xd4\x00\x02\aP\x00\x02\t4\x00\x02\n\xd4\x00\x02\f\xe0\x00\x02\r\xf0\x00\x02\x0f\x18\x00\x02\x104\x00\x02\x11\xe4\x00\x02\x13<\x00\x02\x14,\x00\x02\x15,\x00\x02\x164\x00\x02\x170\x00\x02\x188\x00\x02\x19$\x00\x02\x1a\x88\x00\x02\x1b8\x00\x02\x1d\xb4\x00\x02\x1eT\x00\x02\x1e\xcc\x00\x02 |\x00\x02!h\x00\x02\"\xac\x00\x02$L\x00\x02%0\x00\x02&H\x00\x02'\x88\x00\x02(\xf4\x00\x02)\x8c\x00\x02*0\x00\x02*\xdc\x00\x02+\x94\x00\x02,\xdc\x00\x02.$\x00\x02.\xec\x00\x020\xec\x00\x021\x84\x00\x022@\x00\x022\xfc\x00\x023\xb8\x00\x024t\x00\x025$\x00\x026\xf4\x00\x029 \x00\x02:\x8c\x00\x02:\xd4\x00\x02;\f\x00\x02;\x88\x00\x02<(\x00\x02<\xd8\x00\x02=4\x00\x02?\xb8\x00\x02@\x98\x00\x02A\xe0\x00\x02C\xa0\x00\x02D\xfc\x00\x02F\x98\x00\x02H`\x00\x02H\xf4\x00\x02I\xcc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02L\xbc\x00\x02\x00p\x00\x00\x03\x10\x06\x00\x00\x03\x00\a\x00\x007!\x11!\x03\x11!\x11\xe0\x01\xc0\xfe@p\x02\xa0p\x05 \xfap\x06\x00\xfa\x00\x00\x00\x00\x00\x01\x00]\xff\x00\x06\xa3\x05\x80\x00\x1d\x00\x00\x01\x14\a\x01\x11!2\x16\x14\x06#!\"&463!\x11\x01&54>\x013!2\x1e\x01\x06\xa3+\xfd\x88\x01@\x1a&&\x1a\xfc\x80\x1a&&\x1a\x01@\xfd\x88+$(\x17\x05\x80\x17($\x05F#+\xfd\x88\xfd\x00&4&&4&\x03\x00\x02x+#\x17\x1b\b\b\x1b\x00\x00\x01\x00\x00\xff\x00\x06\x00\x05\x80\x00+\x00\x00\x01\x11\x14\x0e\x02\".\x024>\x0232\x17\x11\x05\x11\x14\x0e\x02\".\x024>\x0232\x17\x11467\x01632\x16\x06\x00DhgZghDDhg-iW\xfd\x00DhgZghDDhg-iW&\x1e\x03@\f\x10(8\x05 \xfb\xa02N+\x15\x15+NdN+\x15'\x02\x19\xed\xfd;2N+\x15\x15+NdN+\x15'\x03\xc7\x1f3\n\x01\x00\x048\x00\x02\x00\x00\xff\x00\x06\x80\x05\x80\x00\a\x00!\x00\x00\x00\x10\x00 \x00\x10\x00 \x01\x14\x06#\"'\x01\x06#\"$&\x02\x10\x126$ \x04\x16\x12\x15\x14\a\x01\x16\x04\x80\xfe\xf9\xfe\x8e\xfe\xf9\x01\a\x01r\x03\aL46$\xfe\xa9\xb3\u070f\xfe\xfb\xbdoo\xbd\x01\x05\x01\x1e\x01\x05\xbdo|\x01W%\x02\a\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\xfe\x804L&\x01V|o\xbd\x01\x05\x01\x1e\x01\x05\xbdoo\xbd\xfe\xfb\x8fܳ\xfe\xa9%\x00\x00\x03\x00\x00\xff\x80\a\x00\x05\x00\x00\x1a\x00=\x00M\x00\x00%\x11\x06\a\x04\a\x0e\x02+\x02\".\x01'&%&'\x11\x14\x163!26\x11<\x02.\x03#!\"\x06\x15\x14\x17\x16\x17\x1e\x04;\x022>\x03767>\x017\x11\x14\x06#!\"&5\x11463!2\x16\x06\x80 %\xfe\xf4\x9e3@m0\x01\x010m@3\x9e\xfe\xf4% \x13\r\x05\xc0\r\x13\x01\x05\x06\f\b\xfa@\r\x13\x93\xc1\xd0\x06:\"7.\x14\x01\x01\x14.7\":\x06\xd0\xc16]\x80^B\xfa@B^^B\x05\xc0B^ \x03\x00$\x1e΄+0110+\x84\xce\x1e$\xfd\x00\r\x13\x13\x04(\x02\x12\t\x11\b\n\x05\x13\r\xa8t\x98\xa5\x051\x1a%\x12\x12%\x1a1\x05\xa5\x98+\x91`\xfb\xc0B^^B\x04@B^^\x00\x00\x01\x00\x00\xff\x80\a\x00\x05\x80\x00\x1c\x00\x00\x04\"'\x01.\x0454632\x1e\x02\x17>\x0332\x16\x15\x14\a\x01\x03\x9a4\x12\xfd\x90\n#L\x81oP$$Po\x81>\xe0\xfe\xe5\xfd\x91\x80\x12\x02Z\b$_d\x8eC\xdc\xf8+I@$$@I+\xf8\xdc\xdd\xe5\xfd\xa8\x00\x00\x01\x00\x00\xff\xad\x06\x80\x05\xe0\x00\"\x00\x00\x01\x14\a\x01\x13\x16\x15\x14\x06#\"'%\x05\x06#\"&547\x13\x01&547%\x1362\x17\x13\x05\x16\x06\x80\x1a\xfe\x95V\x01\x15\x14\x13\x15\xfe?\xfe?\x16\x12\x15\x15\x02V\xfe\x94\x198\x01\xf6\xe1\x13<\x13\xe1\x01\xf68\x03y\x16\x1a\xfe\x9e\xfe\f\a\r\x15\x1d\f\xec\xec\f\x1d\x15\x06\x0e\x01\xf4\x01b\x1b\x15%\tI\x01\xc7))\xfe9I\t\x00\x00\x00\x00\x02\x00\x00\xff\xad\x06\x80\x05\xe0\x00\t\x00+\x00\x00\t\x01%\v\x01\x05\x01\x03%\x05\x01\x14\a\x01\x13\x16\x15\x14#\"'%\x05\x06#\"&547\x13\x01&547%\x1362\x17\x13\x05\x16\x04q\x012\xfeZ\xbd\xbd\xfeZ\x012I\x01z\x01y\x01\xc7\x1a\xfe\x95V\x01)\x13\x15\xfe?\xfe?\x16\x12\x15\x15\x02V\xfe\x94\x198\x01\xf6\xe1\x13<\x13\xe1\x01\xf68\x02\x14\x01)>\x01~\xfe\x82>\xfe\xd7\xfe[\xc7\xc7\x03\n\x16\x1a\xfe\x9e\xfe\f\a\r2\f\xec\xec\f\x1d\x15\x06\x0e\x01\xf4\x01b\x1b\x15%\tI\x01\xc7))\xfe9I\t\x00\x00\x02\x00\x00\xff\x80\x05\x00\x05\x80\x00\x15\x00\x1d\x00\x00%\x14\x06#!\"&54>\x033\x16 72\x1e\x03\x00\x10\x06 &\x106 \x05\x00}X\xfc\xaaX}\x11.GuL\x83\x01l\x83LuG.\x11\xff\x00\xe1\xfe\xc2\xe1\xe1\x01>\x89m\x9c\x9cmU\x97\x99mE\x80\x80Em\x99\x97\x03\xc1\xfe\xc2\xe1\xe1\x01>\xe1\x00\x00\x00\v\x00\x00\xff\x00\a\x80\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00o\x00\u007f\x00\x8f\x00\x9f\x00\xaf\x00\x00\x0554&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x01\x114&#!\"\x06\x15\x11\x14\x163!26\x0154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x0154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x01\x114&#!\"\x06\x15\x11\x14\x163!26\x0154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x01267\x11\x14\x06#!\"&5\x11463!2\x16\x01\x80&\x1a\x80\x1a&&\x1a\x80\x1a&&\x1a\x80\x1a&&\x1a\x80\x1a&&\x1a\x80\x1a&&\x1a\x80\x1a&\x04\x00&\x1a\xfd\x00\x1a&&\x1a\x03\x00\x1a&\xfc\x00&\x1a\x80\x1a&&\x1a\x80\x1a&\x05\x80&\x1a\x80\x1a&&\x1a\x80\x1a&\xfe\x80&\x1a\xfd\x00\x1a&&\x1a\x03\x00\x1a&\x01\x80&\x1a\x80\x1a&&\x1a\x80\x1a&&\x1a\x80\x1a&&\x1a\x80\x1a&&\x1a\x80\x1a&&\x1a\x80\x1a&\x80^B\xf9\xc0B^^B\x06@B^@\x80\x1a&&\x1a\x80\x1a&&\x01\x9a\x80\x1a&&\x1a\x80\x1a&&\x01\x9a\x80\x1a&&\x1a\x80\x1a&&\xfd\x1a\x02\x00\x1a&&\x1a\xfe\x00\x1a&&\x04\x9a\x80\x1a&&\x1a\x80\x1a&&\xfb\x9a\x80\x1a&&\x1a\x80\x1a&&\x03\x1a\x02\x00\x1a&&\x1a\xfe\x00\x1a&&\xfe\x9a\x80\x1a&&\x1a\x80\x1a&&\x01\x9a\x80\x1a&&\x1a\x80\x1a&&\x01\x9a\x80\x1a&&\x1a\x80\x1a&&\xba\xfa\xc0B^^B\x05@B^^\x00\x04\x00\x00\x00\x00\x06\x80\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00\x00\x01\x11\x14\x06#!\"&5\x11463!2\x16\x19\x01\x14\x06#!\"&5\x11463!2\x16\x01\x11\x14\x06#!\"&5\x11463!2\x16\x19\x01\x14\x06#!\"&5\x11463!2\x16\x03\x00L4\xfe\x004LL4\x02\x004LL4\xfe\x004LL4\x02\x004L\x03\x80L4\xfe\x004LL4\x02\x004LL4\xfe\x004LL4\x02\x004L\x02\x00\xfe\x804LL4\x01\x804LL\x02\xcc\xfe\x804LL4\x01\x804LL\xfc\xcc\xfe\x804LL4\x01\x804LL\x02\xcc\xfe\x804LL4\x01\x804LL\x00\t\x00\x00\x00\x00\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00o\x00\u007f\x00\x8f\x00\x00\x01\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x02\x008(\xfe\xc0(88(\x01@(88(\xfe\xc0(88(\x01@(8\x02\x808(\xfe\xc0(88(\x01@(8\xfd\x808(\xfe\xc0(88(\x01@(8\x02\x808(\xfe\xc0(88(\x01@(8\x02\x808(\xfe\xc0(88(\x01@(8\xfd\x808(\xfe\xc0(88(\x01@(8\x02\x808(\xfe\xc0(88(\x01@(88(\xfe\xc0(88(\x01@(8\x01 \xc0(88(\xc0(88\x01\xd8\xc0(88(\xc0(88\xfd\xd8\xc0(88(\xc0(88\x03\xd8\xc0(88(\xc0(88\xfd\xd8\xc0(88(\xc0(88\xfd\xd8\xc0(88(\xc0(88\x03\xd8\xc0(88(\xc0(88\xfd\xd8\xc0(88(\xc0(88\x01\xd8\xc0(88(\xc0(88\x00\x00\x06\x00\x00\x00\x00\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00\x00\x01\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x02\x008(\xfe\xc0(88(\x01@(88(\xfe\xc0(88(\x01@(8\x05\x008(\xfc@(88(\x03\xc0(8\xfb\x008(\xfe\xc0(88(\x01@(8\x05\x008(\xfc@(88(\x03\xc0(88(\xfc@(88(\x03\xc0(8\x01 \xc0(88(\xc0(88\x01\xd8\xc0(88(\xc0(88\xfd\xd8\xc0(88(\xc0(88\x03\xd8\xc0(88(\xc0(88\xfd\xd8\xc0(88(\xc0(88\x01\xd8\xc0(88(\xc0(88\x00\x00\x00\x01\x00y\x00\x0e\x06\x87\x04\xb2\x00\x16\x00\x00\x00\x14\a\x01\a\x06\"/\x01\x01&4?\x0162\x17\t\x0162\x1f\x01\x06\x87\x1c\xfd,\x88\x1cP\x1c\x88\xfe\x96\x1c\x1c\x88\x1cP\x1c\x01&\x02\x90\x1cP\x1c\x88\x03\xf2P\x1c\xfd,\x88\x1c\x1c\x88\x01j\x1cP\x1c\x88\x1c\x1c\xfe\xd9\x02\x91\x1c\x1c\x88\x00\x01\x00n\xff\xee\x05\x12\x04\x92\x00#\x00\x00$\x14\x0f\x01\x06\"'\t\x01\x06\"/\x01&47\t\x01&4?\x0162\x17\t\x0162\x1f\x01\x16\x14\a\t\x01\x05\x12\x1c\x88\x1cP\x1c\xfe\xda\xfe\xda\x1cP\x1c\x88\x1c\x1c\x01&\xfe\xda\x1c\x1c\x88\x1cP\x1c\x01&\x01&\x1cP\x1c\x88\x1c\x1c\xfe\xda\x01&\xfeP\x1c\x88\x1c\x1c\x01&\xfe\xda\x1c\x1c\x88\x1cP\x1c\x01&\x01&\x1cP\x1c\x88\x1c\x1c\xfe\xda\x01&\x1c\x1c\x88\x1cP\x1c\xfe\xda\xfe\xda\x00\x00\x03\x00\x00\xff\x00\x06\x80\x05\x80\x00#\x00+\x00D\x00\x00\x01\x15\x14\x06+\x01\x15\x14\x06+\x01\"&=\x01#\"&=\x0146;\x01546;\x012\x16\x1d\x0132\x1e\x01\x10\x00 \x00\x10\x00 \x00\x14\x06#\"'\x01\x06#\"$&\x02\x10\x126$ \x04\x16\x12\x15\x14\a\x01\x04\x00\x13\r\xe0\x13\r@\r\x13\xe0\r\x13\x13\r\xe0\x13\r@\r\x13\xe0\r\x13\x80\xfe\xf9\xfe\x8e\xfe\xf9\x01\a\x01r\x03\aK56$\xfe\xa9\xb3\u070f\xfe\xfb\xbdoo\xbd\x01\x05\x01\x1e\x01\x05\xbdo|\x01W\x02\xe0@\r\x13\xe0\r\x13\x13\r\xe0\x13\r@\r\x13\xe0\r\x13\x13\r\xe0\x13\xe6\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\xfe\xb5jK&\x01V|o\xbd\x01\x05\x01\x1e\x01\x05\xbdoo\xbd\xfe\xfb\x8fܳ\xfe\xa9\x00\x00\x03\x00\x00\xff\x00\x06\x80\x05\x80\x00\x0f\x00\x17\x000\x00\x00\x01\x15\x14\x06#!\"&=\x01463!2\x1e\x01\x10\x00 \x00\x10\x00 \x00\x14\x06#\"'\x01\x06#\"$&\x02\x10\x126$ \x04\x16\x12\x15\x14\a\x01\x04\x00\x13\r\xfd\xc0\r\x13\x13\r\x02@\r\x13\x80\xfe\xf9\xfe\x8e\xfe\xf9\x01\a\x01r\x03\aK56$\xfe\xa9\xb3\u070f\xfe\xfb\xbdoo\xbd\x01\x05\x01\x1e\x01\x05\xbdo|\x01W\x02\xe0@\r\x13\x13\r@\r\x13\x13\xe6\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\xfe\xb5jK&\x01V|o\xbd\x01\x05\x01\x1e\x01\x05\xbdoo\xbd\xfe\xfb\x8fܳ\xfe\xa9\x00\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x06\x00\x00)\x005\x00\x00\x01\x14\x02\x06\x04 $&\x0254\x1276\x16\x17\x16\x06\a\x0e\x01\x15\x14\x1e\x022>\x0254&'.\x017>\x01\x17\x16\x12\x01\x11\x14\x06\"&5\x11462\x16\x06\x00z\xce\xfe\xe4\xfe\xc8\xfe\xe4\xcez\xa1\x92+i\x1f \x0f*bkQ\x8a\xbdн\x8aQkb*\x0f \x1fj*\x92\xa1\xfd\x80LhLLhL\x02\x80\x9c\xfe\xe4\xcezz\xce\x01\x1c\x9c\xb6\x01Bm \x0e+*i J\xd6yh\xbd\x8aQQ\x8a\xbdhy\xd6J i*+\x0e m\xfe\xbe\x02J\xfd\x804LL4\x02\x804LL\x00\x00\x00\x00\x05\x00\x00\xff\x80\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00O\x00\x00%\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x11\x14\x06+\x01\"&5\x1146;\x012\x16%\x11\x14\x06+\x01\"&5\x1146;\x012\x16\x01\x11\x14\x06+\x01\"&5\x1146;\x012\x16\x01\x11\x14\x06+\x01\"&5\x1146;\x012\x16\x01\x00\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x01\x80\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x01\x80\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x01\x80\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x01\x80\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12`\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12r\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\x12\xf2\xfd\xc0\x0e\x12\x12\x0e\x02@\x0e\x12\x12\x01r\xfc@\x0e\x12\x12\x0e\x03\xc0\x0e\x12\x12\x01\xf2\xfa@\x0e\x12\x12\x0e\x05\xc0\x0e\x12\x12\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\a\x00n\x00\x00\x004&\"\x06\x14\x162\x01\x15\x14\x06\x0f\x01\x06\a\x16\x17\x16\x14\a\x0e\x01#\"/\x01\x06\a\x06\a\x06+\x01\"&/\x01&'\a\x06#\"'&'&547>\x017&/\x01.\x01=\x0146?\x0167&'&547>\x0132\x1f\x0167676;\x012\x16\x1f\x01\x16\x177632\x17\x16\x17\x16\x15\x14\a\x0e\x01\a\x16\x1f\x01\x1e\x01\x04\x00\x96Ԗ\x96\xd4\x02\x96\x10\f\xb9\x13\x14#H\n\t\x1b\x90\x16\f\x0e\x8a,/\x10\r\a\x1d\xde\x0e\x15\x01\x1c1)\x8d\n\x0f\x0e\v~'\a\b\x0fH\x12\x1b\x0e\xb7\r\x10\x10\v\xba\x0e\x19(C\n\t\x1a\x91\x16\r\r\x8a,/\x10\r\a\x1d\xde\x0e\x15\x01\x1c1)\x8e\t\x0f\r\f\x81$\a\b\x0fH\x12\x1a\x0f\xb7\r\x10\x02\x16Ԗ\x96Ԗ\x01m\xde\f\x16\x02\x1c6%2X\f\x1a\n%\x8e\tl\x17\x0f\x882\x1c\x11\r\xb8\x10\x15k\t\vr6\n\r\f\v\x15[\x1921\x1b\x02\x15\r\xde\f\x16\x02\x1c..9Q\f\f\n\r$\x8f\nk\x17\x0f\x882\x1c\x11\r\xb8\x10\x15k\t\nw3\b\x0e\f\v\x15[\x1920\x1c\x02\x15\x00\x00\x06\x00\x00\xff\x80\x05\x80\x05\x80\x00\x0f\x00\x1f\x00/\x00;\x00C\x00g\x00\x00\x01\x11\x14\x06+\x01\"&5\x1146;\x012\x16\x05\x11\x14\x06+\x01\"&5\x1146;\x012\x16\x05\x11\x14\x06+\x01\"&5\x1146;\x012\x16\x13\x11!\x11\x14\x1e\x013!2>\x01\x01!'&'!\x06\a\x05\x15\x14\x06+\x01\x11\x14\x06#!\"&5\x11#\"&=\x01463!7>\x013!2\x16\x1f\x01!2\x16\x02\x00\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x01\x00\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x01\x00\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x80\xfc\x80\x0e\x0f\x03\x03@\x03\x0f\x0e\xfd`\x01\xc00\a\n\xfe\xc3\n\a\x03o\x12\x0e`^B\xfc\xc0B^`\x0e\x12\x12\x0e\x015F\x0fN(\x01@(N\x0fF\x015\x0e\x12\x03 \xfd\xc0\x0e\x12\x12\x0e\x02@\x0e\x12\x12\x0e\xfd\xc0\x0e\x12\x12\x0e\x02@\x0e\x12\x12\x0e\xfd\xc0\x0e\x12\x12\x0e\x02@\x0e\x12\x12\xfd\x1e\x03\xb4\xfcL\x16%\x11\x11%\x04Ju\t\x02\x02\t\x95@\x0e\x12\xfcLSyuS\x03\xb8\x12\x0e@\x0e\x12\xa7%44%\xa7\x12\x00\x00\x00\x00\x02\x00\x1a\x00\x00\x06f\x05\x03\x00\x13\x005\x00\x00\x01\x11\x14\x06#!\x11!\x11!\"&5\x11465\t\x01\x167\a\x06\a#\"'\t\x01\x06'&/\x01&67\x0162\x1f\x01546;\x012\x16\x15\x11\x17\x1e\x01\x05\x80&\x1a\xfe\x80\xff\x00\xfe\x80\x1a&\x01\x02?\x02?\x01\xdf>\b\r\x03\r\b\xfdL\xfdL\f\f\r\b>\b\x02\n\x02\xcf X \xf4\x12\x0e\xc0\x0e\x12\xdb\n\x02\x02 \xfe \x1a&\x01\x80\xfe\x80&\x1a\x01\xe0\x01\x04\x01\x01\xda\xfe&\x02AJ\t\x02\a\x02A\xfd\xbf\b\x01\x02\tJ\n\x1b\b\x02W\x1a\x1a\xcc\xc3\x0e\x12\x12\x0e\xfeh\xb6\b\x1b\x00\x00\x03\x00\x00\xff\x00\x06\x00\x06\x00\x00\x13\x00\x1a\x00#\x00\x00\x01\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x17\a\x11!&'\x01&\x01\x11!\"&5\x11!\x11\x05\xbc\x1c(8(\xfa\xc0(88(\x03\x80(`\x1c\x84\x01x\n\f\xfe\xc7\f\x01c\xfe`(8\xfd\x00\x04\x84\x1c`(\xfb\x80(88(\x06@(8(\x1cD\xfe\x88\x1d\f\x019\f\xfa\x12\x04\x008(\x01\xa0\xfa\x00\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x14\x00 \x00,\x00\x00\x01\x11\x14\x06#!\"&=\x0146;\x01\x1146;\x012\x16\x00\x10.\x01 \x0e\x01\x10\x1e\x01 6\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x03\x80\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\xe0\x12\x0e@\x0e\x12\x01\xa0\x92\xfa\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\x01r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x03\xe0\xfe@\x0e\x12\x12\x0e@\x0e\x12\x01`\x0e\x12\x12\xfd\xfe\x01(\xfa\x92\x92\xfa\xfe\xd8\xfa\x92\x92\x02_\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x02\x002\x00\x00\aN\x05\x00\x00\x11\x00C\x00\x00\x015\x03.\x01+\x01\"\x06\a\x03\x15\x06\x16;\x0126\x01\x14#!26'\x03.\x01#!\"\x06\a\x03\x06\x163!\"547\x01>\x013!\"\x06\x0f\x01\x06\x16;\x0126/\x01.\x01#!2\x16\x17\x01\x16\x04W\x18\x01\x14\r\xba\r\x14\x01\x18\x01\x12\f\xf4\f\x12\x02\xf6.\xfd@\r\x12\x01\x14\x01\x14\r\xfe\xf0\r\x14\x01\x14\x01\x12\r\xfd@.\x1a\x01\xa1\b$\x14\x01S\r\x14\x01\x0f\x01\x12\r\xa6\r\x12\x01\x0f\x01\x14\r\x01S\x14$\b\x01\xa1\x1a\x02\x1c\x04\x01@\r\x13\x13\r\xfe\xc0\x04\f\x10\x10\xfe9I\x13\r\x01\x00\r\x13\x13\r\xff\x00\r\x13I6>\x04\x14\x13\x1c\x13\r\xc0\x0e\x12\x12\x0e\xc0\r\x13\x1c\x13\xfb\xec>\x00\x04\x00\x00\x00\x00\x06\x80\x06\x00\x00\a\x00\x0f\x00%\x00=\x00\x00$4&\"\x06\x14\x162$4&\"\x06\x14\x162\x13\x11\x14\x06#!\"&5\x11463!\x17\x162?\x01!2\x16\x01\x16\a\x01\x06\"'\x01&763!\x11463!2\x16\x15\x11!2\x05\x00&4&&4\x01&&4&&4\xa68(\xfa@(88(\x01ч:\x9c:\x88\x01\xd0(8\xfe\xbb\x11\x1f\xfe@\x126\x12\xfe@\x1f\x11\x11*\x01\x00&\x1a\x01\x00\x1a&\x01\x00*\xa64&&4&&4&&4&\x01 \xfe\xc0(88(\x01@(8\x8888\x888\x02\x11)\x1d\xfe@\x13\x13\x01\xc0\x1d)'\x01\xc0\x1a&&\x1a\xfe@\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x18\x00$\x000\x00\x00\x01\x14\a\x01\x06\"'\x01&76;\x01\x1146;\x012\x16\x15\x1132\x16\x02 \x0e\x01\x10\x1e\x01 >\x01\x10&\x04\x10\x02\x04 $\x02\x10\x12$ \x04\x04`\n\xfe\xc1\v\x18\v\xfe\xc0\x0f\b\b\x16\xc0\x12\x0e\xc0\x0e\x12\xc0\x0e\x12\xcc\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\x92\x92\x01r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02`\f\f\xfe\xc1\t\t\x01@\x10\x13\x14\x01`\x0e\x12\x12\x0e\xfe\xa0\x12\x022\x92\xfa\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\xbd\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x18\x00$\x000\x00\x00\x01\x06+\x01\x11\x14\x06+\x01\"&5\x11#\"&547\x0162\x17\x01\x16\x02 \x0e\x01\x10\x1e\x01 >\x01\x10&\x04\x10\x02\x04 $\x02\x10\x12$ \x04\x04^\b\x16\xc0\x12\x0e\xc0\x0e\x12\xc0\x0e\x12\n\x01?\v\x18\v\x01@\x0f\xd2\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\x92\x92\x01r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02\x94\x14\xfe\xa0\x0e\x12\x12\x0e\x01`\x12\x0e\f\f\x01?\t\t\xfe\xc0\x10\x01\xf9\x92\xfa\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\xbd\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x02\x00\x00\x00\x00\x06\x00\x05\x00\x00\r\x00#\x00\x00\x01!.\x01'\x03!\x03\x0e\x01\a!\x17!%\x11\x14\x06#!\"&5\x1147\x13>\x013!2\x16\x17\x13\x16\x03\xff\x01<\x01\x03\x01\xd4\xfd<\xd4\x01\x03\x01\x01<_\x01@\x02`&\x1a\xfa\x80\x1a&\x19\xee\n5\x1a\x03@\x1a5\n\xee\x19\x02@\x03\v\x02\x01\xf0\xfe\x10\x03\v\x02\xc0\xa2\xfe\x1e\x1a&&\x1a\x01\xe2>=\x02(\x19\"\"\x19\xfd\xd8=\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x1b\x00'\x00\x00\x00\x14\a\x01\x06#\"'&5\x11476\x17\x01\x16\x10.\x01 \x0e\x01\x10\x1e\x01 6\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04\xa0 \xfd\xe0\x0f\x11\x10\x10 !\x1f\x02 \xa0\x92\xfa\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\x01r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02\xa5J\x12\xfe\xc0\t\b\x13%\x02\x80%\x13\x12\x13\xfe\xc0\xcb\x01(\xfa\x92\x92\xfa\xfe\xd8\xfa\x92\x92\x02_\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x01\x00\x00\xff\x80\x06\x00\x05\x80\x003\x00\x00\x01\x11\x14\x06#!\"'&?\x01&#\"\x0e\x02\x14\x1e\x023267672\x1f\x01\x1e\x01\a\x06\x04#\"$&\x02\x10\x126$32\x04\x1776\x17\x16\x06\x00&\x1a\xfe@*\x11\x11\x1f\x8a\x94\xc9h\xbd\x8aQQ\x8a\xbdhw\xd4I\a\x10\x0f\n\x89\t\x01\bm\xfeʬ\x9c\xfe\xe4\xcezz\xce\x01\x1c\x9c\x93\x01\x13k\x82\x1d)'\x05\x00\xfe@\x1a&('\x1e\x8a\x89Q\x8a\xbdн\x8aQh_\n\x02\t\x8a\b\x19\n\x84\x91z\xce\x01\x1c\x018\x01\x1c\xcezoe\x81\x1f\x11\x11\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00$\x00G\x00\x00\x01\x14\a\x02\x00!\"$'\a\x06\"&5\x11463!2\x16\x14\x0f\x01\x1e\x013267676;\x012\x16\x13\x11\x14\x06#!\"&4?\x01&#\"\x06\a\x06\a\x06+\x01\"&=\x01\x12\x00!2\x04\x17762\x16\x05\xe7\x01@\xfeh\xfe\xee\x92\xfe\xefk\x81\x134&&\x1a\x01\xc0\x1a&\x13\x89G\xb4a\x86\xe8F\v*\b\x16\xc0\r\x13\x19&\x1a\xfe@\x1a&\x13\x8a\x94Ɇ\xe8F\v*\b\x16\xc7\r\x13A\x01\x9a\x01\x13\x92\x01\x14k\x82\x134&\x01\xe0\x05\x02\xfe\xf4\xfe\xb3nf\x81\x13&\x1a\x01\xc0\x1a&&4\x13\x89BH\x82r\x11d\x17\x13\x03\x13\xfe@\x1a&&4\x13\x8a\x89\x82r\x11d\x17\x13\r\a\x01\f\x01Moe\x81\x13&\x00\x00\x00\x00\b\x00\x00\x00\x00\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00o\x00\u007f\x00\x00\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x165\x15\x14\x06+\x01\"&=\x0146;\x012\x165\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15\x14\x06#!\"&=\x01463!2\x165\x15\x14\x06#!\"&=\x01463!2\x165\x15\x14\x06#!\"&=\x01463!2\x16\x13\x114&#!\"\x06\x15\x11\x14\x163!26\x13\x11\x14\x06#!\"&5\x11463!2\x16\x01\x80\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x04\x80\x13\r\xfc@\r\x13\x13\r\x03\xc0\r\x13\x13\r\xfc@\r\x13\x13\r\x03\xc0\r\x13\x13\r\xfc@\r\x13\x13\r\x03\xc0\r\x13\x80\x13\r\xfa@\r\x13\x13\r\x05\xc0\r\x13\x80^B\xfa@B^^B\x05\xc0B^\x01`@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xfd\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xfd3\x03@\r\x13\x13\r\xfc\xc0\r\x13\x13\x04M\xfb\xc0B^^B\x04@B^^\x00\x02\x00\x00\x00\x00\x04\x80\x05\x80\x00\a\x00\x1f\x00\x00\x01!54&\"\x06\x15\x01\x11\x14\x06#!\"&5\x1146;\x0154\x00 \x00\x1d\x0132\x16\x01@\x02\x00\x96Ԗ\x03@8(\xfc@(88( \x01\b\x01p\x01\b (8\x03\x00\xc0j\x96\x96j\xfe\xe0\xfd\xc0(88(\x02@(8\xc0\xb8\x01\b\xfe\xf8\xb8\xc08\x00\x00\x02\x00@\xff\x80\a\x00\x05\x80\x00\x11\x007\x00\x00\x01\x14\a\x11\x14\x06+\x01\"&5\x11&5462\x16\x05\x11\x14\x06\a\x06#\".\x02#\"\x05\x06#\"&5\x114767632\x16\x17\x1632>\x0232\x16\x01@@\x13\r@\r\x13@KjK\x05\xc0\x19\x1bך=}\\\x8bI\xc0\xfe\xf0\x11\x10\x1a&\x1f\x15:\xec\xb9k\xba~&26\u007f]S\r\x1a&\x05\x00H&\xfb\x0e\r\x13\x13\r\x04\xf2&H5KKu\xfd\x05\x19\x1b\x0et,4,\x92\t&\x1a\x02\xe6 \x17\x0e\x1dx:;\x13*4*&\x00\x00\x00\x01\x00\x00\x00\x00\x06\x80\x05\x80\x00K\x00\x00\x01\x14\x0f\x02\x0e\x01#\x15\x14\x06+\x01\"&5\x1146;\x012\x16\x1d\x012\x16\x177654\x02$ \x04\x02\x15\x14\x1f\x01>\x013546;\x012\x16\x15\x11\x14\x06+\x01\"&=\x01\"&/\x02&54\x126$ \x04\x16\x12\x06\x80<\x14\xb9\x16\x89X\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12Gv\"D\x1d\xb0\xfe\xd7\xfe\xb2\xfeװ\x1dD\"vG\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12X\x89\x16\xb9\x14<\x86\xe0\x014\x01L\x014\xe0\x86\x02\x8a\xa6\x941!Sk \x0e\x12\x12\x0e\x02@\x0e\x12\x12\x0e G<\f_b\x94\x01\x06\x9c\x9c\xfe\xfa\x94b_\f\x034.\x0354632\x17\x16\x03\x00&4\x13\xfe\xb3\xfe\xfa\x1a&&\x1a\x01\x06\x01M\x134&\x01\x80UF\n\x0f\x1a&\x18\"\"\x18\x18\"\"\x18&\x1a\x0f\nF\x04\xa0\xfb\xc0\x1a&\x13\x01M&\x1a\x01\x80\x1a&\x01M\x13&\xfe\x12\x98\x83\x1c\x05%\x1b\x15\x1d\x15\x19/B/\x19\x15\x1d\x15\x1b%\x05\x1b\x00\x00\x00\x00\x04\x00\x00\xff\xb9\x06\x80\x05G\x00\x13\x00-\x00I\x00k\x00\x00\x01\x11\x14\x06\"'\x01!\"&5\x11463!\x0162\x16\x00\x14\x06\a\x06#\"&54>\x034.\x0354632\x17\x16\x04\x10\x02\a\x06#\"&54767>\x014&'&'&54632\x17\x16\x04\x10\x02\a\x06#\"&547>\x017676\x12\x10\x02'&'.\x01'&54632\x17\x16\x03\x00&4\x13\xfe\xb3\xfe\xfa\x1a&&\x1a\x01\x06\x01M\x134&\x01\x80UF\n\x0f\x1a&\x18\"\"\x18\x18\"\"\x18&\x1a\x0f\nF\x01U\xaa\x8c\r\f\x1b&'8\x14JSSJ\x148'&\x1a\r\r\x8c\x01\xaa\xfe\xd3\r\r\x1a&'\a\x1f\a.${\x8a\x8a{$.\a\x1f\a'&\x1a\r\r\xd3\x04\xa0\xfb\xc0\x1a&\x13\x01M&\x1a\x01\x80\x1a&\x01M\x13&\xfe\x12\x98\x83\x1c\x05%\x1b\x15\x1d\x15\x19/B/\x19\x15\x1d\x15\x1b%\x05\x1b7\xfe\xce\xfe\xfd;\x05&\x1a'\x14\x1d\x0f6\xa3\xb8\xa36\x0f\x1d\x14'\x1a&\x05;\xb6\xfe4\xfe\u007f[\x05&\x1a$\x17\x04\r\x04\x19\x1a[\x01\x10\x012\x01\x10[\x1a\x19\x04\r\x04\x17$\x1a&\x05[\x00\f\x00\x00\x00\x00\x05\x80\x05\x80\x00\x03\x00\a\x00\v\x00\x0f\x00\x13\x00\x17\x00\x1b\x00\x1f\x00#\x00/\x003\x007\x00\x00\x01\x15#5\x13\x15#5!\x15#5\x01!\x11!\x11!\x11!\x01!\x11!\x01\x11!\x11\x01\x15#5!\x15#5\x13\x11!5#\x11#\x11!\x1535\x01\x11!\x11!\x11!\x11\x01\x80\x80\x80\x80\x03\x80\x80\xfc\x80\x01\x80\xfe\x80\x01\x80\xfe\x80\x03\x00\x01\x80\xfe\x80\xff\x00\xfd\x80\x04\x80\x80\x01\x80\x80\x80\xfe\x80\x80\x80\x01\x80\x80\xfd\x80\xfd\x80\x05\x80\xfd\x80\x01\x80\x80\x80\x03\x00\x80\x80\x80\x80\xfc\x01\x01\u007f\x01\x80\x01\x80\xfe\x80\x01\x80\xfd\x80\xfd\x80\x02\x80\xfe\x00\x80\x80\x80\x80\x02\x00\xfe\x80\x80\xfe\x80\x02\x80\x80\x80\x03\x00\xfd\x80\x02\x80\xfd\x80\x02\x80\x00\x00\x00\x00\x10\x00\x00\x00\x00\a\x00\x05\x80\x00\x03\x00\a\x00\v\x00\x0f\x00\x13\x00\x17\x00\x1b\x00\x1f\x00#\x00'\x00+\x00/\x003\x007\x00;\x00?\x00\x003#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113\x13#\x113???? ^\x1f\x1f\x9d\x1f\x1f\x9d>>~\x1f\x1f?\x1f\x1f?\x1f\x1f\x9d??\x9d??~??~??^??\xbd^^? ^??\x05\x80\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x81\x05\u007f\xfa\x80\x05\x80\x00\x00\x00\x02\x00\x00\xff\x95\x05\xeb\x05\x80\x00\a\x00\x1d\x00\x00\x004&\"\x06\x14\x162\x01\x14\a\x01\x06#\"'\x01.\x015\x11463!2\x16\x17\x01\x16\x01\xc0KjKKj\x04v%\xfe\x15'45%\xfd5&5L4\x01\xa05\x80&\x02\xcb%\x04\vjKKjK\xfe@5%\xfe\x14%%\x02\xcc%\x805\x01\xa04L5&\xfd6'\x00\x00\x00\x00\x03\x00\x00\xff\x95\ak\x05\x80\x00\a\x00\x1d\x005\x00\x00\x004&\"\x06\x14\x162\x01\x14\a\x01\x06#\"'\x01.\x015\x11463!2\x16\x17\x01\x16\x05\x14\a\x01\x06#\"&'\x01654'\x01.\x01#32\x16\x17\x01\x16\x01\xc0KjKKj\x04v%\xfe\x15'45%\xfd5&5L4\x01\xa05\x80&\x02\xcb%\x01\x80%\xfe\x15'4$.\x1e\x01\xd6%%\xfd5&\x805\xe05\x80&\x02\xcb%\x04\vjKKjK\xfe@5%\xfe\x14%%\x02\xcc%\x805\x01\xa04L5&\xfd6'45%\xfe\x14%\x1c\x1f\x01\xd6%54'\x02\xca&55&\xfd6'\x00\x03\x00\n\xff\x80\x06y\x05\x80\x00T\x00d\x00t\x00\x00\x01\x16\a\x01\x0e\x01#!\"&'&74676&7>\x027>\x0176&7>\x017>\x0176&7>\x017>\x0176&7>\x027>\x06\x17\a63!2\x16\a\x01\x0e\x01#!\"\a\x06\x17\x163!267\x016'\x16\x05\x06\x163!26?\x016&#!\"\x06\a\x03\x06\x163!26?\x016&#!\"\x06\a\x06g(\x16\xfe\xed\x13sA\xfceM\x8f\x1c\x18\x16\x06\x01\x01\b\x01\x02\f\x15\x06\x17,\b\x03\x05\x02\x03\x1c\x03\x15*\x04\x01\a\x04\x04$\x04\x13/\x04\x01\b\x02\x02\x0e\x16\x06\b\x11\r\x13\x14!'\x1c\x01&\r\x02\xf9JP\x16\xfe\xee$G]\xfc\x9b\x1b\v\v\n\x18x\x03\x9b\x1d6\b\x01,\a\x02&\xfb\xed\x04\f\x0e\x02`\r\x19\x04\x15\x04\f\x0e\xfd\xa0\r\x19\x04h\x04\f\x0e\x02`\r\x19\x04\x15\x04\f\x0e\xfd\xa0\r\x19\x04\x04\"9H\xfcv@WkNC<\x04.\x0e\b\x1b\x06\v\x14\x1b\n&k&\n(\b\v\"\x06$p\"\t.\x05\r#\x05\x1au&\b#\t\b\x14\x1a\b\f%!'\x19\x16\x01\x06\x03\tpJ\xfcvwE\x0f\x10\x1bF\x1f\x1a\x03\xdb\x16#\x0f\x1e\r\x13\x13\r@\r\x13\x13\r\xfe\xc0\r\x13\x13\r@\r\x13\x13\r\x00\x00\x01\x00\x00\xff\x97\x05\x00\x05\x80\x00\x1c\x00\x00\x012\x17\x1e\x01\x15\x11\x14\x06\a\x06#\"'\t\x01\x06#\"'.\x015\x1146763\x04\x8c\x17\x15!''!\x13\x190#\xfeG\xfeG$/\x17\x15!''!\x15\x17\x05\x80\t\r8\"\xfa\xf7\"8\r\b \x01\xa8\xfeX!\t\r8\"\x05\t\"8\r\t\x00\x00\x00\x00\x04\x00\x00\xff\x80\x06\x80\x05\x80\x00\x03\x00\f\x00\x14\x00<\x00\x00)\x01\x11!\x11!\x11#\"&=\x01!\x004&\"\x06\x14\x1627\x11\x14\x06+\x01\x15\x14\x06#!\"&=\x01#\"&5\x1146;\x01\x11463!2\x16\x1f\x01\x1e\x01\x15\x1132\x16\x01\x80\x03\x80\xfc\x80\x03\x80\xa0(8\xfd\x80\x04\x80&4&&4\xa6\x13\r\xe08(\xfc@(8\xe0\r\x13qO@8(\x02\xa0(`\x1c\x98\x1c(@Oq\x01\x00\x01\x80\x01\x808(\xa0\xfd&4&&4&@\xfe`\r\x13\xa0(88(\xa0\x13\r\x01\xa0Oq\x02 (8(\x1c\x98\x1c`(\xff\x00q\x00\x03\x00\x00\xff\x80\a\x80\x06\x00\x00\a\x00!\x00)\x00\x00\x002\x16\x14\x06\"&4\x012\x16\x15\x11\x14\x06#!\"&5\x1146;\x017>\x013!2\x16\x1f\x01\x00 \x00\x10\x00 \x00\x10\x03I\uea69\xee\xa9\x03\xe0j\x96\x96j\xfa\x80j\x96\x96j\xe03\x13e5\x02\x005e\x133\xfdg\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\x03`\xa9\uea69\xee\x02I\x96j\xfc\x80j\x96\x96j\x03\x80j\x96\x881GG1\x88\xfb\x80\x01\a\x01r\x01\a\xfe\xf9\xfe\x8e\x00\x00\x00\x00\x02\x00\x00\xff\x80\x06\x80\x05\x80\x00\a\x00P\x00\x00\x01\x032\x16327&\x017>\x047\x13\x01;\x01\x16\x17\x13\x16\x12\x17\x1e\x01\x17\x16\x17\x1e\x01\x17\x16\x15\x14\x06\x15\"&#\"\x04\a4?\x012>\x0554.\x01'%\x06\x02\x15\x14\x1e\x033\x16\x15\x14\a\"&#\"\x06#\x06\x02ժ!\xcf9\x13&W\xfc\xca\x02\x17B03&\f\xed\x01\x18K5\b\x03\xcd!\x92)\x0fV\x1d\x14\x0f\x13\x8a\x0f\x06\x01?\xfe@L\xfe\xea'\x04\x83\x01\x17\b\x15\t\r\x05>R\x01\xfe>\x1ae\x1c;&L\x03\x01\x02:\xe9:\b%\x03P\x03\xd1\xfe>\x04\x02\xfd\xfcvO\a\v\n\x13'\x1f\x02h\x02\xd4\x0e\a\xfe N\xfe\x99_\"\xdd:-\f\x0f\x1d\x06&\x13\x05\x11\x04\x10\x0e\x01+#\x1c\x05\x02\a\x06\n\f\b\x10\xa1\xc2\x03\x02:\xfe\xed\x19\x16\x1f\x12\t\b\x13'\t\x12\x14\b\x0e\x00\x00\x03\x00\x00\xff\x80\x05\x80\x05\x80\x00\x15\x00+\x00a\x00\x00%\x163 \x114'.\x04#\"\a\x14\x06\x15\x14\x06\x1e\x01\x03\x1632>\x0254.\x02#\"\a\x14\x16\x15\x14\x06\x15\x14\x017>\x017>\x04<\x015\x10'.\x04/\x016$32\x1632\x1e\x03\x15\x14\x0e\x03\a\x1e\x01\x15\x14\x0e\x03#\"&#\"\x04\x02+JB\x01x)\x1bEB_I:I\x1c\x01\x02\x01\b\x06*CRzb3:dtB2P\b\x01\xfd\xe4\x02\x0f\x8c$\a\v\x06\x05\x01\x16\x04$5.3\x05\x04b\x01\xe4\x83\x17Z\x17F\x85|\\8!-T>5\x9a\xcdFu\x9f\xa8\\,\xb0,j\xfen\x0f \x01OrB,\x027676\x1a\x01'5.\x02'7\x1e\x0232>\x017\x06\a\x0e\x01\a\x0e\x03\a\x06\x02\a\x0e\x03\x1f\x01\x16\x17\x06\a\"\x06#\"&#&#\"\x06\x11\x16OA\x1b\x1c\r\x01zj\x01\x18=N\x13\x13!\xae}:0e\x8d\x1c\x05\x0e\x1e\x8f%\b\f\x06\t\x02\x1by\x11\x02\x16\x12\x0e\x01\x01\x11\xa8\x03\r\v+\v\x1dt\x1c\x8aD3\xb8~U\a\x13\x13\x0e#B\a\x024\x02\v#\x19\r\v\x05\x03g\x02\t\x05\x05\t\x02'2\n%\x0f\x13/!:\r\x94\xfd\xe1T\tbRU\x0f\x12\x04\x1b,7\x03\x14\x02\x12\x00\x00\x00\x00\x02\x00\x00\xff\x80\x06\xfa\x05\x80\x00\x1b\x00}\x00\x00%2\x16\x0f\x01\x06\"/\x01&6;\x01\x11#\"&?\x0162\x1f\x01\x16\x06+\x01\x11\x01\x17\x1632632\x163!2\x16>\x02?\x012\x163\x16\x15\x14\a\x06\a&'.\x02'.\x03\x06#\"&\"\x06\a\x06\x17\x14\x12\x15\x14\x06\x16\x17\x1e\x01\x17\x16\x15\x14\x0f\x01\x06$#\"\x06#&=\x01>\x0276\x114\x02=\x01464.\x01'&#\"\x06\a\x0e\x02\a&'\x11\x06\xd0!\x12\x14~\x14:\x14~\x14\x12!PP!\x12\x14~\x14:\x14~\x14\x12!P\xf9\xd16\f\xc7,\xb0,$\x8f$\x01%\x06\x1e\v\x15\x0e\b*\x04\x14\x04\x02\x05'\x1d\x19\x1d\x03\x10\r\x01\x06\f\x13\a\x1d\x02\x11c2N \t\x01\x04\x05\x05\n(\xa8$\x05\x03\"L\xfe\xe4A2\xca3\x03\x11Yl\x18\x13\x06\x01\x02\x04\x03\v\x97!x\x14\x13\x1e!\x1a*\x0e\x80%\x1a\xa2\x1a\x1a\xa2\x1a%\x04\x00%\x1a\xa2\x1a\x1a\xa2\x1a%\xfc\x00\x04\xff\x1b\x05\x04\x01\x01\x01\x05\r\v\x01\x01p\xe0P\x1d\x0e\x04,T\tNE\x01\b\t\x03\x02\x01\x01\x04\x04Q7^\xfd\xb4\xa1\x10oH!\x15+\x10(\n\x0e\x0f\x01\x02\x14\x123\x01\t\x1b \x1a\x0e*\x01Ue\x01\x94eu\x02\x1b\x17\x1c\x14\x04\f\x18\x0e\rwg\x02\x1a\x12\x01\u007f\x00\x00\x02\x00\x00\xff\x03\x06\x00\x05\x80\x00a\x00\x95\x00\x00\x13\x17\x1632632$\x04\x17\x16?\x012\x163\x16\x15\x14\a\x06\a&'.\x025&'&#\"&\"\x06\a\x06\x1f\x015\x14\x1e\x01\x15\x14\x06\x16\x17\x1e\x01\x17\x16\x15\x14\x0f\x01\x06$#\"\x06#&=\x01>\x027>\x024&54&54>\x01.\x01'&#\"\x06\a\x0e\x02\a&'\x11\x012\x1e\x02\x17\x16\x14\a\x0e\x03#\".\x01465!\x14\x16\x14\x0e\x01#\".\x02'&47>\x0332\x1e\x01\x14\x06\x15!4&4>\x01Q6\f\xc7,\xb0,F\x01a\x01\x00w!\x17*\x04\x14\x04\x02\x05'\x1d\x19\x1d\x03\x10\x0e\n\x11\x05=\x1e~Pl*\t\x01\x01\x02\x01\x05\x05\n(\xa8$\x05\x03\"L\xfe\xe4A2\xca3\x03\x11Yl\x18\a\t\x03\x01\x05\x01\x01\x01\x05\x04\v\x97)\xf4\x10\x13\x1e!\x1a*\x0e\x05\x1e\f<7@\x04\x1a\x1a\x04@7<\f\r\x0f\x05\x03\xfc\x00\x03\x05\x0f\r\f<7@\x04\x1a\x1a\x04@7<\f\r\x0f\x05\x03\x04\x00\x03\x05\x0f\x05\u007f\x1b\x05\x04\x02\x01\x04\x01 \x01\x01p\xe0P\x1d\x0e\x04,T\tMF\x01\r\x06\x02\x02\x04\x05Q7\x9847ƢH\x10oH!\x15+\x10(\n\x0e\x0f\x01\x02\x14\x123\x01\t\x1b \x1a\x0e\x10t\xaf\x87\xac\x03\a\x1d\b\aJHQ6\x05\f\x1b\v\fwh\x02\x1a\x12\x01\u007f\xfa\xff',6\x03\x158\x15\x036,'\x15$\x1f#\x02\x02#\x1f$\x15',6\x03\x158\x15\x036,'\x15$\x1f#\x02\x02#\x1f$\x15\x00\x00\x04\x00\x00\x00\x00\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00\x00%\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\a\x00&\x1a\xf9\x80\x1a&&\x1a\x06\x80\x1a&\xfe\x80&\x1a\xfb\x00\x1a&&\x1a\x05\x00\x1a&\x01\x00&\x1a\xfa\x00\x1a&&\x1a\x06\x00\x1a&\xfe\x80&\x1a\xfb\x80\x1a&&\x1a\x04\x80\x1a&\xc0\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x00\x00\x04\x00\x00\x00\x00\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00\x00%\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\a\x00&\x1a\xf9\x80\x1a&&\x1a\x06\x80\x1a&\xfe\x80&\x1a\xfc\x80\x1a&&\x1a\x03\x80\x1a&\x01\x00&\x1a\xfa\x80\x1a&&\x1a\x05\x80\x1a&\xfe\x80&\x1a\xfd\x80\x1a&&\x1a\x02\x80\x1a&\xc0\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x00\x00\x04\x00\x00\x00\x00\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00\x00%\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\a\x00&\x1a\xf9\x80\x1a&&\x1a\x06\x80\x1a&&\x1a\xfb\x00\x1a&&\x1a\x05\x00\x1a&&\x1a\xfa\x00\x1a&&\x1a\x06\x00\x1a&&\x1a\xfb\x80\x1a&&\x1a\x04\x80\x1a&\xc0\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x00\x00\x00\x00\x04\x00\x00\x00\x00\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00\x00%\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\a\x00&\x1a\xf9\x80\x1a&&\x1a\x06\x80\x1a&&\x1a\xf9\x80\x1a&&\x1a\x06\x80\x1a&&\x1a\xf9\x80\x1a&&\x1a\x06\x80\x1a&&\x1a\xf9\x80\x1a&&\x1a\x06\x80\x1a&\xc0\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x01f\x80\x1a&&\x1a\x80\x1a&&\x00\x00\x00\x00\b\x00\x00\x00\x00\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00o\x00\u007f\x00\x00%\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x11\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x11\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x01\x00\x13\r\xc0\r\x13\x13\r\xc0\r\x13\x13\r\xc0\r\x13\x13\r\xc0\r\x13\x13\r\xc0\r\x13\x13\r\xc0\r\x13\x06\x00\x13\r\xfa\xc0\r\x13\x13\r\x05@\r\x13\xfa\x00\x13\r\xc0\r\x13\x13\r\xc0\r\x13\x06\x00\x13\r\xfa\xc0\r\x13\x13\r\x05@\r\x13\x13\r\xfa\xc0\r\x13\x13\r\x05@\r\x13\x13\r\xfa\xc0\r\x13\x13\r\x05@\r\x13\xe0\xc0\r\x13\x13\r\xc0\r\x13\x13\x01s\xc0\r\x13\x13\r\xc0\r\x13\x13\x01s\xc0\r\x13\x13\r\xc0\r\x13\x13\xfc\xf3\xc0\r\x13\x13\r\xc0\r\x13\x13\x04s\xc0\r\x13\x13\r\xc0\r\x13\x13\xfc\xf3\xc0\r\x13\x13\r\xc0\r\x13\x13\x01s\xc0\r\x13\x13\r\xc0\r\x13\x13\x01s\xc0\r\x13\x13\r\xc0\r\x13\x13\x00\x00\x05\x00\x00\x00\x00\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00O\x00\x00\x01\x11\x14\x06#\"'\x01&47\x01632\x16\x01\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x01\x80\x13\r\x0e\t\xfe\xe0\t\t\x01 \t\x0e\r\x13\x05\x80\x13\r\xf9@\r\x13\x13\r\x06\xc0\r\x13\x13\r\xfb\xc0\r\x13\x13\r\x04@\r\x13\x13\r\xfb\xc0\r\x13\x13\r\x04@\r\x13\x13\r\xf9@\r\x13\x13\r\x06\xc0\r\x13\x03\xe0\xfd\xc0\r\x13\t\x01 \t\x1c\t\x01 \t\x13\xfc\xf3\xc0\r\x13\x13\r\xc0\r\x13\x13\x01s\xc0\r\x13\x13\r\xc0\r\x13\x13\x01s\xc0\r\x13\x13\r\xc0\r\x13\x13\x01s\xc0\r\x13\x13\r\xc0\r\x13\x13\x00\x05\x00\x00\x00\x00\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00O\x00\x00\x00\x14\a\x01\x06#\"&5\x114632\x17\t\x01\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x01`\t\xfe\xe0\t\x0e\r\x13\x13\r\x0e\t\x01 \x05\xa9\x13\r\xf9@\r\x13\x13\r\x06\xc0\r\x13\x13\r\xfb\xc0\r\x13\x13\r\x04@\r\x13\x13\r\xfb\xc0\r\x13\x13\r\x04@\r\x13\x13\r\xf9@\r\x13\x13\r\x06\xc0\r\x13\x02\xce\x1c\t\xfe\xe0\t\x13\r\x02@\r\x13\t\xfe\xe0\xfe\t\xc0\r\x13\x13\r\xc0\r\x13\x13\x01s\xc0\r\x13\x13\r\xc0\r\x13\x13\x01s\xc0\r\x13\x13\r\xc0\r\x13\x13\x01s\xc0\r\x13\x13\r\xc0\r\x13\x13\x00\x00\x01\x00\x00\x00\x00\a\x00\x05\x00\x00\x1f\x00\x00\x01\x11\x14\a\x06#\"'\x01\x15\x14\x06#!\"&5\x11463!2\x16\x1d\x01\x01632\x17\x16\a\x00'\r\f\x1b\x12\xfem\xa9w\xfd@w\xa9\xa9w\x02\xc0w\xa9\x01\x93\x12\x1b\f\r'\x04\xa0\xfb\xc0*\x11\x05\x13\x01\x93\xa6w\xa9\xa9w\x02\xc0w\xa9\xa9w\xa5\x01\x92\x13\x05\x11\x00\x00\x00\x00\x04\x00\x00\xff\x80\a\x80\x05\x80\x00\a\x00\x0e\x00\x1e\x00.\x00\x00\x00\x14\x06\"&462\x01\x11!5\x01\x17\t\x01!\"\x06\x15\x11\x14\x163!265\x114&\x17\x11\x14\x06#!\"&5\x11463!2\x16\x02\x80p\xa0pp\xa0\x04p\xfa\x80\x01@\xa0\x02\x00\x02\x00\xf9\xc0\r\x13\x13\r\x06@\r\x13\x13\x93^B\xf9\xc0B^^B\x06@B^\x04\x10\xa0pp\xa0p\xfd\xc0\xfe@\xc0\x01@\xa0\x02\x00\x01 \x13\r\xfb@\r\x13\x13\r\x04\xc0\r\x13 \xfb@B^^B\x04\xc0B^^\x00\x04\x00\x00\xff\x80\x05\xeb\x05k\x00\x06\x00\x14\x00\x19\x00%\x00\x00!7'\a\x153\x15\x014#\"\a\x01\x06\x15\x14327\x016'\t\x01!\x11\x01\x14\x0f\x01\x017632\x1f\x01\x16\x01k[\xeb[\x80\x02v\x16\n\a\xfd\xe2\a\x16\n\a\x02\x1e\a6\x01\xa0\xfc\xc0\xfe`\x05\xeb%\xa6\xfe`\xa6$65&\xeb%[\xeb[k\x80\x03\xa0\x16\a\xfd\xe2\a\n\x16\a\x02\x1e\a\xca\xfe`\xfc\xc0\x01\xa0\x02\xe05%\xa6\x01\xa0\xa5&&\xea'\x00\x00\x02\x00\x00\xff\x80\x04\x00\x05\x80\x00\a\x00\x17\x00\x00\x004&\"\x06\x14\x162\x01\x14\a\x01\x0e\x01\"&'\x01&54\x00 \x00\x03\x00\x96Ԗ\x96\xd4\x01\x96!\xfe\x94\x10?H?\x0f\xfe\x93!\x01,\x01\xa8\x01,\x03\x16Ԗ\x96Ԗ\x01\x00mF\xfc\xfa!&&!\x03\x06Fm\xd4\x01,\xfe\xd4\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\a\x00\x13\x00\x00%\x11\"\x0e\x01\x10\x1e\x01\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x03\x00\x94\xfa\x92\x92\xfa\x03\x94\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a`\x04@\x92\xfa\xfe\xd8\xfa\x92\x02\xf1\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x00\x02\x00\x00\x00\x00\x04\x00\x05\xc0\x00\x15\x00-\x00\x00\x014'.\x03'&\"\a\x0e\x03\a\x06\x15\x14\x1626%\x14\x00 \x00547>\x037>\x012\x16\x17\x1e\x03\x17\x16\x02\x00\x14\x01\x1d\x16\x1c\a\x04\"\x04\a\x1c\x16\x1d\x01\x14KjK\x02\x00\xfe\xd4\xfeX\xfe\xd4Q\x06qYn\x1c\t243\b\x1cnYq\x06Q\x01\x80$!\x01+!7\x17\x10\x10\x177!+\x01!$5KK\xb5\xd4\xfe\xd4\x01,ԑ\x82\t\xa3\x8b\xd9]\x1e\"\"\x1e]ً\xa3\t\u007f\x00\x05\x00\x00\x00\x00\x06\xf8\x05\x80\x00\x06\x00\x0e\x009\x00>\x00H\x00\x00\x017'\a\x153\x15\x00&\a\x01\x06\x167\x01\x13\x15\x14\x06#!\"&5\x11463!2\x17\x16\x17\x16\x0f\x01\x06'&#!\"\x06\x15\x11\x14\x163!26=\x014?\x016\x16\x03\t\x01!\x11\x01\a\x01762\x1f\x01\x16\x14\x03xt\x98t`\x02\x00 \x11\xfe\xa2\x11 \x11\x01^Q\xa9w\xfc\xc0w\xa9\xa9w\x03@?6\x0f\x03\x03\f1\x0e\x12\x17\x16\xfc\xc0B^^B\x03@B^\t@\x0f(`\x01 \xfd`\xfe\xe0\x04\\\\\xfe\xe0\\\x1cP\x1c\x98\x1c\x01`t\x98t8`\x02\xc0 \x11\xfe\xa2\x11 \x11\x01^\xfdϾw\xa9\xa9w\x03@w\xa9\x19\a\x10\x11\f1\x0e\x06\x06^B\xfc\xc0B^^B~\r\t@\x0f\x10\x02\xcd\xfe\xe0\xfd`\x01 \x02\x1c\\\x01 \\\x1c\x1c\x98\x1cP\x00\x00\x00\x00\x02\x00\x00\x00\x00\x06\x80\x06\x00\x00+\x00Z\x00\x00\x01\x11\x14\x06#!\"&5\x11463!12\x16\x15\x14\a\x06\a\x06+\x01\"\x06\x15\x11\x14\x163!26=\x0147676\x17\x16\x13\x01\x06#\"'&=\x01# \a\x06\x13\x16\a\x06#\"'.\x0454>\a;\x01547632\x17\x01\x16\x14\x05\x80\xa9w\xfc\xc0w\xa9\xa9w\x00\xff\r\x13\x1aM8\n\x06pB^^B\x03@B^\x12\x1c\x1a\x10\x13\x15\xed\xfe\x80\x12\x1b\f\r'\xa0\xfe\xbdsw-\x03\x17\b\x04\x10\n\n\x169*#\a\x15#;No\x8a\xb5j\xa0'\r\f\x1a\x13\x01\x80\x13\x02#\xfe\xfdw\xa9\xa9w\x03@w\xa9\x13\r\x1b\x05\x1a\"\x04^B\xfc\xc0B^^B\xd6\x13\n\r\x18\x10\b\t\x01\xdc\xfe\x80\x13\x05\x11*\xc0\x83\x89\xfe\xb0\x17\v\x02\r\x0e\"g`\x8481T`PSA:'\x16\xc0*\x11\x05\x13\xfe\x80\x134\x00\x00\x02\x00\x00\x00\x00\x06\u007f\x05\x80\x00/\x00D\x00\x00\x01\x11\x14\x06#!\"&5\x11463!2\x17\x16\x17\x16\x0f\x01\x06#\"'&#!\"\x06\x15\x11\x14\x163!26=\x014?\x01632\x17\x16\x13\x01\x06\"'\x01&4?\x0162\x17\t\x0162\x1f\x01\x16\x14\x05\x80\xa9w\xfc\xc0w\xa9\xa9w\x03@?6\x0f\x03\x03\f1\n\r\x03\x06\x17\x16\xfc\xc0B^^B\x03@B^\t@\n\r\x06\x06\x14\xe7\xfc\xd2\x18B\x18\xfeR\x18\x18n\x18B\x18\x01\a\x02\x87\x18B\x18n\x18\x02^\xfe\xc2w\xa9\xa9w\x03@w\xa9\x19\a\x10\x11\f1\n\x02\x06^B\xfc\xc0B^^B\xfe\r\t@\n\x03\b\x01\xd4\xfc\xd2\x18\x18\x01\xae\x18B\x18n\x18\x18\xfe\xf9\x02\x87\x18\x18n\x18B\x00\x00\x00\x00\x01\x00\x00\xff\x00\a\x00\x06\x00\x00C\x00\x00\x00\x14\a\x01\x06\"&=\x01!\x1132\x16\x14\a\x01\x06\"'\x01&46;\x01\x11!\x15\x14\x06\"'\x01&47\x0162\x16\x1d\x01!\x11#\"&47\x0162\x17\x01\x16\x14\x06+\x01\x11!5462\x17\x01\a\x00\x13\xff\x00\x134&\xfe\x80\x80\x1a&\x13\xff\x00\x134\x13\xff\x00\x13&\x1a\x80\xfe\x80&4\x13\xff\x00\x13\x13\x01\x00\x134&\x01\x80\x80\x1a&\x13\x01\x00\x134\x13\x01\x00\x13&\x1a\x80\x01\x80&4\x13\x01\x00\x02\x9a4\x13\xff\x00\x13&\x1a\x80\xfe\x80&4\x13\xff\x00\x13\x13\x01\x00\x134&\x01\x80\x80\x1a&\x13\x01\x00\x134\x13\x01\x00\x13&\x1a\x80\x01\x80&4\x13\x01\x00\x13\x13\xff\x00\x134&\xfe\x80\x80\x1a&\x13\xff\x00\x00\x01\x00\x00\xff\x80\x04\x00\x05\x80\x00\x1d\x00\x00\x016\x16\x15\x11\x14\x06'\x01&'\x11\x14\x06+\x01\"&5\x1146;\x012\x16\x15\x1167\x03\xd3\x13\x1a\x1a\x13\xfd:\t\x04&\x1a\x80\x1a&&\x1a\x80\x1a&\x04\t\x05s\x13\f\x1a\xfa@\x1a\f\x13\x02\xc6\t\n\xfdZ\x1a&&\x1a\x05\x80\x1a&&\x1a\xfdZ\n\t\x00\x01\x00\x00\xff\x80\a\x00\x05\x80\x00+\x00\x00\x016\x16\x15\x11\x14\x06'\x01&'\x11\x14\x06'\x01&'\x11\x14\x06+\x01\"&5\x1146;\x012\x16\x15\x1167\x016\x16\x15\x1167\x06\xd3\x13\x1a\x1a\x13\xfd:\t\x04\x1a\x13\xfd:\t\x04&\x1a\x80\x1a&&\x1a\x80\x1a&\x04\t\x02\xc6\x13\x1a\x04\t\x05s\x13\f\x1a\xfa@\x1a\f\x13\x02\xc6\t\n\xfd:\x1a\f\x13\x02\xc6\t\n\xfdZ\x1a&&\x1a\x05\x80\x1a&&\x1a\xfdZ\n\t\x02\xc6\x13\f\x1a\xfd:\n\t\x00\x01\x00z\xff\x80\x06\x80\x05\x80\x00\x19\x00\x00\x016\x16\x15\x11\x14\x06'\x01&'\x11\x14\x06'\x01&47\x016\x16\x15\x1167\x06S\x13\x1a\x1a\x13\xfd:\t\x04\x1a\x13\xfd:\x13\x13\x02\xc6\x13\x1a\x04\t\x05s\x13\f\x1a\xfa@\x1a\f\x13\x02\xc6\t\n\xfd:\x1a\f\x13\x02\xc6\x134\x13\x02\xc6\x13\f\x1a\xfd:\n\t\x00\x00\x01\x00\x00\xff|\x05\u007f\x05\x84\x00\v\x00\x00\t\x01\x06&5\x1146\x17\x01\x16\x14\x05h\xfa\xd0\x17!!\x17\x050\x17\x02a\xfd\x1e\r\x14\x1a\x05\xc0\x1a\x14\r\xfd\x1e\r$\x00\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x1f\x00\x00\x01\x11\x14\x06#!\"&5\x11463!2\x16\x05\x11\x14\x06#!\"&5\x11463!2\x16\x06\x00&\x1a\xfe\x00\x1a&&\x1a\x02\x00\x1a&\xfc\x80&\x1a\xfe\x00\x1a&&\x1a\x02\x00\x1a&\x05@\xfa\x80\x1a&&\x1a\x05\x80\x1a&&\x1a\xfa\x80\x1a&&\x1a\x05\x80\x1a&&\x00\x00\x00\x00\x01\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x00\x01\x11\x14\x06#!\"&5\x11463!2\x16\x06\x00&\x1a\xfa\x80\x1a&&\x1a\x05\x80\x1a&\x05@\xfa\x80\x1a&&\x1a\x05\x80\x1a&&\x00\x00\x00\x00\x01\x00\x00\xff\x80\x06\x06\x05\x80\x00\x19\x00\x00\x17\x06&5\x1146\x17\x01\x16\x17\x1146\x17\x01\x16\x14\a\x01\x06&5\x11\x06\a-\x13\x1a\x1a\x13\x02\xc6\t\x04\x1a\x13\x02\xc6\x13\x13\xfd:\x13\x1a\x04\ts\x13\f\x1a\x05\xc0\x1a\f\x13\xfd:\t\n\x02\xc6\x1a\f\x13\xfd:\x134\x13\xfd:\x13\f\x1a\x02\xc6\n\t\x00\x00\x00\x00\x01\x00\x00\xff\x80\a\x00\x05\x80\x00+\x00\x00\x17\x06&5\x1146\x17\x01\x16\x17\x1146\x17\x01\x16\x17\x1146;\x012\x16\x15\x11\x14\x06+\x01\"&5\x11\x06\a\x01\x06&5\x11\x06\a-\x13\x1a\x1a\x13\x02\xc6\t\x04\x1a\x13\x02\xc6\t\x04&\x1a\x80\x1a&&\x1a\x80\x1a&\x04\t\xfd:\x13\x1a\x04\ts\x13\f\x1a\x05\xc0\x1a\f\x13\xfd:\t\n\x02\xc6\x1a\f\x13\xfd:\t\n\x02\xa6\x1a&&\x1a\xfa\x80\x1a&&\x1a\x02\xa6\n\t\xfd:\x13\f\x1a\x02\xc6\n\t\x00\x00\x00\x01\x00\x00\xff\x80\x04\x00\x05\x80\x00\x1d\x00\x00\x17\x06&5\x1146\x17\x01\x16\x17\x1146;\x012\x16\x15\x11\x14\x06+\x01\"&5\x11\x06\a-\x13\x1a\x1a\x13\x02\xc6\t\x04&\x1a\x80\x1a&&\x1a\x80\x1a&\x04\ts\x13\f\x1a\x05\xc0\x1a\f\x13\xfd:\t\n\x02\xa6\x1a&&\x1a\xfa\x80\x1a&&\x1a\x02\xa6\n\t\x00\x00\x00\x02\x00\x01\x00\x00\x06\x01\x05\x06\x00\v\x00\x1b\x00\x00\x13\x0162\x17\x01\x16\x06#!\"&\x01!\"&5\x11463!2\x16\x15\x11\x14\x06\x0e\x02\xc6\x134\x13\x02\xc6\x13\f\x1a\xfa@\x1a\f\x05\xc6\xfa\x80\x1a&&\x1a\x05\x80\x1a&&\x02-\x02\xc6\x13\x13\xfd:\x13\x1a\x1a\xfd\xe6&\x1a\x01\x00\x1a&&\x1a\xff\x00\x1a&\x00\x00\x00\x00\x01\x00\x9a\xff\x9a\x04\xa6\x05\xe6\x00\x14\x00\x00\t\x02\x16\x14\x0f\x01\x06\"'\x01&47\x0162\x1f\x01\x16\x14\x04\x93\xfd\xed\x02\x13\x13\x13\xa6\x134\x13\xfd\x1a\x13\x13\x02\xe6\x134\x13\xa6\x13\x04\xd3\xfd\xed\xfd\xed\x134\x13\xa6\x13\x13\x02\xe6\x134\x13\x02\xe6\x13\x13\xa6\x134\x00\x00\x00\x00\x01\x00Z\xff\x9a\x04f\x05\xe6\x00\x14\x00\x00\t\x01\x06\"/\x01&47\t\x01&4?\x0162\x17\x01\x16\x14\x04S\xfd\x1a\x134\x13\xa6\x13\x13\x02\x13\xfd\xed\x13\x13\xa6\x134\x13\x02\xe6\x13\x02\x93\xfd\x1a\x13\x13\xa6\x134\x13\x02\x13\x02\x13\x134\x13\xa6\x13\x13\xfd\x1a\x134\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00#\x00/\x00\x00\x0154&#!\x114&+\x01\"\x06\x15\x11!\"\x06\x1d\x01\x14\x163!\x11\x14\x16;\x01265\x11!26\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04\xc0&\x1a\xff\x00&\x1a\x80\x1a&\xff\x00\x1a&&\x1a\x01\x00&\x1a\x80\x1a&\x01\x00\x1a&\x01@\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02@\x80\x1a&\x01\x00\x1a&&\x1a\xff\x00&\x1a\x80\x1a&\xff\x00\x1a&&\x1a\x01\x00&\x01+\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x1b\x00\x00\x0154&#!\"\x06\x1d\x01\x14\x163!26\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04\xc0&\x1a\xfd\x00\x1a&&\x1a\x03\x00\x1a&\x01@\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02@\x80\x1a&&\x1a\x80\x1a&&\x01+\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00+\x007\x00\x00\x014/\x017654/\x01&#\"\x0f\x01'&#\"\x0f\x01\x06\x15\x14\x1f\x01\a\x06\x15\x14\x1f\x01\x1632?\x01\x17\x1632?\x016\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04}\x13\xb5\xb5\x13\x13Z\x13\x1b\x1a\x13\xb5\xb5\x13\x1a\x1b\x13Z\x13\x13\xb5\xb5\x13\x13Z\x13\x1b\x1a\x13\xb5\xb5\x13\x1a\x1b\x13Z\x13\x01\x83\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01\x9e\x1a\x13\xb5\xb5\x13\x1a\x1b\x13Z\x13\x13\xb5\xb5\x13\x13Z\x13\x1b\x1a\x13\xb5\xb5\x13\x1a\x1b\x13Z\x13\x13\xb5\xb5\x13\x13Z\x13\x01\xce\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x17\x00#\x00\x00\x014/\x01&\"\a\x01'&\"\x0f\x01\x06\x15\x14\x17\x01\x16327\x01>\x01\x10\x02\x04 $\x02\x10\x12$ \x04\x05\x04\x12[\x134\x13\xfeh\xe2\x134\x13[\x12\x12\x01j\x13\x1a\x1b\x13\x02\x1f\x12\xfc\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x03\"\x1c\x12Z\x13\x13\xfei\xe2\x13\x13Z\x12\x1c\x1b\x12\xfe\x96\x13\x13\x02\x1f\x12J\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00:\x00F\x00\x00%54&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x014.\x01#\"\a\x06\x1f\x01\x1632767632\x16\x15\x14\x06\a\x0e\x01\x1d\x01\x14\x16;\x01265467>\x04$\x10\x02\x04 $\x02\x10\x12$ \x04\x03\x80\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x01\x00o\xa6W\xf3\x80\x0f\x17\x84\a\f\x10\t5!\"40K(0?i\x12\x0e\xc0\x0e\x12+! \":\x1f\x19\x01\x80\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xa0\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x02\xaeX\x96R\xd5\x18\x12d\x06\fD\x18\x184!&.\x16\x1cuC$\x0e\x12\x12\x0e\x13=\x13\x12\x151/J=\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x1e\x00.\x00:\x00\x00%54&+\x01\x114&#!\"\x06\x1d\x01\x14\x16;\x01\x11#\"\x06\x1d\x01\x14\x163!26\x0354&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x04\x10\x02\x04 $\x02\x10\x12$ \x04\x04\x00\x12\x0e`\x12\x0e\xfe\xc0\x0e\x12\x12\x0e``\x0e\x12\x12\x0e\x01\xc0\x0e\x12\x80\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x02\x80\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xa0\xa0\x0e\x12\x02\x00\x0e\x12\x12\x0e\xa0\x0e\x12\xfe\xc0\x12\x0e\xa0\x0e\x12\x12\x03\x8e\xa0\x0e\x12\x12\x0e\xa0\x0e\x12\x12\xc1\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00/\x00_\x00\x00\x01#\"&=\x0146;\x01.\x01'\x15\x14\x06+\x01\"&=\x01\x0e\x01\a32\x16\x1d\x01\x14\x06+\x01\x1e\x01\x17546;\x012\x16\x1d\x01>\x01\x01\x15\x14\x06+\x01\x0e\x01\a\x15\x14\x06+\x01\"&=\x01.\x01'#\"&=\x0146;\x01>\x017546;\x012\x16\x1d\x01\x1e\x01\x1732\x16\x04\xadm\x1a&&\x1am \xa1l&\x1a\x80\x1a&l\xa1 m\x1a&&\x1am \xa1l&\x1a\x80\x1a&l\xa1\x01s&\x1a\x8f%\xeb\xa1&\x1a\x80\x1a&\xa1\xeb%\x8f\x1a&&\x1a\x8f%\xeb\xa1&\x1a\x80\x1a&\xa1\xeb%\x8f\x1a&\x02\x00&\x1a\x80\x1a&l\xa1 m\x1a&&\x1am \xa1l&\x1a\x80\x1a&l\xa1 m\x1a&&\x1am \xa1\x01,\x80\x1a&\xa1\xeb%\x8f\x1a&&\x1a\x8f%\xeb\xa1&\x1a\x80\x1a&\xa1\xeb%\x8f\x1a&&\x1a\x8f%\xeb\xa1&\x00\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00#\x00/\x00;\x00\x00\x01\a\x06\"/\x01\a\x06\"/\x01&4?\x01'&4?\x0162\x1f\x01762\x1f\x01\x16\x14\x0f\x01\x17\x16\x146\x10.\x01 \x0e\x01\x10\x1e\x01 6\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04I\x92\n\x1a\n\x89\x89\n\x1a\n\x92\n\n\x89\x89\n\n\x92\n\x1a\n\x89\x89\n\x1a\n\x92\n\n\x89\x89\n͒\xfa\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\x01r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01ɒ\n\n\x89\x89\n\n\x92\n\x1a\n\x89\x89\n\x1a\n\x92\n\n\x89\x89\n\n\x92\n\x1a\n\x89\x89\n\x1a\x19\x01(\xfa\x92\x92\xfa\xfe\xd8\xfa\x92\x92\x02_\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x14\x00 \x00,\x00\x00\t\x01\x06\"'\x01&4?\x0162\x1f\x01\x0162\x1f\x01\x16\x14\x16\x10.\x01 \x0e\x01\x10\x1e\x01 6\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04\x93\xfeZ\x134\x13\xfe\xda\x13\x13f\x134\x13\x93\x01\x13\x134\x13f\x13z\x92\xfa\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\x01r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02\xd3\xfeZ\x13\x13\x01&\x134\x13f\x13\x13\x93\x01\x13\x13\x13f\x134\xfa\x01(\xfa\x92\x92\xfa\xfe\xd8\xfa\x92\x92\x02_\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x85\x00\t\x00\x12\x00\"\x00\x00\x014'\x01\x1632>\x02\x05\x01&#\"\x0e\x01\x15\x14\x00\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x05 W\xfd\x0e\x89\xa0oɒV\xfc\x19\x02\U000c7954\xfa\x92\x05 z\xcd\xfe\xe3\xfe\xc8\xfe\xe3\xcdzz\xcd\x01\x1d\x018\x01\x1d\xcd\x02\x83\xa1\x86\xfd\x0fYW\x92˼\x02\xf2[\x92\xfc\x94\xa2\x01?\xfe\xc6\xfe\xe2\xcezz\xce\x01\x1e\x01:\x01\x1d\xcezz\xce\x00\x00\x01\x00@\xff5\x06\x00\x05K\x00 \x00\x00\x01\x15\x14\x06#!\x01\x16\x14\x0f\x01\x06#\"'\x01&547\x01632\x1f\x01\x16\x14\a\x01!2\x16\x06\x00A4\xfd@\x01%&&K%54'\xfdu%%\x02\x8b&54&K&&\xfe\xdb\x02\xc04A\x02\x80\x805K\xfe\xda$l$L%%\x02\x8c%54'\x02\x8a&&J&j&\xfe\xdbK\x00\x00\x01\x00\x00\xff5\x05\xc0\x05K\x00 \x00\x00\x01\x14\a\x01\x06#\"/\x01&47\x01!\"&=\x01463!\x01&4?\x01632\x17\x01\x16\x05\xc0%\xfdu'43'K&&\x01%\xfd@4AA4\x02\xc0\xfe\xdb&&K&45&\x02\x8b%\x02@6%\xfdu%%K&j&\x01%K5\x805K\x01&$l$K&&\xfdu#\x00\x00\x01\x005\xff\x80\x06K\x05@\x00!\x00\x00\x01\x14\x0f\x01\x06#\"'\x01\x11\x14\x06+\x01\"&5\x11\x01\x06\"/\x01&547\x01632\x17\x01\x16\x06K%K&56$\xfe\xdaK5\x805K\xfe\xda$l$K&&\x02\x8b#76%\x02\x8b%\x0253'K&&\x01%\xfd@4AA4\x02\xc0\xfe\xdb&&K&45&\x02\x8b%%\xfdu'\x00\x00\x00\x00\x01\x005\xff\xb5\x06K\x05\x80\x00\"\x00\x00\x01\x14\a\x01\x06#\"'\x01&54?\x01632\x17\x01\x1146;\x012\x16\x15\x11\x01632\x1f\x01\x16\x06K%\xfdu'45%\xfdu&&J'45%\x01&L4\x804L\x01&%54'K%\x02\xc05%\xfdt%%\x02\x8c$65&K%%\xfe\xda\x02\xc04LL4\xfd@\x01&%%K'\x00\x00\x01\x00\x00\xff\x80\a\x00\x05\xc0\x00,\x00\x00\x00\x14\a\x01\x06\"&5\x11#\"\x0e\x05\x15\x14\x17\x14\x16\x15\x14\x06#\"'.\x02'\x02547\x12!3\x11462\x17\x01\a\x00\x13\xfe\x00\x134&\xe0b\x9b\x99qb>#\x05\x05\x11\x0f\x10\f\a\f\x0f\x03\u007f5\xa2\x02\xc9\xe0&4\x13\x02\x00\x03\x9a4\x13\xfe\x00\x13&\x1a\x01\x00\f\x1f6Uu\xa0e7D\x06#\t\x0f\x14\x11\t\x1a\"\a\x01\x1d\xa6dž\x01\x93\x01\x00\x1a&\x13\xfe\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x17\x00/\x00\x00\x00\x14\a\x01\x17\x16\x14\x06#!\"&5\x11462\x1f\x01\x0162\x1f\x01\x01\x11\x14\x06\"/\x01\x01\x06\"/\x01&47\x01'&463!2\x16\x02\xf3\n\xfe\xb4\x90\x13&\x1a\xfe@\x1a&&4\x13\x90\x01L\n\x1a\nr\x03\x17&4\x13\x90\xfe\xb4\n\x1a\nr\n\n\x01L\x90\x13&\x1a\x01\xc0\x1a&\x01\xed\x1a\n\xfe\xb4\x90\x134&&\x1a\x01\xc0\x1a&\x13\x90\x01L\n\nr\x03I\xfe@\x1a&\x13\x90\xfe\xb4\n\nr\n\x1a\n\x01L\x90\x134&&\x00\x00\x00\x00\x02\x00\r\xff\x8d\x05\xf3\x05s\x00\x17\x00/\x00\x00\x01\x11\x14\x06\"/\x01\x01\x06\"/\x01&47\x01'&463!2\x16\x00\x14\a\x01\x17\x16\x14\x06#!\"&5\x11462\x1f\x01\x0162\x1f\x01\x03\x00&4\x13\x90\xfe\xb4\n\x1a\nr\n\n\x01L\x90\x13&\x1a\x01\xc0\x1a&\x02\xf3\n\xfe\xb4\x90\x13&\x1a\xfe@\x1a&&4\x13\x90\x01L\n\x1a\nr\x02@\xfe@\x1a&\x13\x90\xfe\xb4\n\nr\n\x1a\n\x01L\x90\x134&&\x02\x93\x1a\n\xfe\xb4\x90\x134&&\x1a\x01\xc0\x1a&\x13\x90\x01L\n\nr\x00\x00\x00\x00\x01\x00\x00\x00\x00\x05\x80\x05\x80\x00#\x00\x00\x01\x15\x14\x06#!\x11\x14\x06+\x01\"&5\x11!\"&=\x01463!\x1146;\x012\x16\x15\x11!2\x16\x05\x808(\xfe`8(\xc0(8\xfe`(88(\x01\xa08(\xc0(8\x01\xa0(8\x03 \xc0(8\xfe`(88(\x01\xa08(\xc0(8\x01\xa0(88(\xfe`8\x00\x00\x00\x00\x01\x00\x00\x02\x00\x05\x80\x03\x80\x00\x0f\x00\x00\x01\x15\x14\x06#!\"&=\x01463!2\x16\x05\x808(\xfb@(88(\x04\xc0(8\x03 \xc0(88(\xc0(88\x00\x00\x01\x00z\xff\x80\x06\x06\x05\x80\x005\x00\x00\x01\x1e\x01\x0f\x01\x0e\x01'%\x11\x14\x06+\x01\"&5\x11\x05\x06&/\x01&67-\x01.\x01?\x01>\x01\x17\x05\x1146;\x012\x16\x15\x11%6\x16\x1f\x01\x16\x06\a\x05\x05\xca.\x1b\x1a@\x1ag.\xfe\xf6L4\x804L\xfe\xf6.g\x1a@\x1a\x1b.\x01\n\xfe\xf6.\x1b\x1a@\x1ag.\x01\nL4\x804L\x01\n.g\x1a@\x1a\x1b.\xfe\xf6\x01\xe6\x1ag.n.\x1b\x1a\x99\xfe\xcd4LL4\x013\x99\x1a\x1b.n.g\x1a\x9a\x9a\x1ag.n.\x1b\x1a\x99\x0134LL4\xfe͙\x1a\x1b.n.g\x1a\x9a\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\v\x00\x1b\x00-\x00\x00\x00 \x04\x12\x10\x02\x04 $\x02\x10\x12\x0154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x03\x134'&+\x01\"\a\x06\x15\x13\x14\x16;\x0126\x02/\x01\xa2\x01a\xce\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x02\xb2\x12\r\xc0\r\x14\x14\r\xc0\r\x12\x02\x12\n\n\x0e\xdc\x0e\n\n\x11\x14\x0e\xb9\x0e\x13\x05\x80\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xfb\xef\xbe\x0e\x13\x14\r\xbe\r\x14\x13\x01f\x02m\f\x06\b\b\x06\f\xfd\x93\n\x0f\x0f\x00\x00\x00\x04\x00\x00\x00\x00\x06\x00\x05@\x00\r\x00\x16\x00\x1f\x00J\x00\x00%5\x115!\x15\x11\x15\x14\x16;\x0126\x013'&#\"\x06\x14\x16$4&#\"\x0f\x0132\x05\x11\x14\x06+\x01\x11\x14\x06#!\"&5\x11#\"&5\x11463!\"&4632\x1f\x017632\x16\x14\x06#!2\x16\x03\xa0\xfe\xc0$\x1c\xc0\x1c$\xfe8\xc3~\x1a+(88\x02\xd88(+\x1a}\xc2(\x01\xb0\x12\x0e`8(\xfb\xc0(8`\x0e\x12\x12\x0e\x01\xb8]\x83\x83]k=\x80\x80=k]\x83\x83]\x01\xb8\x0e\x12\xb48\x01\xd4\xc0\xc0\xfe,8\x19\x1b\x1b\x03e\xa1\x1f8P88P8\x1f\xa1\xa0\xfe\xc0\x0e\x12\xfe`(88(\x01\xa0\x12\x0e\x01@\x0e\x12\x83\xba\x83M\xa5\xa5M\x83\xba\x83\x12\x00\x02\x00\x00\x00\x00\a\x00\x05\x80\x00\x15\x00N\x00\x00\x004&#\"\x04\x06\a\x06\x15\x14\x16327>\x0176$32\x01\x14\a\x06\x00\a\x06#\"'.\x01#\"\x0e\x02#\"&'.\x0354>\x0254&'&54>\x027>\x047>\x0432\x1e\x02\x05\x00&\x1a\xac\xfe\xdc\xe3z\x13&\x1a\x18\x15\x1b^\x14\x89\x01\a\xb6\x1a\x02&\x14.\xfe\xeb\xdb\xd6\xe0\x94\x8a\x0f\x92\x17\x10/+>\x1d+)\x19\x02\b\x03\x03>J>\x1c\x02\tW\x97\xbem7\xb4\xb3\xb2\x95'\n'\x14\"'\x18'? \x10\x03&4&c\xa9\x87\x15\x18\x1a&\x13\x18^\x13|h\x01\x06_b\xe0\xfe\xc2ml/\x05J@L@#*\x04\x0e\x06\r\a#M6:\x13\x04D\n35sҟw$\x12\x0f\x03\t'%\n'\x11\x17\t\\\x84t\x00\x00\x00\x00\x02\x00\x00\xff\x00\x05\x80\x06\x00\x00\x0f\x003\x00\x00\x05\x15\x14\x06#!\"&=\x01463!2\x16\x01\x14\x0e\x05\x15\x14\x17'\x17.\x0454>\x0554'\x17'\x1e\x04\x05\x80\x13\r\xfa\xc0\r\x13\x13\r\x05@\r\x13\xff\x001O``O1C\x04\x01Z\x8c\x89Z71O``O1B\x03\x01Z\x8c\x89Z7\xa0@\r\x13\x13\r@\r\x13\x13\x04\x13N\x84]SHH[3`\x80\x01\x01)Tt\x81\xacbN\x84]SHH[3^\x82\x01\x01)Tt\x81\xac\x00\x00\x00\x00\x03\x00\x00\x00\x00\a\x00\x04\x80\x00\x11\x00!\x001\x00\x00\x01&'\x16\x15\x14\x00 \x00547\x06\a\x16\x04 $\x004&#\"\x06\x15\x14\x162654632\x00\x14\a\x06\x00 \x00'&476\x00 \x00\x17\x06\x80\x98\xe5=\xfe\xf9\xfe\x8e\xfe\xf9=嘅\x01\x91\x01\xd4\x01\x91\xfd\xb5\x1c\x14}\xb3\x1c(\x1czV\x14\x03l\x14\x8c\xfe'\xfd\xf2\xfe'\x8c\x14\x14\x8c\x01\xd9\x02\x0e\x01ٌ\x02@\xecuhy\xb9\xfe\xf9\x01\a\xb9yhu\xec\xcd\xf3\xf3\x029(\x1c\xb3}\x14\x1c\x1c\x14Vz\xfe\xd2D#\xe6\xfe\xeb\x01\x16\xe5#D#\xe5\x01\x16\xfe\xea\xe5\x00\x05\x00\x00\xff\xa0\a\x00\x04\xe0\x00\t\x00\x19\x00=\x00C\x00U\x00\x00%7.\x01547\x06\a\x12\x004&#\"\x06\x15\x14\x162654632%\x14\a\x06\x00\x0f\x01\x06#\"'&547.\x01'&476\x00!2\x177632\x1e\x03\x17\x16\x13\x14\x06\a\x01\x16\x04\x14\a\x06\a\x06\x04#76$7&'7\x1e\x01\x17\x02+NWb=嘧\x02\x89\x1c\x14}\xb3\x1c(\x1czV\x14\x01\x87\x01j\xfe\\i1\n\x12\fz\x10,\x8f\xf1X\x14\x14\x99\x01\xc6\x01\rY[6\n\x12\x05\x1a$\x1e!\x03\x10%\x9e\x82\x01\x18\b\x01\xc0\x14'F\x96\xfeu\xdeJ\xd4\x01iys\xa7?_\xaf9ɍ?\xc0kyhu\xec\xfe\xfe\x02n(\x1c\xb3}\x14\x1c\x1c\x14Vz\xef\a\x02\xbd\xfd\f\xbcY\x10F\n\x12\fKA؉\x1fL\x1f\xeb\x01\x10\x11a\x10\f\x13\x12\x13\x02\n\xfe0\x8b\xe52\x01\xf6-\x84F\"@Q\xac\xbe\x84\x12\uef33sp@\xb2_\x00\x00\x00\x00\x03\x00\x10\xff\x80\x06\xf0\x06\x00\x00\x0f\x00!\x003\x00\x00%54&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x03\x134'&+\x01\"\a\x06\x15\x13\x14\x16;\x0126\x03\x01\x16\a\x0e\x01#!\"&'&7\x01>\x012\x16\x04\x00\x13\r\xc0\r\x13\x13\r\xc0\r\x13\x02\x12\n\r\v\xdc\v\r\n\x11\x14\x0e\xb9\x0e\x13\r\x03\x00#%\x11;\"\xfa\x00\";\x11%#\x03\x00\x11\x01\x05`,@L\xa1\xa0\x05\x11\x80\a\f\x04\x03\x0f\x06\xfe\xe9\xfe\xfd5\x05\r`\t\x0e\x02\x0f\t\xbd\xfc\v\x02\x01\n`\t\x0e\x06\x02\xc2\x01\x03\xfe\x04\x0e\x03\x02\v\x80\x0e\x10\x02\x99\xa0L\xc0\x05`4\xc0L\xa1\xfdH\x13\x0e`\x06\x01\x03\r\x01\xfc\xfe\xfd\xc2\x11\x0e`\t\x02\v\xfc\xbd\a\x10\r\fa\t\x015\x01\x03\x01\x17\b\x10\x10\v\x80\r\x05\x9f\xa0L@\x00\x0f\x00\x00\xff\x00\x06\x80\x06\x00\x00\x03\x00\a\x00\v\x00\x0f\x00\x13\x00\x17\x00\x1b\x00\x1f\x00#\x003\x007\x00;\x00?\x00O\x00s\x00\x00\x17!\x11!\x01!\x11!%!\x11!\x01!\x11!%!\x11!\x01!\x11!\x01!\x11!\x01!\x11!%!\x11!\x01\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126\x01!\x11!%!\x11!\x01!\x11!7\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126%\x11\x14\x06#!\"&5\x1146;\x01546;\x012\x16\x1d\x01!546;\x012\x16\x1d\x0132\x16\x80\x01 \xfe\xe0\x01`\x01@\xfe\xc0\xfe\xa0\x01 \xfe\xe0\x01`\x01@\xfe\xc0\xfe\xa0\x01 \xfe\xe0\x02\xe0\x01@\xfe\xc0\xfe\x80\x01@\xfe\xc0\x03\x00\x01 \xfe\xe0\xfe\x80\x01@\xfe\xc0\xfe\xa0\x13\r@\r\x13\x13\r@\r\x13\x02\xe0\x01 \xfe\xe0\xfe\x80\x01@\xfe\xc0\x01\x80\x01 \xfe\xe0 \x13\r@\r\x13\x13\r@\r\x13\x01\x80L4\xfa\x804LL4\x80^B@B^\x01\x80^B@B^\x804L\x80\x01 \xfe\xe0\x01 @\x01@\xfe\xc0\x01@@\x01 \xfc\x00\x01 \x01\xc0\x01 \xfc\x00\x01 @\x01@\x02 \x01 \r\x13\x13\r\xfe\xe0\r\x13\x13\xfc\xad\x01@@\x01 \xfe\xe0\x01 \xc0\x01 \r\x13\x13\r\xfe\xe0\r\x13\x13M\xfb\x004LL4\x05\x004L`B^^B``B^^B`L\x00\x00\x00\x03\x00\x00\xff\xa0\a\x00\x05\xe0\x00\x12\x007\x00q\x00\x00\x01\x06\a.\x04+\x01\"&=\x0146;\x012\x00\x14\a\x01\x06#\"&=\x01\"\x0e\x01.\x06'67\x1e\x043!54632\x17\x01\x12\x14\a\x01\x06#\"&=\x01!\"\x0e\x02\a\x06\a\x0e\x06+\x01\"&=\x0146;\x012>\x02767>\x063!54632\x17\x01\x02\x9amBZxPV3!\x12\x0e\xc0\x0e\x12\x1emBZxPV3!\xc0\x0e\x12\n\xfe\xc1\x00\x00\x00\x01\x00\x00\xff\x00\a\x00\x05\x00\x00&\x00\x00\x00\x10\x02\x04#\"'\x06\x05\x06\a\x06&'5&6&>\x027>\x057&\x0254>\x01$32\x04\a\x00\xf0\xfed\xf4FK\xc6\xfe\xfa1A\x11\x1b\x04\x03\x05\x01\n\x02\f\x02\a0\x15)\x18\x1e\v\x9d\xb5\x8e\xf0\x01L\xb6\xf4\x01\x9c\x03.\xfe\xa4\xfe٫\b\xafC\x0e\b\x02\x16\x12\x01\x04\x10\x04\x0f\x03\x0e\x02\b5\x178.H(Y\x01\x06\x96\x82\xed\xace\xab\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00#\x003\x00C\x00\x00\x01\x15\x14\x02\x04 $\x02=\x01463!2\x16\x1d\x01\x14\x1e\x032>\x03=\x01463!2\x16\x01\x11\x14\x06#!\"&5\x11463!2\x16\x05\x11\x14\x06#!\"&5\x11463!2\x16\x06\x00\xc5\xfe\xa1\xfeH\xfe\xa1\xc5&\x1a\x01\x80\x1a&/\x027\x03#\"&463!2\x1e\x04\x17!2\x16\x02\x80LhLLh\x03\xccLhLLh\xcc!\x18\xfb\xec\r\x18\x03\x98\x1a&&\x1a\xfc\x00\x1a&\x10\x10\x1b\x02\xb1\xcc\x1a&&\x1a\x01\x00\x10\x19\x0e\f\x04\a\x01\x04\xb1\x1a&4hLLhLLhLLhL\x03\xc0\xfe\x00\x18%\x03z<\n\x100&4&&\x1a\v)\x1f1\x05\x037&4&\r\x12\x1f\x15&\a&\x00\x00\x00\x00\x01\x00\x00\x00\x00\x06\x80\x05\x80\x00\x14\x00\x00\x01\x11\x14\x06#!\"&5\x11463!2\x16\x1d\x01!2\x16\x06\x80\x84\\\xfb@\\\x84\x84\\\x01@\\\x84\x02\xa0\\\x84\x03\xa0\xfd@\\\x84\x84\\\x03\xc0\\\x84\x84\\ \x84\x00\x00\x00\x00\x02\x00\x00\x00\x00\aW\x05\x80\x00\x13\x00*\x00\x00\x01\x14\a\x01\x0e\x01#!\"&547\x01>\x013!2\x16\x01\x15!\"\x06\a\x01\a4&5\x11463!2\x16\x1d\x01!2\x16\aW\x1f\xfe\xb0+\x9bB\xfb\xc0\"5\x1f\x01P+\x9bB\x04@\"5\xfe\xa9\xfc\xc0^\xce=\xfe\xaf\x05\x01\x84\\\x01@\\\x84\x02 \\\x84\x02H\x1f#\xfet3G\x1a\x1e\x1f#\x01\x8c3G\x1a\x01:\xa0_H\xfet\x06\x04\x11\x04\x03\xc0\\\x84\x84\\ \x84\x00\x00\x00\x01\x00@\xff\x00\x02\xc0\x06\x00\x00\x1f\x00\x00\x00\x14\x06+\x01\x1132\x16\x14\a\x01\x06\"'\x01&46;\x01\x11#\"&47\x0162\x17\x01\x02\xc0&\x1a\x80\x80\x1a&\x13\xff\x00\x134\x13\xff\x00\x13&\x1a\x80\x80\x1a&\x13\x01\x00\x134\x13\x01\x00\x04\xda4&\xfc\x00&4\x13\xff\x00\x13\x13\x01\x00\x134&\x04\x00&4\x13\x01\x00\x13\x13\xff\x00\x00\x00\x00\x01\x00\x00\x01@\a\x00\x03\xc0\x00\x1f\x00\x00\x00\x14\a\x01\x06\"&=\x01!\x15\x14\x06\"'\x01&47\x0162\x16\x1d\x01!5462\x17\x01\a\x00\x13\xff\x00\x134&\xfc\x00&4\x13\xff\x00\x13\x13\x01\x00\x134&\x04\x00&4\x13\x01\x00\x02\x9a4\x13\xff\x00\x13&\x1a\x80\x80\x1a&\x13\x01\x00\x134\x13\x01\x00\x13&\x1a\x80\x80\x1a&\x13\xff\x00\x00\x00\x00\x05\x00\x00\xff\x80\b\x00\x05\x80\x00\x03\x00\a\x00\r\x00\x11\x00\x15\x00\x00\x01\x11!\x11\x01\x11!\x11\x01\x15!\x113\x11\x01\x11!\x11\x01\x11!\x11\x02\x80\xff\x00\x02\x80\xff\x00\x05\x00\xf8\x00\x80\x05\x00\xff\x00\x02\x80\xff\x00\x02\x80\xfe\x00\x02\x00\x02\x00\xfc\x00\x04\x00\xfb\x80\x80\x06\x00\xfa\x80\x03\x80\xfd\x00\x03\x00\x01\x80\xfb\x80\x04\x80\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x000\x00@\x00\x00\x01\x06\a67\x06\a&#\"\x06\x15\x14\x17.\x01'\x06\x15\x14\x17&'\x15\x14\x16\x17\x06#\"'\x1e\x01\x17\x06#\"'\x1632>\x0354'6\x01\x11\x14\x06#!\"&5\x11463!2\x16\x05\x008AD\x19AE=\\W{\x05\x81\xe2O\x1d[/5dI\x1d\x16\r\x1a\x15kDt\x91\x1a\x18\x94\xaepČe1\x01?\x01*\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x03\x9e\x19\t(M&\rB{W\x1d\x13\ata28r=\x01\x19\x02Ku\x0e\b\x04?R\x01Z\x03^Gw\x9b\xa9T\x12\t-\x01\x02\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x01\x00\x00\xff\x80\x06\x00\x05\x80\x00$\x00\x00\x012\x16\x15\x11\x14\x06+\x01\x1137#546375&#\"\x06\x1d\x01#\x153\x11!\"&5\x11463\x04\xe0w\xa9\xa9w\xbc\xc7\x1e\xe5/Dz?s\x88\xa3\xc8\xc8\xfd\xecw\xa9\xa9w\x05\x80\xa9w\xfc@w\xa9\x02S\xe8\x9488\x01\xcf\t\xa0\x92\xab\xe8\xfd\xad\xa9w\x03\xc0w\xa9\x00\x00\x00\x00\a\x00\x00\xff\x80\a\x00\x05\x80\x00\x0f\x00\x17\x00\x1b\x00#\x00'\x00.\x00>\x00\x00\x004&#\"\x06\x15\x14\x1626546326\x14\x06\"&462\x01!5!\x00\x10& \x06\x10\x16 \x01!5!\x03!=\x01!\a!%\x11\x14\x06#!\"&5\x11463!2\x16\x03\xa0\x12\x0eB^\x12\x1c\x128(\x0e\xf2\x96Ԗ\x96\xd4\xfc\x96\x06\x00\xfa\x00\x04\x80\xe1\xfe\xc2\xe1\xe1\x01>\xfc\xe1\x01\x80\xfe\x80\x80\x06\x00\xfc\xc4@\xfd|\x06\x80K5\xfa\x005KK5\x06\x005K\x02\xb2\x1c\x12^B\x0e\x12\x12\x0e(8\bԖ\x96Ԗ\xfc\u0080\x01\x1f\x01>\xe1\xe1\xfe\xc2\xe1\x04\x02\x80\xfe\xc0v\x8a\x80\x80\xfb\x005KK5\x05\x005KK\x00\x02\x00\x00\xffH\x06\x93\x05\x80\x00\x15\x00G\x00\x00\x004&\"\x06\x15\x14\x17&#\"\x06\x14\x162654'\x1632\x01\x14\x06#\".\x02'\a\x17\x16\x15\x14\x06#\"'\x01\x06#\"&54\x12$32\x16\x15\x14\a\x017.\x0354632\x17\x1e\x04\x03@p\xa0p\x13)*Ppp\xa0p\x13)*P\x03\xc3b\x11\t'\"+\x03`\xdc\x1cN*(\x1c\xfda\xb0\xbd\xa3;\x012\xa0\xa3̓\x01c`\x03.\" b\x11\r\n\x06PTY9\x03\xb0\xa0ppP*)\x13p\xa0ppP*)\x13\xfe\x00\x11b \".\x03`\xdc\x1c(*N\x1c\x02\x9f\x83ͣ\xa0\x012\xbeͣ\xbd\xb0\xfe\x9d`\x03+\"'\t\x11b\n\x06MRZB\x00\x00\x00\x00\x06\x00\x00\xff\x0f\a\x80\x05\xf0\x00\a\x00\x11\x00\x1b\x00\u007f\x00\xbd\x00\xfb\x00\x00\x004&\"\x06\x14\x162\x014&\"\x06\x15\x14\x1626\x114&\"\x06\x15\x14\x1626\x01\x15\x14\x06\x0f\x01\x06\a\x16\x17\x16\x15\x14\a\x0e\x01#\"/\x01\x06\a\x06\a\x06+\x01\"&/\x01&'\a\x06#\"'&547>\x017&/\x01.\x01=\x0146?\x0167&'&547>\x0132\x1f\x0167676;\x012\x16\x1f\x01\x16\x177632\x17\x16\x15\x14\a\x0e\x01\a\x16\x1f\x01\x1e\x01\x01\x15\x14\a\x06\a\x16\x15\x14\a\x06#\"&'\x06\"'\x0e\x01#\"'&547&'&=\x014767&547>\x0232\x16\x1762\x176?\x012\x17\x16\x15\x14\a\x16\x17\x16\x11\x15\x14\a\x06\a\x16\x15\x14\a\x06#\"&'\x06\"'\x0e\x01#\"'&547&'&=\x014767&547>\x0232\x16\x1762\x176?\x012\x17\x16\x15\x14\a\x16\x17\x16\x03\x80\x96Ԗ\x96\xd4\x03\x96LhLKjKLhLKjK\xfe\x80\x0e\t\x9b\v\x15\"8\a\a\x17w\x13\v\ns%(\v\f\a\x17\xba\v\x12\x01\x17\")v\a\r\v\n\x90\a\n>\x10\x17\f\x98\n\x0e\x0e\t\x9b\v\x15\"8\a\a\x16x\x13\v\ns\"+\v\f\a\x17\xba\v\x12\x01\x17\")v\b\f\v\n\x90\a\f<\x0f\x17\v\x98\n\x0e\x02\x80\x95\f\x123\x04z\x02\bL\x0e\x14\x14\x14\x0eL\b\x02z\x043\x12\f\x95\x95\r\x113\x04\x04>8\x02\bL\x0e\x14\x14\x143)\x06\x04x\x043\x11\r\x95\x95\f\x123\x04z\x02\bL\x0e\x14\x14\x14\x0eL\b\x02z\x043\x12\f\x95\x95\r\x113\x04\x04>8\x02\bL\x0e\x14\x14\x143)\x06\x04x\x043\x11\r\x95\x02\x16Ԗ\x96Ԗ\xff\x004LL45KK\x0454LL45KK\xfe\x90\xb9\n\x13\x01\x18#)0C\v\t\f\a\x1ew\aZ\x13\fl/\x18\x0f\n\x99\n\x15Y\a\b\x85\x1b\t\n\x0eN\x16,&\x18\x01\x11\v\xb9\n\x13\x01\x18#)0C\v\t\f\b\x1ev\aZ\x12\x0el.\x18\x0f\n\x99\n\x15Y\a\b\x85\x1b\b\v\x10L\x160\"\x17\x02\x11\xfd\xe0\x8c\x10\x0f\x1b\x19q\x19\x04\x03G^\x15\x02\x02\x15^G\x03\x04\x19q\x19\x1b\x0f\x10\x8c\x10\x0f\x1d\x17q\x19\x04\x03\x02$ ]\x15\x02\x02G)\x02F\x03\x04\x19q\x17\x1d\x0f\x03\xf0\x8c\x10\x0f\x1b\x19q\x19\x04\x03G^\x15\x02\x02\x15^G\x03\x04\x19q\x19\x1b\x0f\x10\x8c\x10\x0f\x1d\x17q\x19\x04\x03\x02$ ]\x15\x02\x02G)\x02F\x03\x04\x19q\x17\x1d\x0f\x00\x00\x00\x00\x02\x00\x00\xff\x80\a\x00\x05\x00\x00%\x00O\x00\x00\x00\x10\x06\x04#\"'\x06\a\x06\a#\"&'&4>\x057>\x047.\x01546$ \x04\x01\x14\x06\a\x1e\x04\x17\x1e\x06\x14\a\x0e\x01'&'&'\x06# '\x1632$7>\x0154'\x1e\x01\x05\x80\xbc\xfe\xbb\xbfVZ|\x9a$2\x03\v\x13\x02\x01\x01\x03\x02\x05\x03\x06\x01\x05$\x10\x1d\x15\n|\x8e\xbc\x01E\x01~\x01E\x02<\x8e|\n\x15\x1d\x10$\x05\x01\x06\x03\x05\x02\x03\x01\x01\x03\x14\f2$\x9a|ZV\xfe\xf1\xc9:\x1e\xa1\x01(t}\x86\x17\x81\x96\x03\x8b\xfe\xea\xec\x89\x10X(\t\a\x10\r\x03\a\x06\x06\x04\a\x03\a\x01\x06&\x15%(\x18H\xd2w\x8b쉉\xfd\x89x\xd1H\x18(%\x15&\x06\x01\a\x03\a\x04\x06\x06\a\x03\x0e\x10\x01\a\t(X\x10\x84\x04ZT\\\xf0\x86MKG\xd6\x00\x00\x03\x00\x00\xff\x80\x06\x00\x06\x00\x00\a\x00<\x00m\x00\x00$4&\"\x06\x14\x162\x014&#!4654&#\x0e\x02\a\x06\a\x0e\x06+\x01\x1132\x1e\x04\x17\x16;\x01254'>\x014'654&'>\x017\x14\a\x16\x15\x14\a\x16\x15\x14\a\x16\x06+\x02\"&'&#!\"&5\x11463!6767>\x027632\x1e\x01\x15\x14\a32\x16\x01\x00&4&&4\x04\xa6N2\xfe\xa0`@`\x1a\x18%)\x167\x04&\x19,$)'\x10 \r%\x1d/\x170\x05Ӄy\xc0\x05\x1e#\x125\x14\x0f +\x801\t&\x03<\x01\xac\x8d$]`\xbb{t\x16\xfe\xe05KK5\x01\x12$e:1\x18\x17&+'3T\x86F0\xb0h\x98\xa64&&4&\x02\x803M:\xcb;b^\x1av\x85+\x17D\x052 5#$\x12\xfd\x80\x06\a\x0f\b\x11\x02I\xa7\x1a\x1e\x10IJ 2E\x19=\x11\x01\\$YJ!$MC\x15\x16eM\x8b\xa1-+(K5\x02\x805K\x18\x83K5\x19y\x84*%A\x8au]c\x98\x00\x00\x00\x03\x00\x00\xff\x00\x06\x00\x05\x80\x00\a\x00>\x00q\x00\x00\x004&\"\x06\x14\x162\x014&'>\x0154'654&'654&+\x01\"\a\x0e\x05+\x01\x1132\x1e\x05\x17\x16\x17\x1e\x02\x172654&5!267\x14\x06+\x01\x16\x15\x14\a\x0e\x01#\"'.\x03'&'&'!\"&5\x11463!27>\x01;\x012\x16\a\x15\x16\x15\x14\a\x16\x15\x14\a\x16\x01\x00&4&&4\x04\xa6+ \x0f\x145\x12#\x1e\x05bW\x80\x83\xd3\x050\x17/\x1d%\r \x10')$,\x19&\x047\x16)%\x18\x1a`@`\x01`2N\x80\x98h\xb00##\x86T3'\"(\v\x18\x130;e$\xfe\xee5KK5\x01 \x16t\x80\xbeip\x8c\xad\x01<\x03&\t1\x04&4&&4&\xfe\x00#\\\x01\x11=\x19E2\x1f&%I\x10\x1e\x1aURI\x02\x11\b\x0f\a\x06\xfd\x80\x12$#5 2\x05D\x17+\x85v\x1a^b;\xcb:M2g\x98c]vDEA%!bSV\x152M\x83\x18K5\x02\x805K(,,\x9e\x89\x05Me\x16\x15CM$!I\x00\x00\x00\x01\x00\x00\xff\xad\x03@\x05\xe0\x00\x12\x00\x00\x01\x11\x05\x06#\"&547\x13\x01&547%\x136\x03@\xfe?\x16\x12\x15\x15\x02V\xfe\x94\x198\x01\xf6\xe1\x13\x05\xe0\xfa\xc5\xec\f\x1d\x15\x06\x0e\x01\xf4\x01b\x1b\x15%\tI\x01\xc7)\x00\x00\x00\x00\x02\x00\x00\xff\x80\a\x00\x05\x80\x00\x1c\x009\x00\x00\x014.\x03\"\x0e\x02\a\x06\"'.\x03\"\x0e\x03\x15\x14\x17\t\x0167\x14\a\x01\x06\"'\x01.\x0454632\x1e\x02\x17>\x0332\x16\x06\x80+C`\\hxeH\x18\x12>\x12\x18Hexh\\`C+\xbb\x02E\x02D\xbc\x80\xe5\xfd\x91\x124\x12\xfd\x90\n#L\x81oP$$Po\x81>\xe0\xfe\x03\xacQ|I.\x103MC\x1c\x16\x16\x1cCM3\x10.I|Q\xa8\xbb\xfd\xd0\x02/\xbc\xa8\xdd\xe5\xfd\xa8\x12\x12\x02Z\b$_d\x8eC\xdc\xf8+I@$$@I+\xf8\x00\x00\x00\x00\x02\x00\x00\x00\x00\x06 \x05\x00\x00(\x00@\x00\x00%\x14\x16\x0e\x02#!\"&5\x11463!2\x16\x15\x14\x16\x0e\x02#!\"\x06\x15\x11\x14\x163!:\x02\x1e\x03\x00\x14\a\x01\x06\"&5\x11!\"&5\x11463!\x11462\x17\x01\x02\x80\x02\x01\x05\x0f\r\xfe\xc0w\xa9\xa9w\x01@\r\x13\x02\x01\x05\x0f\r\xfe\xc0B^^B\x01 \x01\x14\x06\x11\x06\n\x04\x03\xa0\x13\xfd\xe0\x134&\xfe@\x1a&&\x1a\x01\xc0&4\x13\x02 `\x04 \x15\x1a\r\xa9w\x02\xc0w\xa9\x13\r\x04 \x15\x1a\r^B\xfd@B^\x02\x04\a\v\x0224\x13\xfd\xe0\x13&\x1a\x01 &\x1a\x01\x80\x1a&\x01 \x1a&\x13\xfd\xe0\x00\x00\x04\x00\x00\xff\x80\x06\x00\x05\x80\x00\x03\x00\x0f\x00%\x005\x00\x0073\x11#7.\x01\"\x06\x15\x14\x16;\x0126\x013\x114&#\"\a35#\x16\x033\x1147>\x0132\x15\x01\x11\x14\x06#!\"&5\x11463!2\x16\xed\xe7\xe7\xf6\x01FtIG9\x01;H\x02I\xe7\x92x\x88I\x02\xe7\x03\x03\xe7\a\x0f<,t\x01ԩw\xfc@w\xa9\xa9w\x03\xc0w\xa9z\x02\xb6\xd64DD43EE\xfc\xa7\x01\x8e\x9a\x9eueB\xfd\x8c\x01\x84&\x12#1\x9d\x02s\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x02\x00\x00\xff\x00\x04\x80\x05\x80\x00\v\x00.\x00\x00\x01\x114&\"\x06\x15\x11\x14\x1626\x01\x14\x06#!\x03\x0e\x01+\x01\"'\x03!\"&5463\x11\"&463!2\x16\x14\x06#\x112\x16\x01\xe0\x12\x1c\x12\x12\x1c\x12\x02\xa0&\x1a\xfeS3\x02\x11\f\x01\x1b\x05L\xfel\x1a&\x9dc4LL4\x02\x804LL4c\x9d\x02\xa0\x01\xc0\x0e\x12\x12\x0e\xfe@\x0e\x12\x12\xfe\xae\x1a&\xfe\x1d\f\x11\x1b\x01\xe5&\x1a{\xc5\x02\x00LhLLhL\xfe\x00\xc5\x00\x00\x00\x02\x00\x00\x00\x00\a\x00\x06\x00\x00'\x00?\x00\x00\x01\x11\x14\x06#!\"&5\x11463!2\x16\x1d\x01\x14\x06#!\"\x06\x15\x11\x14\x163!265\x1146;\x012\x16\x01\x11\x14\x06\"/\x01\x01\x06\"/\x01&47\x01'&463!2\x16\x05\x80\xa9w\xfc\xc0w\xa9\xa9w\x02\xc0\x0e\x12\x12\x0e\xfd@B^^B\x03@B^\x12\x0e@\x0e\x12\x01\x80&4\x13\xb0\xfdt\n\x1a\nr\n\n\x02\x8c\xb0\x13&\x1a\x02\x00\x1a&\x02`\xfe\xc0w\xa9\xa9w\x03@w\xa9\x12\x0e@\x0e\x12^B\xfc\xc0B^^B\x01@\x0e\x12\x12\x03R\xfe\x00\x1a&\x13\xb0\xfdt\n\nr\n\x1a\n\x02\x8c\xb0\x134&&\x00\x02\x00\x00\x00\x00\x06\x00\x05\x00\x00\x17\x00@\x00\x00\x00\x14\a\x01\x06\"&5\x11!\"&5\x11463!\x11462\x17\t\x01\x11\x14\x06#!\"&54&>\x023!265\x114&#!*\x02.\x0354&>\x023!2\x16\x04\xa0\x13\xfd\xe0\x134&\xfe@\x1a&&\x1a\x01\xc0&4\x13\x02 \x01s\xa9w\xfe\xc0\r\x13\x02\x01\x05\x0f\r\x01@B^^B\xfe\xe0\x01\x14\x06\x11\x06\n\x04\x02\x01\x05\x0f\r\x01@w\xa9\x02\x9a4\x13\xfd\xe0\x13&\x1a\x01 &\x1a\x01\x80\x1a&\x01 \x1a&\x13\xfd\xe0\x013\xfd@w\xa9\x13\r\x04 \x15\x1a\r^B\x02\xc0B^\x02\x04\a\v\b\x04 \x15\x1a\r\xa9\x00\x03\x00\x00\xff\x80\x06\x80\x05\x80\x00\x06\x00\r\x00I\x00\x00\x01&5!\x15\x14\x16%5!\x14\a>\x017\x15\x14\x0e\x02\a\x06\a\x0e\x01\x15\x14\x1632\x16\x1d\x01\x14\x06#!\"&=\x014632654&'&'.\x03=\x01463!5463!2\x16\x1d\x01!2\x16\x01\xcaJ\xff\x00\xbd\x04\xc3\xff\x00J\x8d\xbd\x80S\x8d\xcdq*5&\x1d=CKu\x12\x0e\xfc\xc0\x0e\x12uKC=\x1d&5*q͍S8(\x01 ^B\x02@B^\x01 (8\x02\x8d\xa2\xd1`N\xa8\xf6`Ѣ\x1d\xa8\u0380G\x90tO\x056)\"M36J[E@\x0e\x12\x12\x0e@E[J63M\")6\x05Ot\x90G\x80(8`B^^B`8\x00\x00\x00\t\x00\x00\xff\x80\x06\x00\x05\x80\x00\a\x00\x0f\x00\x17\x00\x1f\x00'\x00,\x002\x00\x81\x00\x91\x00\x00\x016'&\a\x06\x17\x16'&\a\x06\x17\x1676'6'&\a\x06\x17\x16\x176&'&\x06\x17\x16\x176'&\a\x06\x17\x1e\x014#\"\x147&\x06\x17\x166\x014\x00 \x00\x15\x14\x12\x17\x16654'\x0e\x02.\x01'&'.\x03632\x1e\x01\x17\x1e\x0126767.\x03547&76\x16\x1f\x0162\x17>\x02\x17\x16\a\x16\x15\x14\x0e\x03\a\x16\x15\x14\x06\x15\x14\x1676\x12\x01\x11\x14\x06#!\"&5\x11463!2\x16\x02\a\x04\a\t\x05\x04\a\t\x17\x05\a\x06\x06\a\x05\x06/\x02\a\a\x01\x03\a\b\x16\x02\x01\x03\x06\b\x05\x06[\x02\v\t\x04\x02\v\t.\f\n=\x02\x16\x02\x02\x14\x02\x82\xfe\xd4\xfeX\xfe\xd4Ě\x12\x11\x01\x06\x134,+\b\x17\"\x02\x05\v\x03\v\x0e\x06\x12*\f\x10+, \x0e\a\x1a1JH'5\x18\x1d\x13G\x19\x1a:\x8c:\v#L\x13\x1d\x185\x1c+@=&#\x01\x11\x12\x9a\xc4\x01\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x01P\x06\a\a\x05\x06\a\a.\a\x03\x04\b\b\x03\x041\x04\x04\x02\x04\x05\x03\x02\x13\x01\a\x02\a\b\a\x06G\a\x04\x03\a\a\x04\x03\x04\x10\x10\x0f\a\x04\a\b\x04\x01E\xd4\x01,\xfe\xd4ԧ\xfe\xf54\x03\x10\f4+\x01\x03\x01\t\x1f\x1a;\x0f\x01\x05\v\b\a\x04\x1b\x16\x1c\x1c\a\x06/\x16\x06\x195cFO:>J\x06\x1b\x10\x10\x11\x11\a\x16\x1e\x06J>:O9W5$\x10\x04\x1f@(b\x02\f\x10\x034\x01\v\x02\x87\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x04\x00\x00\xff\x80\x06\x80\x05\xc0\x00\a\x00\x0f\x00'\x00?\x00\x00$4&\"\x06\x14\x162$4&\"\x06\x14\x162\x13\x11\x14\x06#!\"&5\x11463!\x1e\x013!267!2\x16\x01\x06#!\x11\x14\x06#!\"&5\x11!\"'&7\x0162\x17\x01\x16\x05\x00&4&&4\x01&&4&&4\xa68(\xfa@(88(\x01\xab\x15c=\x01\x00=c\x15\x01\xab(8\xfe\xbb\x11*\xff\x00&\x1a\xff\x00\x1a&\xff\x00*\x11\x11\x1f\x01\xc0\x126\x12\x01\xc0\x1f&4&&4&&4&&4&\x01 \xfe\xc0(88(\x01@(88HH88\x02`(\xfe@\x1a&&\x1a\x01\xc0('\x1e\x01\xc0\x13\x13\xfe@\x1e\x00\x00\x00\x00\x02\x00\x00\xff\x80\x05\xff\x05\x80\x001\x00c\x00\x00\x014&'.\x0254654'&#\"\x06#\"&#\"\x0e\x01\a\x06\a\x0e\x02\x15\x14\x16\x15\x14\x06\x14\x1632632\x16327>\x01\x127\x14\x02\x06\a\x06#\"&#\"\x06#\"&54654&54>\x02767632\x1632632\x16\x15\x14\x06\x15\x14\x1e\x02\x17\x1e\x01\x05\u007f\x0e\v\f\n\b\n\n\x04\t\x13N\x14<\xe8;+gC8\x89A`\u007f1\x19\x16\x18\x16\x18a\x199\xe19\xb5g\x81\xd5w\x80\x8c\xfc\x9b|\xca9\xe28\x18a\x19Ie\x16\x19$I\x80VN\x9a\xc2z<\xe7:\x13L\x14QJ\n\x04\x03\f\x02\x10\x12\x02\xc6,\x8b\x1b\x1e\x1c-\x1a\x17[\x16%\x12\x01\t0\x17\x18\x1661I\xe9\xef\x81(\xa0)\x17W,\x1d\x16\x1f$-\xd7\x01\x14\x8b\xa5\xfe\xbb\xfb7,\x1d\x1doI\x18X\x17(\xa1)o\xd5ζA;=N0\neT\x17Z\x17\r\x18\t \x04(\x9d\x00\x00\x01\x00\x00\x00\x00\x05\x80\x05\x80\x00O\x00\x00\x01\x14\x06\a\x06\a\x06#\".\x03'&'&\x00'&'.\x0454767>\x0132\x17\x16\x17\x1e\x02\x17\x1e\x02\x15\x14\x0e\x02\x15\x14\x1e\x02\x17\x1e\x01\x17\x1e\x0332>\x0232\x1e\x01\x17\x1e\x02\x17\x16\x17\x16\x05\x80\x14\v\x15e^\\\x1b4?\x1fP\tbM\u007f\xfe\xeeO0#\x03\x1e\v\x12\a382\x19W\x1b\x0e\a\x12#\v& \x0f\x03\x1d\x0e9C9\n\a\x15\x01Lĉ\x02\"\x0e\x1b\t\x1282<\x14\x0e\x1d*\x04\x199F\x13F\x06\x03\x01(\x1bW\x19283\a\x12\v\x1e\x03#0O\x01\x12\u007fMb\tP\x1f?4\x1b\\^e\x15\v\x14\x03\x06F\x13F9\x19\x04*\x1d\x0e\x14<28\x12\t\x1b\x0e\"\x02\x89\xc4L\x01\x15\a\n9C9\x0e\x1d\x03\x0f &\v#\x12\a\x00\x00\x00\x02\x00\x00\x00\x00\x05\x80\x05\x80\x00\x0f\x00\x1f\x00\x00\x01!\"\x06\x15\x11\x14\x163!265\x114&\x17\x11\x14\x06#!\"&5\x11463!2\x16\x04`\xfc\xc0B^^B\x03@B^^ީw\xfc\xc0w\xa9\xa9w\x03@w\xa9\x05\x00^B\xfc\xc0B^^B\x03@B^\xa0\xfc\xc0w\xa9\xa9w\x03@w\xa9\xa9\x00\x02\x00\x00\xff\x97\x05\x00\x05\x80\x00\x06\x00#\x00\x00\x01!\x11\x017\x17\x01\x132\x17\x1e\x01\x15\x11\x14\x06\a\x06#\"'\t\x01\x06#\"'.\x015\x1146763\x04\x80\xfc\x00\x01\xa7YY\x01\xa7\f\x17\x15!''!\x13\x190#\xfeG\xfeG$/\x17\x15!''!\x15\x17\x05\x00\xfb&\x01\x96UU\xfej\x05Z\t\r8\"\xfa\xf7\"8\r\b \x01\xa8\xfeX!\t\r8\"\x05\t\"8\r\t\x00\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00G\x00W\x00\x00\x014.\x04'.\x02#\"\x0e\x02#\".\x02'.\x01'.\x0354>\x0254.\x01'.\x05#\"\a\x0e\x01\x15\x14\x1e\x04\x17\x16\x00\x17\x1e\x0532676\x01\x11\x14\x06#!\"&5\x11463!2\x16\x05\x00\x04 1.-\x06\x05\x1c\x16\n\x0f+$)\r\a\x13\f\x16\x03c\x8e8\x02\r\x06\a)1)\n\x14\x03\x03\x18\x1a\x1b\x17\n\v05.D\x05\x05\r\a\x12\x02<\x019\xa4\x060\x12)\x19$\x109\x93\x15\x16\x01\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x01W\v\n\x17\x1b\x1a\x18\x03\x03\x14\n)1)\a\x06\r\x027\x8fc\x03\x16\f\x13\a\r)$+\x0f\n\x16\x1c\x05\x06-.1 \x04\x16\x15\x939\x10$\x19)\x120\x06\xa4\xfe\xc7<\x02\x12\a\r\x05\x05D.5\x039\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x01\x00,\x00\x00\x06T\x05\x00\x001\x00\x00\x01\x06\a\x16\x15\x14\x02\x0e\x01\x04# '\x16327.\x01'\x16327.\x01=\x01\x16\x17.\x01547\x16\x04\x17&54632\x1767\x06\a6\x06TC_\x01L\x9b\xd6\xfeҬ\xfe\xf1\xe1#+\xe1\xb0i\xa6\x1f!\x1c+*p\x93DNBN,y\x01[\xc6\b\xbd\x86\x8c`m`%i]\x04hbE\x0e\x1c\x82\xfe\xfd\xee\xb7m\x91\x04\x8a\x02}a\x05\v\x17\xb1u\x04&\x03,\x8eSXK\x95\xb3\n&$\x86\xbdf\x159s?\n\x00\x00\x00\x01\x00_\xff\x80\x03\xbf\x06\x00\x00\x14\x00\x00\x01\x11#\"\x06\x1d\x01!\x03#\x11!\x11#\x11!54632\x03\xbf\x9dV<\x01%'\xfe\xfe\xce\xff\x00\xffЭ\x93\x05\xf4\xfe\xf8HH\xbd\xfe\xd8\xfd\t\x02\xf7\x01(ں\xcd\x00\x00\x00\b\x00\x00\xff\xa7\x06\x00\x05\x80\x00T\x00\\\x00d\x00k\x00s\x00z\x00\x82\x00\x88\x00\x00\x00 \x04\x12\x15\x14\x00\a\x06&54654'>\x0454'6'&\x06\x0f\x01&\"\a.\x02\a\x06\x17\x06\x15\x14\x1e\x03\x17\x06\a\x0e\x01\"&'.\x01/\x01\"\x06\x1e\x01\x1f\x01\x1e\x01\x1f\x01\x1e\x03?\x01\x14\x16\x15\x14\x06'&\x0054\x12\x136'&\a\x06\x17\x16\x176'&\a\x06\x17\x16\x176'&\a\x06\x16\x176'&\a\x06\x17\x16\x176'&\x06\x17\x1674\a\"\x15\x14727&\a\x06\x166\x02/\x01\xa2\x01a\xce\xfe\xdb\xe8\x1b\x1a\x0149[aA)O%-\x1cj'&]\xc6]\x105r\x1c-%O)@a[9'\n\x150BA\x17\x13;\x14\x14\x15\x10\x06\f\a\a\x16+\n\n\r>HC\x16\x17\x01\x1a\x1b\xe8\xfe\xdb\xceU\x03\n\n\x03\x03\n\t#\a\t\n\x06\a\t\n$\t\t\b\t\t\x122\b\f\f\b\t\r\fA\x03\x10\x0f\b\x11\x0fC\x11\x10\x11\x10:\x02\x10\x10\x04 \x05\x80\xce\xfe\x9f\xd1\xfb\xfeoM\x05\x18\x12\x03\x93=a-\x06\x186O\x83UwW[q\t(\x18\x18\x1a\x1a\v -\tq[WwU\x82P6\x18\x06$C\n\n+) (\x04\x03\t\x0e\x0e\x05\x05\n8\x17\x17&/\r\x01\x04\x04&e\x04\x12\x18\x05M\x01\x91\xfb\xd1\x01a\xfc\u007f\a\x05\x03\x05\a\x05\x06\x1a\x05\v\t\x06\x05\v\n&\a\f\r\a\x05\x1a$\b\v\f\t\b\v\f\x10\v\x05\x04\x16\x04\x06\a\r\x02\v\r\x02\x15\v\x02\x03\x18\b\x00\x00\x00\x01\x00\x00\x00\x00\x06\x80\x05\x80\x00%\x00\x00\x01\x11\x14\x06+\x01\"&5\x114&\"\x06\x1d\x0132\x16\x15\x11\x14\x06#!\"&5\x11463!54\x00 \x00\x06\x80&\x1a@\x1a&\x96Ԗ`(88(\xfc@(88(\x02\xa0\x01\a\x01r\x01\a\x03\xc0\xff\x00\x1a&&\x1a\x01\x00j\x96\x96j\xc08(\xfd\xc0(88(\x02@(8\xc0\xb9\x01\a\xfe\xf9\x00\x00\x00\x05\x00\x00\xff\x80\a\x80\x05\x80\x00\x0f\x00\x19\x00#\x00'\x00+\x00\x00\x012\x16\x15\x11\x14\x06#!\"&5\x11463\x15\"\x06\x1d\x01!54&#\x11265\x11!\x11\x14\x16375!\x1535!\x15\x06\xe0B^^B\xf9\xc0B^^B\r\x13\x06\x80\x13\r\r\x13\xf9\x80\x13\r`\x01\x00\x80\x01\x80\x05\x80^B\xfb@B^^B\x04\xc0B^\x80\x13\r\xe0\xe0\r\x13\xfb\x00\x13\r\x02`\xfd\xa0\r\x13\x80\x80\x80\x80\x80\x00\x03\x00\x00\x00\x00\x05\x80\x05\x80\x00\a\x00!\x00=\x00\x00\x00\x14\x06\"&462\x01\x16\a\x06+\x01\"&'&\x00'.\x01=\x01476;\x01\x16\x04\x17\x16\x12\x05\x16\a\x06+\x01\"&'&\x02\x00$'.\x01=\x01476;\x01\f\x01\x17\x16\x12\x01\x80p\xa0pp\xa0\x02p\x02\x13\x12\x1d\x87\x19$\x02\x16\xfe\xbb\xe5\x19!\x15\x11\x1a\x05\xa0\x01$qr\x87\x02\r\x02\x14\x12\x1c\x8f\x1a%\x01\f\xb2\xfe\xe3\xfe}\xd7\x19#\x14\x12\x1a\x03\x01\x06\x01ߺ\xbb\xd6\x01\x10\xa0pp\xa0p\xfe\xc5\x1c\x14\x15!\x19\xe5\x01E\x16\x02$\x19\x87\x1d\x12\x11\r\x87rq\xfeܢ\x1b\x14\x14#\x19\xd7\x01\x83\x01\x1d\xb2\r\x01%\x19\x8f\x1c\x12\x12\rֻ\xba\xfe!\x00\x05\x00\x00\x00\x00\x06\x00\x05\x00\x00\a\x00\x0f\x00\x1f\x00)\x00?\x00\x00\x00\x14\x06\"&462\x04\x14\x06\"&462\x17\x114&#!\"\x06\x15\x11\x14\x163!26\x01!\x03.\x01#!\"\x06\a\x01\x11\x14\x06#!\"&5\x1147\x13>\x013!2\x16\x17\x13\x16\x04\x10/B//B\x01//B//B\x9f\x13\r\xfb@\r\x13\x13\r\x04\xc0\r\x13\xfb2\x04\x9c\x9d\x04\x18\x0e\xfc\xf2\x0e\x18\x04\x04\xb1^B\xfb@B^\x10\xc5\x11\\7\x03\x0e7\\\x11\xc5\x10\x01aB//B//B//B/\xf0\x01@\r\x13\x13\r\xfe\xc0\r\x13\x13\x01\xed\x01\xe2\r\x11\x11\r\xfd~\xfe\xc0B^^B\x01@\x192\x02^5BB5\xfd\xa22\x00\x02\x00\x00\xff\x83\a\x00\x05\x80\x00.\x004\x00\x00\x012\x16\x14\x06#\x11\x14\x06#\x00%\x0e\x01\x16\x17\x0e\x01\x1e\x02\x17\x0e\x01&'.\x0467#\"&=\x01463! \x012\x16\x15\x03\x11\x00\x05\x11\x04\x06\x805KK5L4\xfe_\xfeu:B\x04&\x14\x06\x121/&\x1d\xa5\xac.\a-\x13\x1b\x03\n\x11zB^^B\x01\xe0\x01\xb3\x01\xcd4L\x80\xfev\xfe\x8a\x01y\x03\x80KjK\xfe\x804L\x01[!\x13^k'!A3;)\x1e:2\x1b*\x17\x81\x0454\x127&5462\x16\x15\x14\a\x16\x12\x15\x14\x1e\x03\x03\x90\x10;U gI\xfdv\x05\x14\xfe\xf60Z\x99\xba\x99Z0\x04\xc0L4\xfe@\x96Ԗ\xfe@4L2RX='\xea\xbe\b8P8\b\xbe\xea'=XR\xb0 U;\x10\x10Ig\x010\x01,\x02\x143lb??bl3\xfd\xec\xfe\xd44Lj\x96\x96jL4*\\\x93\xaa\xf2\x8b\x98\x01\x05\x1c\x13\x14(88(\x14\x13\x1c\xfe\xfb\x98\x8b\xf2\xaa\x93\\\x00\x00\x00\x01\x00\x02\xff\x80\x05\xfe\x05}\x00I\x00\x00\x01\x17\x16\a\x06\x0f\x01\x17\x16\a\x06/\x01\a\x06\a\x06#\"/\x01\a\x06'&/\x01\a\x06'&?\x01'&'&?\x01'&76?\x01'&76\x1f\x017676\x1f\x0176\x17\x16\x1f\x0176\x17\x16\x0f\x01\x17\x16\x17\x16\a\x05`\x8a\x1e\n\f(\xbc5\f\x1f\x1d)\xba0\n)\f\a\x1f\x14\x87\x87\x1c*)\n0\xba)\x1d\x1f\f5\xbc(\f\n\x1e\x8a\x8a\x1e\n\f(\xbc5\f\x1f\x1d)\xba0\n))\x1d\x87\x87\x1d))\n0\xba)\x1d\x1f\f5\xbc(\f\n\x1e\x02\x80\x87\x1c*)\n0\xba)\x1d\x1f\f5\xbc(\f\x02\x16\x8a\x8a\x1e\n\v)\xbc5\f\x1f\x1d)\xba0\n)*\x1c\x87\x87\x1c*)\n0\xba)\x1d\x1f\f5\xbc)\n\f\x1f\x8b\x8b\x1e\v\n)\xbc5\f\x1f\x1d)\xba0\n)*\x1c\x00\x03\x00\x00\xff\x80\a\x00\x05\x80\x00\a\x005\x00h\x00\x00$4&\"\x06\x14\x162\x014&#!4>\x0254&#\"\a\x06\a\x06\a\x06\a\x06+\x01\x1132\x1e\x013254'>\x014'654&'!267\x14\x06+\x01\x06\a\x16\x15\x14\a\x16\x06#\"'&#!\"&5\x11463!2>\x05767>\x0432\x16\x15\x14\a!2\x16\x01\x00&4&&4\x05\xa6N2\xfd\xc0\x1e$\x1eYG\x18B\x18\r(HG\x1eEG H\xbe\xc5Q\xbd\x05\x1e#\x125\x14\x0f\x01K4L\x80\x97i\xa9\x04!\x03<\x01\xac\x8d\x85\xbd\xa4;\xfe\xe05KK5\x01 \n\x17\x18\x15\x1b\x0e\x18\x02A#\r(\"/?&}\xa3\x16\x01vh\x98\xa64&&4&\x02\x803M\x1495S+C=\x8b,\x15@QQ\x199\xfd\x80@@\xa7\x1a\x1e\x10IJ 2E\x19=\x11L5i\x98>9\x15\x16eM\x8b\xa1E;K5\x02\x805K\t\x13\x11\x1c\x0f\x1c\x03J7\x15R>@#\x86zD<\x98\x00\x00\x03\x00\x00\xff\x80\a\x00\x05\x80\x005\x00=\x00q\x00\x00%3\x11#\".\x02'&'&'&'.\x04#\"\x06\x15\x14\x1e\x02\x15!\"\x06\x15\x14\x163!\x0e\x01\x15\x14\x17\x06\x14\x16\x17\x06\x15\x14\x1632>\x01$4&\"\x06\x14\x162\x13\x11\x14\x06#!\"\a\x06#\"&?\x01&547&'#\"&5463!&54632\x1e\x03\x17\x16\x17\x1e\x063!2\x16\x05` #A<(\x1d\b\x04H(\x0e\x18\x01\x13\x12\x16\x15\bGY\x1e$\x1e\xfd\xc02NL4\x01K\x0f\x145\x12#\x1e\x04aWTƾ\x01h&4&&4\xa6K5\xfe\xe0;\xa4\xbe\u007f\x8e\xb0\x01\x01=\x03!\x04\xa9i\x97\x98h\x01v\x16\xa3}&?/\"(\r#A\x02\x18\x0e\x1b\x15\x18\x17\n\x01 5K\x80\x02\x80\x182*!\t\x05Q@\x16.\x03'!&\x17=C+S59\x14M34L\x11=\x19E2 JI\x10\x18 UR@@&4&&4&\x02\x80\xfd\x805K;E\x9b\x8c\x05Lf\x16\x159>\x98ig\x98R\x157J\x03\x1c\x0f\x1c\x11\x13\tK\x00\x00\x00\x03\x00\x00\xff\x00\x06\x00\x06\x00\x00\a\x005\x00h\x00\x00\x044&\"\x06\x14\x162\x134#\"\a.\x01\"\a&#\"\x06\a\x114&#\"\x06\x15\x11\".\x02#\"\x06\x15\x14\x17\x16\x17\x16\x17\x16\x17\x16\x1d\x01!54>\x017\x14\a\x06\x15\x11\x14\x06#!\"&5\x114.\x05'&'.\x0454632\x17\x114632\x16\x1d\x01\x16\x17632\x176\x16\x05\x00&4&&4\xa6\xa7\x1a\x1e\x10IJ 2E\x19=\x11L43M\x1495S+C=\x8b,\x15@QQ\x199\x02\x80@@\x80E;K5\xfd\x805K\t\x13\x11\x1c\x0f\x1c\x03J7\x15R>@#\x86zD<\x98gi\x98>9\x15\x16eM\x8b\xa1Z4&&4&\x03<\xbd\x05\x1e#\x125\x14\x0f\x01K4LN2\xfd\xc0\x1e$\x1eYG\x18B\x18\r(HG\x1eEG H\xbe\xc5V\x85\xbd\xa4;\xfe\xe05KK5\x01 \n\x17\x18\x15\x1b\x0e\x18\x02A#\r(\"/?&}\xa3\x16\x01vh\x98\x97i\xa9\x04!\x03<\x01\xac\x00\x00\x00\x03\x00\x00\xff\x00\x06\x00\x06\x00\x004\x00<\x00p\x00\x00\x014.\x01=\x01!\x15\x14\x0e\x02\a\x06\a\x06\a\x06\a\x0e\x04\x15\x14\x1632>\x023\x11\x14\x163265\x11\x16327\x16267\x16326\x024&\"\x06\x14\x162\x01\x14\x06/\x01\x06#\"'\x06\a\x15\x14\x06#\"&5\x11\x06#\"&54>\x03767>\x065\x11463!2\x16\x15\x11\x14\x17\x16\x05\x80@@\xfd\x80\x182*!\t\x05Q@\x16.\x03'!&\x17=C+S59\x14M34L.9E2 JI\x10\x18 UR\x80&4&&4\x01&\x9b\x8c\x05Lf\x16\x156A\x98ig\x986Jy\x87#@>R\x157J\x03\x1c\x0f\x1c\x11\x13\tK5\x02\x805K;E\x02@TƾH #A<(\x1d\b\x04H(\x0e\x18\x01\x13\x12\x16\x15\bGY\x1e$\x1e\xfd\xc02NL4\x01K#5\x12#\x1e\x04a\x03=4&&4&\xfdD\x8e\xb0\x01\x01=\x03\x1e\a\xa9i\x97\x98h\x01v\x16\xa3}&?/\"(\r#A\x02\x18\x0e\x1b\x15\x18\x17\n\x01 5KK5\xfe\xe0;\xa4\xbe\x00\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x1f\x00+\x00\x00\x0154&#!764/\x01&\"\a\x01\a\x06\x14\x1f\x01\x01\x162?\x0164/\x01!26\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x05\x00&\x1a\xfe\n\xbd\x13\x13[\x126\x12\xfe\x96[\x12\x12[\x01j\x126\x12[\x12\x12\xbd\x01\xf6\x1a&\x01\x00\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02@\x80\x1a&\xbd\x134\x13[\x12\x12\xfe\x96[\x126\x12[\xfe\x96\x12\x12[\x126\x12\xbd&\x01+\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x1f\x00+\x00\x00\x004/\x01\x01&\"\x0f\x01\x06\x14\x1f\x01!\"\x06\x1d\x01\x14\x163!\a\x06\x14\x1f\x01\x1627\x017$\x10\x02\x04 $\x02\x10\x12$ \x04\x05\x05\x12[\xfe\x96\x126\x12[\x12\x12\xbd\xfe\n\x1a&&\x1a\x01\xf6\xbd\x13\x13[\x126\x12\x01j[\x01\r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02e6\x12[\x01j\x12\x12[\x126\x12\xbd&\x1a\x80\x1a&\xbd\x134\x13[\x12\x12\x01j[\xfe\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x1f\x00+\x00\x00\x004'\x01'&\"\x0f\x01\x01\x06\x14\x1f\x01\x162?\x01\x11\x14\x16;\x01265\x11\x17\x162?\x01$\x10\x02\x04 $\x02\x10\x12$ \x04\x05\x04\x12\xfe\x96[\x126\x12[\xfe\x96\x12\x12[\x126\x12\xbd&\x1a\x80\x1a&\xbd\x134\x13[\x01\x0e\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02f6\x12\x01j[\x12\x12[\xfe\x96\x126\x12[\x12\x12\xbd\xfe\n\x1a&&\x1a\x01\xf6\xbd\x13\x13[\xfd\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x1f\x00+\x00\x00\x004/\x01&\"\x0f\x01\x114&+\x01\"\x06\x15\x11'&\"\x0f\x01\x06\x14\x17\x01\x17\x162?\x01\x01\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x05\x04\x12[\x126\x12\xbd&\x1a\x80\x1a&\xbd\x134\x13[\x12\x12\x01j[\x126\x12[\x01j\x01\x0e\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02d6\x12[\x12\x12\xbd\x01\xf6\x1a&&\x1a\xfe\n\xbd\x13\x13[\x126\x12\xfe\x96[\x12\x12[\x01j\x00\xff\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\v\x01\xd8\x02\x18\x00\x00\x00 \x04\x12\x10\x02\x04 $\x02\x10\x12\x01\x0e\x01\a2>\x01767676\x17&67>\x01?\x01\x06&'\x14\a4&\x06'.\x02'.\x01'.\x03\"\x0e\x01#&\x0e\x02\a\x0e\x01\a6'&\a6&'3.\x02'.\x01\a\x06\x1e\x01\x15\x16\x06\x15\x14\x16\a\x0e\x01\a\x06\x16\x17\x16\x0e\x02\x0f\x01\x06&'&'&\a&'&\a6'&\a>\x01567>\x02#\x167>\x0176\x1e\x013\x166'\x16'&'&\a\x06\x17&\x0e\x01'.\x01'\"\a6&'6'.\x01\a\x0e\x01\x1e\x02\x17\x16\a\x0e\x02\a\x06\x16\a.\x01'\x16/\x01\"\x06&'&76\x17.\x01'\x06\a\x167>\x0176\x177\x16\x17&\a\x06\a\x16\a.\x02'\"\a\x06\a\x16\x17\x1e\x027\x16\a6\x17\x16\x17\x16\a.\x01\a\x06\x167\"\x06\x14\a\x17\x06\x167\x06\x17\x16\x17\x1e\x02\x17\x1e\x01\x17\x06\x16\a\"\x06#\x1e\x01\x17\x1e\x0276'&'.\x01'2\x1e\x02\a\x06\x1e\x02\x17\x1e\x01#2\x16\x17\x1e\x01\x17\x1e\x03\x17\x1e\x01\x17\x162676\x16\x17\x167\x06\x1e\x02\x17\x1e\x01\x1767\x06\x16765\x06'4.\x026326&'.\x01'\x06&'\x14\x06\x15\"'>\x017>\x03&\a\x06\a\x0e\x02\a\x06&'.\x0154>\x01'>\x017>\x01\x1667&'&#\x166\x17\x1674&7\x167\x1e\x01\x17\x1e\x0267\x16\x17\x16\x17\x16>\x01&/\x0145'.\x0167>\x0276'27\".\x01#6'>\x017\x1676'>\x017\x16647>\x01?\x016#\x1676'6&'6\x1676'&\x0367.\x01'&'6.\x02'.\x03\x06#\a\x0e\x03\x17&'.\x02\x06\a\x0e\x01\a&6'&\x0e\x04\a\x0e\x01\a.\x015\x1e\x01\x17\x16\a\x06\a\x06\x17\x14\x06\x17\x14\x02/\x01\xa2\x01a\xce\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x03D\x02\x0f\x06\x02\x05\x05\x01\x06\x10\x0e&\"\x11\x02\x17\x03\x03\x18\x03\x02\f\v\x01\x06\t\x0e\x02\n\n\x06\x01\x02\x0f\x02\x01\x03\x03\x05\x06\b\a\x01\x03\x06\x03\x06\x02\x03\v\x03\x0f\x10\n\x06\t\x03\a\x05\x01\x0f\x14\x03\b4\a\x05\x01\a\x01\r\x1c\x04\x03\x1a\x03\x05\a\a\x02\x01\x06\x05\x04\x03\v\x13\x04\a\t\x17\x06\x05$\x19!\x06\x06\a\f\x03\x02\x03\t\x01\f\a\x03#\x0f\x05\r\x04\t\n\x13\x05\x0e\x03\t\f\t\x04\x04\f\x0f\b\n\x01\x11\x10\b\x01\t\x05\b\b\x03\x1c\n\x13\x1b\a\x1b\x06\x05\x01\v\n\r\x02\x0e\x06\x02\r\n\x01\x03\x06\x05\x05\b\x03\a \n\x04\x18\x11\x05\x04\x04\x01\x03\x04\x0e\x03.0\x06\x06\x05\x10\x02\"\b\x05\x0e\x06\a\x17\x14\x02\a\x02\x04\x0f\x0e\b\x10\x06\x92Y\a\x05\x04\x02\x03\n\t\x06\x01+\x13\x02\x03\r\x01\x10\x01\x03\a\a\a\x05\x01\x02\x03\x11\r\r!\x06\x02\x03\x12\f\x04\x04\f\b\x02\x17\x01\x01\x03\x01\x03\x19\x03\x01\x02\x04\x06\x02\x1a\x0f\x02\x03\x05\x02\x02\b\t\x06\x01\x03\n\x0e\x14\x02\x06\x10\b\t\x16\x06\x05\x06\x02\x02\r\f\x14\x03\x05\x1b\b\n\f\x11\x05\x0f\x1c\a$\x13\x02\x05\v\a\x02\x05\x1a\x05\x06\x01\x03\x14\b\x0e\x1f\x12\x05\x03\x02\x02\x04\t\x02\x06\x01\x01\x14\x02\x05\x16\x05\x03\r\x02\x01\x03\x02\x01\t\x06\x02\v\f\x13\a\x01\x04\x06\x06\a\"\a\r\x13\x05\x01\x06\x03\f\x04\x02\x05\x04\x04\x01\x01\x03\x03\x01\a+\x06\x0f\a\x05\x02\x05\x18\x03\x19\x05\x03\b\x03\a\x05\n\x02\v\b\a\b\x01\x01\x01\x01\x01\x0f\a\n\n\x01\x0e\x11\x04\x15\x06\a\x04\x01\b\a\x01\t\a\x05\x05\x05\t\f\b\a\x05\x1f\x03\a\x02\x03\x04\x16\x02\x11\x03\x03\x12\r\n\x10\x03\f\t\x03\x11\x02\x0f\x16\x11\xbdΑ\x03\x13\x03\x12\x06\x01\a\t\x10\x03\x02\n\x04\v\x06\a\x03\x03\x05\x06\x02\x01\x15\x0f\x05\f\t\v\x06\x05\x02\x01\a\x0e\x05\x03\x0f\t\x0e\x04\r\x02\x03\x06\x02\x02\x13\x02\x04\x03\a\x13\x1b\x02\x04\x10\x10\x01\x05\x80\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xfe\xc5\x01\x11\x01\n\f\x01\a\b\x06\x06\b\x13\x02\x16\x01\x02\x05\x05\x16\x01\x10\r\x02\x06\a\x02\x04\x01\x03\t\x18\x03\x05\f\x04\x02\a\x06\x05\n\n\x02\x01\x01\x05\x01\x02\x02\x01\x05\x06\x04\x01\x04\x10\x06\x04\t\b\x02\x05\t\x04\x06\t\x13\x03\x06\x0e\x05\a\x11\r\b\x10\x04\b\x15\x06\x02\x04\x05\x03\x02\x02\x05\x16\x0f\x19\x05\b\t\r\r\t\x05\x01\x0e\x0f\x03\x06\x17\x02\r\n\x01\x0f\f\x04\x0f\x05\x18\x05\x06\x01\n\x01\x18\b\x01\x12\a\x02\x04\t\x04\x04\x01\x17\f\v\x01\x19\x01\x0f\b\x0e\x01\f\x0f\x04\x02\x05\a\t\a\x04\x04\x01\n\x04\x01\x05\x04\x02\x04\x14\x04\x05\x19\x04\t\x03\x01\x04\x02\a\b\f\x04\x02\x03\r\x02\x0f\x1a\x01\x02\x02\t\x01\x0e\a\x05\x10\t\x04\x03\x06\x06\f\x06\x03\x0e\b\x01\x01P\x8e\a\x01\x01\x10\x06\x06\b\v\x01\x1c\x11\x04\v\a\x02\x0e\x03\x05\x1b\x01 '\x04\x01\f-\x03\x03(\b\x01\x02\v\t\x06\x05#\x06\x06\x1c\t\x02\a\x0e\x06\x03\x0e\b\x02\x14*\x19\x04\x05\x15\x04\x03\x04\x04\x01\a\x15\x10\x16\x02\x06\x1b\x15\t\b$\x06\a\r\x06\n\x02\x02\x11\x03\x04\x05\x01\x02\"\x04\x13\b\x01\r\x12\v\x03\x06\x12\x06\x04\x05\b\x18\x02\x03\x1d\x0f!\x01\t\b\t\x06\a\x12\x04\b\x18\x03\t\x02\b\x01\t\x02\x01\x03\x1d\b\x04\x10\r\f\a\x01\x01\x13\x03\x0f\b\x03\x03\x02\x04\b*\x10\n!\x11\x10\x02\x0f\x03\x01\x01\x01\x04\x04\x01\x02\x03\x03\t\x06\v\r\x01\x11\x05\x1b\x12\x03\x04\x03\x02\a\x02\x03\x05\x0e\n(\x04\x03\x02\x11\v\a\b\t\t\b\x03\x12\x13\t\x01\x05\b\x04\x13\x10\t\x06\x04\x05\v\x03\x10\x02\f\n\b\b\a\a\x06\x02\b\x10\x04\x05\b\x01\v\x04\x02\r\v\t\x06\a\x02\x01\x01\x02\n\x06\x05\xfc\x82$\x99\x03\x03\x02\a\x01\a\f\x06\n\x02\x02\b\x03\x06\x02\x01\x01\x03\x03\x03\x01\x11\x05\x01\t\x05\x02\x06\x05\x14\x03\x05\x19\x06\x06\x03\x06\v\x02\t\x03\x04\x10\x03\x04\x05\x03\n2\r\x1f\x11\x19\x0f\x16\x04\a\x1b\b\x06\x00\x00\x03\x00\x15\xff\x15\x06~\x05\x80\x00\a\x00\x15\x00/\x00\x00$4&\"\x06\x14\x162\t\x01\x06#\"/\x01&547\x01\x1e\x01\x01\x14\a\x0e\x01#\"\x00\x10\x0032\x16\x17\x16\x14\a\x05\x15\x17>\x0232\x16\x01\x80&4&&4\x02\xaa\xfdV%54'j&&\x02\xa9'\x97\x02\xdc\x17/덹\xfe\xf9\x01\a\xb9:\u007f,\x10\x10\xfe\xdb\xc1\x05\x94{\t\x0f\x11&4&&4&\x01\xe4\xfdV%%l$65&\x02\xa9b\x97\x01\x8c'C\x86\xa7\x01\a\x01r\x01\a!\x1e\v\"\v\xa9\xe0k\x03[G\x14\x00\x00\x00\x06\x00\x00\x00\x00\a\x00\x05\x80\x00\x03\x00\a\x00\v\x00\x1b\x00+\x00;\x00\x00%!5!\x01!5!\x01!5!\x01\x11\x14\x06#!\"&5\x11463!2\x16\x19\x01\x14\x06#!\"&5\x11463!2\x16\x19\x01\x14\x06#!\"&5\x11463!2\x16\x04\x00\x02\x80\xfd\x80\xfe\x80\x04\x00\xfc\x00\x02\x80\x01\x80\xfe\x80\x02\x00&\x1a\xf9\x80\x1a&&\x1a\x06\x80\x1a&&\x1a\xf9\x80\x1a&&\x1a\x06\x80\x1a&&\x1a\xf9\x80\x1a&&\x1a\x06\x80\x1a&\x80\x80\x01\x80\x80\x01\x80\x80\xfc@\xff\x00\x1a&&\x1a\x01\x00\x1a&&\x01\xe6\xff\x00\x1a&&\x1a\x01\x00\x1a&&\x01\xe6\xff\x00\x1a&&\x1a\x01\x00\x1a&&\x00\x00\x01\x00\x05\xff\x80\x05{\x05\x00\x00\x15\x00\x00\x01\x16\a\x01\x11\x14\a\x06#\"'\x01&5\x11\x01&763!2\x05{\x11\x1f\xfe\x13'\r\f\x1b\x12\xff\x00\x13\xfe\x13\x1f\x11\x11*\x05\x00*\x04\xd9)\x1d\xfe\x13\xfd\x1a*\x11\x05\x13\x01\x00\x13\x1a\x01\xe6\x01\xed\x1d)'\x00\x00\x00\x04\x00\x00\x00\x00\a\x00\x06\x00\x00\x03\x00\x17\x00\x1b\x00/\x00\x00\x01!5!\x01\x11\x14\x06#!\"&5\x11!\x15\x14\x163!26=\x01#\x15!5\x01\x11!\x11463!5463!2\x16\x1d\x01!2\x16\x02\x80\x02\x00\xfe\x00\x04\x80^B\xfa@B^\x02\xa0&\x1a\x01@\x1a&`\xff\x00\x04\x00\xf9\x00^B\x01`8(\x02@(8\x01`B^\x05\x00\x80\xfd\x00\xfe B^^B\x01\xe0\xa0\x1a&&\x1a\xa0\x80\x80\x01\xe0\xfe\x80\x01\x80B^\xa0(88(\xa0^\x00\x00\x01\x00\x00\xff\x80\x06\x00\x05\x80\x00G\x00\x00\t\x0276\x17\x16\x15\x11\x14\x06#!\"'&?\x01\t\x01\x17\x16\a\x06#!\"&5\x11476\x1f\x01\t\x01\a\x06#\"'&5\x11463!2\x17\x16\x0f\x01\t\x01'&763!2\x16\x15\x11\x14\a\x06#\"'\x05\x03\xfe\x9d\x01c\x90\x1d)'&\x1a\xfe@*\x11\x11\x1f\x90\xfe\x9d\xfe\x9d\x90\x1f\x11\x11*\xfe@\x1a&('\x1e\x90\x01c\xfe\x9d\x90\x13\x1a\f\f(&\x1a\x01\xc0*\x11\x11\x1f\x90\x01c\x01c\x90\x1f\x11\x11*\x01\xc0\x1a&'\r\f\x1a\x13\x03\xe3\xfe\x9d\xfe\x9d\x90\x1f\x11\x11*\xfe@\x1a&('\x1e\x90\x01c\xfe\x9d\x90\x1e'(&\x1a\x01\xc0*\x11\x11\x1f\x90\x01c\x01c\x90\x13\x05\x11*\x01\xc0\x1a&('\x1e\x90\xfe\x9d\x01c\x90\x1e'(&\x1a\xfe@*\x11\x05\x13\x00\x00\x06\x00\x00\xff\x00\a\x80\x06\x00\x00\x11\x001\x009\x00A\x00S\x00[\x00\x00\x01\x06\a#\"&5\x1032\x1e\x01327\x06\x15\x14\x01\x14\x06#!\"&54>\x0532\x1e\x022>\x0232\x1e\x05\x00\x14\x06\"&462\x00\x10\x06 &\x106 \x01\x14\x06+\x01&'654'\x1632>\x0132\x02\x14\x06\"&462\x02Q\xa2g\x86Rp|\x06Kx;CB\x05\x04\x80\x92y\xfc\x96y\x92\a\x15 6Fe=\nBP\x86\x88\x86PB\n=eF6 \x15\a\xfc\x00\x96Ԗ\x96\xd4\x03V\xe1\xfe\xc2\xe1\xe1\x01>\x03!pR\x86g\xa2Q\x05BC;xK\x06|\x80\x96Ԗ\x96\xd4\x02\x80\x05{QN\x01a*+\x17%\x1d\x8b\xfd\x0ex\x8b\x8bx5eud_C(+5++5+(C_due\x052Ԗ\x96Ԗ\xfe\x1f\xfe\xc2\xe1\xe1\x01>\xe1\xfd\x9fNQ{\x05u\x8b\x1d%\x17+*\x01jԖ\x96Ԗ\x00\x00\x00\x00\x03\x00\x10\xff\x90\x06p\x05\xf0\x00!\x00C\x00i\x00\x00\x014/\x01&#\"\a\x1e\x04\x15\x14\x06#\".\x03'\x06\x15\x14\x1f\x01\x1632?\x016\x014/\x01&#\"\x0f\x01\x06\x15\x14\x1f\x01\x16327.\x0454632\x1e\x03\x176\x00\x14\x0f\x01\x06#\"/\x01&547'\x06#\"/\x01&4?\x01632\x1f\x01\x16\x15\x14\a\x17632\x1f\x01\x05\xb0\x1c\xd0\x1c(*\x1e\x03 \v\x13\a8(\x0f\x19\x1a\f\x1f\x03!\x1c\xce\x1b)(\x1c\x93\x1c\xfdA\x1c\xce\x1c('\x1d\x93\x1c\x1c\xd0\x1b)*\x1e\x03 \v\x13\a8(\x0f\x19\x1a\f\x1f\x03!\x03\u007fU\x93SxyS\xceSXXVzxT\xd0TU\x93SxyS\xceSXXVzxT\xd0\x01@(\x1c\xd0\x1c \x03\x1f\f\x1a\x19\x0f(8\a\x13\v \x03\x1f*(\x1c\xcf\x1b\x1a\x92\x1c\x02\xe8(\x1c\xcf\x1c\x1b\x92\x1c'(\x1c\xd0\x1b\x1f\x03\x1f\f\x1a\x19\x0f(8\a\x13\v \x03\x1f\xfd\xe1\xf0S\x92SU\xcfSx{VXXT\xd0T\xf0S\x92SU\xcfSx{VXXT\xd0\x00\x01\x00\x00\x00\x00\a\x80\x05\x80\x00\x1b\x00\x00\x01\x14\x06#!\"\x005467&54\x0032\x04\x17632\x16\x15\x14\a\x1e\x01\a\x80\xe1\x9f\xfb\xc0\xb9\xfe\xf9\x8et\x02\x01,Ԟ\x01\x01;F`j\x96)\x81\xa8\x01\x80\x9f\xe1\x01\a\xb9\x84\xdb6\x1c\x0f\xd4\x01,\xb0\x8e>\x96jK?\x1e\xd1\x00\x02\x00s\xff\x80\x06\r\x05\x80\x00\x17\x00!\x00\x00%\x16\x06#!\"&7\x01\x11#\"&463!2\x16\x14\x06+\x01\x11\x05\x01!\x01'5\x11#\x11\x15\x05\xf78Ej\xfb\x80jE8\x01\xf7@\x1a&&\x1a\x02\x00\x1a&&\x1a@\xfe\xec\xfe\xf0\x02\xc8\xfe\xf0\x14\x80XY\u007f\u007fY\x03\x19\x01\x8f&4&&4&\xfeqD\xfeS\x01\xad\x1f%\x01\x8f\xfeq%\x00\x00\x00\x00\a\x00\x01\xff\x80\a\x00\x05\x00\x00\a\x00N\x00\\\x00j\x00x\x00\x86\x00\x8c\x00\x00\x002\x16\x14\x06\"&4\x05\x01\x16\a\x06\x0f\x01\x06#\"'\x01\a\x06\a\x16\a\x0e\x01\a\x06#\"'&7>\x017632\x176?\x01'&'\x06#\"'.\x01'&67632\x17\x1e\x01\x17\x16\a\x16\x1f\x01\x01632\x1f\x01\x16\x17\x16\a\x056&'&#\"\a\x06\x16\x17\x1632\x03>\x01'&#\"\a\x0e\x01\x17\x1632\x01\x1754?\x01'\a\x0e\x01\a\x0e\x01\a\x1f\x01\x01'\x01\x15\a\x17\x16\x17\x1e\x01\x1f\x01\x017\x01\a\x06\a\x03\xa64&&4&\x01l\x01\xfb\x1c\x03\x05\x1e\x80\r\x10\x11\x0e\xfdNn\b\x04\x0e\x04\abS\x84\x91\x88VZ\v\abR\x84\x92SD\t\rzz\r\tDS\x92\x84Rb\a\x05)+U\x89\x91\x84Sb\a\x04\x0e\x04\bn\x02\xb2\x0e\x11\x10\r\x80\x1e\x05\x03\x1c\xfb\\.2Q\\dJ'.2Q\\dJ.Q2.'Jd\\Q2.'Jd\x01\x0e`!\x0eO\x1a\x03\x0e\x05\x02\x04\x01\xd7`\x02\xe0\x80\xfd\x00\xa0\t\x02\x05\x04\x0e\x04\x1a\x03`\x80\xfd\xf8\xb1\x02\v\x02\x80&4&&4\x1a\xfer\x14$#\x10@\a\b\x01\x83B\x04\x0110M\x8d5TNT{L\x8e5T\x1f\r\tII\t\r\x1fT5\x8eL;l'OT4\x8eM01\x01\x04B\x01\x83\b\a@\x10#$\x14\x8a*\x843;$*\x843;\xfd;3\x84*$;3\x84*$\x02\xa0:\v$\x14\b/\x1a\x03\x10\x04\x02\x03\x01\xe9 \x02@@\xfeQq`\b\x02\x04\x04\x10\x04\x1a\xfe\xc0@\x01\x98\x8a\x03\x04\x00\x00\x05\x00\x00\xff\x00\a\x00\x06\x00\x00\x1f\x00\"\x00%\x003\x00<\x00\x00\x012\x16\x15\x11\x14\x06#!\"&5\x11!\"&5\x11467\x01>\x013!2\x16\x15\x1163\a\x01!\t\x01!\x13\x01\x11!\x11\x14\x06#!\x11!\x1146\x01\x11!\x11\x14\x06#!\x11\x06\xa0(88(\xfc@(8\xfd\xe0(8(\x1c\x01\x98\x1c`(\x01\xa0(8D<\x80\xfe\xd5\x01+\xfd\x80\xfe\xd5\x01+\xc4\x01<\xfe\x808(\xfe`\x02\x00(\x03\xd8\xfe\x808(\xfe`\x04\x808(\xfb@(88(\x01 8(\x02\xa0(`\x1c\x01\x98\x1c(8(\xfe\xb8(\xd5\xfe\xd5\x02\xab\xfe\xd5\xfe\xa4\x01<\x01\xa0\xfe`(8\xfd\x80\x01\x00(`\xfc\xf8\x04\x80\xfe`(8\xfd\x80\x00\x00\x00\x01\x00\x04\xff\x84\x05|\x05|\x00?\x00\x00%\x14\x06#\"'\x01&54632\x17\x01\x16\x15\x14\x06#\"'\x01&#\"\x06\x15\x14\x17\x01\x1632654'\x01&#\"\x06\x15\x14\x17\x01\x16\x15\x14\x06#\"'\x01&54632\x17\x01\x16\x05|\x9eu\x87d\xfc\xf7qܟ\x9es\x02]\n=\x10\r\n\xfd\xa2Ofj\x92L\x03\b?R@T?\xfd\xbb\x1a\"\x1d&\x19\x01\x9a\n>\x10\f\n\xfef?rRX=\x02Ed\x97u\x9ed\x03\bs\x9c\x9f\xdeq\xfd\xa2\n\f\x10=\n\x02_M\x96jiL\xfc\xf7?T@R?\x02E\x18&\x1d \x1b\xfef\n\f\x10>\n\x01\x9a=XRr?\xfd\xbbb\x00\x04\x00\x00\xff\x80\x06\x00\x05\x80\x00\x03\x00!\x001\x00E\x00\x00)\x01\x11!\x013\x114&'\x01.\x01#\x11\x14\x06#!\"&5\x11#\x113\x11463!2\x16\x15\x01\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126\x05\x11\x14\x06#!\"&5\x11463!2\x16\x17\x01\x1e\x01\x01\x80\x03\x00\xfd\x00\x03\x80\x80\x14\n\xfe\xe7\n0\x0f8(\xfd\xc0(8\x80\x808(\x03@(8\xfe\x80\x13\r\xc0\r\x13\x13\r\xc0\r\x13\x02\x808(\xfa\xc0(88(\x03\xa0(`\x1c\x01\x18\x1c(\x01\x80\xfe\x80\x03\x80\x0e1\n\x01\x19\n\x14\xfe`(88(\x01\xa0\xfb\x00\x01\xa0(88(\x02\x00\x01@\r\x13\x13\r\xfe\xc0\r\x13\x13\x13\xfc`(88(\x05@(8(\x1c\xfe\xe8\x1c`\x00\x00\x00\x01\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x00\x01\x11\x14\x06#!\"&5\x11463!2\x16\x06\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x04`\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x00\x03\x00\x00\x00\x00\x06\x00\x05\x00\x00\x0f\x00\x1f\x00/\x00\x00%\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x06\x00&\x1a\xfa\x80\x1a&&\x1a\x05\x80\x1a&&\x1a\xfa\x80\x1a&&\x1a\x05\x80\x1a&&\x1a\xfa\x80\x1a&&\x1a\x05\x80\x1a&\xc0\x80\x1a&&\x1a\x80\x1a&&\x01\xe6\x80\x1a&&\x1a\x80\x1a&&\x01\xe6\x80\x1a&&\x1a\x80\x1a&&\x00\x06\x00\x00\xff\xc0\a\x00\x05@\x00\a\x00\x0f\x00\x1f\x00'\x007\x00G\x00\x00$\x14\x06\"&462\x12\x14\x06\"&462\x01\x15\x14\x06#!\"&=\x01463!2\x16\x00\x14\x06\"&462\x01\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x01\x80p\xa0pp\xa0pp\xa0pp\xa0\x05\xf0\x13\r\xfb@\r\x13\x13\r\x04\xc0\r\x13\xfa\x80p\xa0pp\xa0\x05\xf0\x13\r\xfb@\r\x13\x13\r\x04\xc0\r\x13\x13\r\xfb@\r\x13\x13\r\x04\xc0\r\x13Рpp\xa0p\x01\x90\xa0pp\xa0p\xfd\xa0\xc0\r\x13\x13\r\xc0\r\x13\x13\x03\xe3\xa0pp\xa0p\xfd\xa0\xc0\r\x13\x13\r\xc0\r\x13\x13\x01\xf3\xc0\r\x13\x13\r\xc0\r\x13\x13\x00\x00\x00\x00\x06\x00\x0f\xff\x00\a\x00\x05\xf7\x00\x1e\x00<\x00L\x00\\\x00l\x00|\x00\x00\x05\x14\x06#\"'7\x1632654\a'>\x0275\"\x06#\x15#5!\x15\a\x1e\x01\x13\x15!&54>\x0354&#\"\a'>\x0132\x16\x15\x14\x0e\x02\a35\x01\x15\x14\x06#!\"&=\x01463!2\x16\x01\x15!5346=\x01#\x06\a'73\x11\x01\x15\x14\x06#!\"&=\x01463!2\x16\x11\x15\x14\x06#!\"&=\x01463!2\x16\x01}mQjB919\x1d+i\x1a\b1$\x13\x10A\x10j\x01M_3<\x02\xfe\x96\x06/BB/\x1d\x19.#U\x18_:IdDRE\x01\u007f\x05\xea\x13\r\xfb@\r\x13\x12\x0e\x04\xc0\r\x13\xfa\x80\xfe\xb1k\x01\x02\b*G\x88j\x05\xec\x13\r\xfb@\r\x13\x12\x0e\x04\xc0\r\x13\x13\r\xfb@\r\x13\x13\r\x04\xc0\r\x13TP\\BX-\x1d\x1c@\b8\nC)\x12\x01\x025\x98Xs\fJ\x02@\x9f$\x123T4+,\x17\x19\x1b:;39SG2S.7\x19<\xfe\xc1\xc0\r\x13\x13\r\xc0\x0e\x12\x13\x03vcc)\xa1)\f\x11%L\u007f\xfel\xfe}\xc0\r\x13\x13\r\xc0\x0e\x12\x13\x01\xf3\xc0\r\x13\x13\r\xc0\r\x13\x13\x00\x00\x00\x00\x03\x00\x00\xff\x80\a\x00\x05\x80\x00\x0f\x005\x00e\x00\x00\x012\x16\x1d\x01\x14\x06#!\"&=\x01463%&'&5476!2\x17\x16\x17\x16\x17\x16\x15\x14\x0f\x01/\x01&'&#\"\a\x06\x15\x14\x17\x16\x17\x16\x17\x16\x17\x03!\x16\x15\x14\a\x06\a\x06\a\x06\a\x06#\"/\x01&'&=\x014'&?\x0157\x1e\x02\x17\x16\x17\x16\x17\x1632767654'&\x06\xe0\x0e\x12\x12\x0e\xf9@\x0e\x12\x12\x0e\x01\xc3\x1c\x170\x86\x85\x01\x042uBo\n\v\x0e\x05\fT\x0e25XzrDCBB\xd5Eh:%\xec\x01\x9b\a)\x170%HPIP{rQ\x8c9\x0f\b\x02\x01\x01\x02f\x0f\x1e\x0f\x05#-+>;I@KM-/Q\"\x02\x80\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12@#-bZ\xb5\x80\u007f\x13\f$&P{<\x12\x1b\x03\x06\x02\x958[;:XICC>\x14.\x1c\x18\xff\x00'5oe80#.0\x12\x15\x17(\x10\f\b\x0e\rl0\x1e&%,\x02\"J&\b9%$\x15\x16\x1b\x1a<=DTI\x1d\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00c\x00s\x00\x00\x13&/\x01632\x17\x163276727\a\x17\x15\x06#\"\a\x06\x15\x14\x16\x15\x17\x13\x16\x17\x16\x17\x16327676767654.\x01/\x01&'&\x0f\x01'73\x17\x167\x17\x16\x15\x14\a\x06\a\x06\a\x06\x15\x14\x16\x15\x16\x13\x16\a\x06\a\x06\a\x06\a\x06#\"'&'&'&5\x114'&\x0154&#!\"\x06\x1d\x01\x14\x163!260%\b\x03\r\x1b<4\x84\"VRt\x1e8\x1e\x01\x02<@<\x13\r\x01\x01\x0e\x06-#=XYhW8+0\x11$\x11\x15\a\x0f\x06\x04\x05\x13\"+d\x0e\x02T\xcdLx\x12\x06\x04-'I\x06\x0f\x03\b\x0e\x06\x15\x0f\x1a&JKkm\x92\xa7uw<=\x16\x10\x11\x19\x05V\x12\x0e\xfa@\x0e\x12\x12\x0e\x05\xc0\x0e\x12\x05!\x02\x02X\x01\x04\a\x03\x04\x01\x02\x0e@\t\t\x19\x0ev\r'\x06\xe5\xfe\xe8|N;!/\x1c\x12!$\x1c8:I\x9cOb\x93V;C\x15#\x01\x02\x03V\n\x03\r\x02&\r\a\x18\f\x01\v\x06\x0f\x1a\a(\v\x13\xfe\x87\xc3mL.A:9 !./KLwP\x9d\x01M\xbc\x19$\xfa\x82@\x0e\x12\x12\x0e@\x0e\x12\x12\x00\x00\n\x00\x00\x00\x00\x06\x80\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00o\x00\u007f\x00\x8f\x00\x9f\x00\x00%54&#!\"\x06\x1d\x01\x14\x163!26\x1154&#!\"\x06\x1d\x01\x14\x163!26\x0154&#!\"\x06\x1d\x01\x14\x163!26\x0154&#!\"\x06\x1d\x01\x14\x163!26\x0154&#!\"\x06\x1d\x01\x14\x163!26\x0154&#!\"\x06\x1d\x01\x14\x163!26\x0154&#!\"\x06\x1d\x01\x14\x163!26\x0154&#!\"\x06\x1d\x01\x14\x163!26\x1154&#!\"\x06\x1d\x01\x14\x163!26\x13\x11\x14\x06#!\"&5\x11463!2\x16\x02\x00\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\x02\x00\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\xfe\x00\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\x02\x00\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\x02\x00\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\xfe\x00\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\x02\x00\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\x80^B\xfa\xc0B^^B\x05@B^\xa0\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x01\x8e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\xfe\x8e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x03\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\xfe\x8e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\xfe\x8e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x03\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\xfe\x8e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x01\x8e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x01N\xfb\xc0B^^B\x04@B^^\x00\x00\x00\x06\x00\x1b\xff\x9b\x06\x80\x06\x00\x00\x03\x00\x13\x00\x1b\x00#\x00+\x003\x00\x00\t\x01'\x01$\x14\a\x01\x06\"/\x01&47\x0162\x1f\x01%\x17\x0f\x01/\x01?\x01\x01\x17\x0f\x01/\x01?\x01\x01\x17\x0f\x01/\x01?\x01\x01\x17\x0f\x01/\x01?\x01\x04\xa6\x01%k\xfe\xdb\x02*\x12\xfa\xfa\x126\x12\xc6\x12\x12\x05\x06\x126\x12\xc6\xfa\xcbbb\x1e\x1ebb\x1e\x01|\xc4\xc4<<\xc4\xc4<\x03\xdebb\x1e\x1ebb\x1e\xfd\x9ebb\x1e\x1ebb\x1e\x03\xbb\x01%k\xfe\xdb\xd56\x12\xfa\xfa\x12\x12\xc6\x126\x12\x05\x06\x12\x12Ƒ\x1e\x1ebb\x1e\x1eb\xfe\xfc<<\xc4\xc4<<\xc4\xfd^\x1e\x1ebb\x1e\x1eb\x02\x1e\x1e\x1ebb\x1e\x1eb\x00\x00\x00\x04\x00@\xff\x80\a\x00\x05\x00\x00\a\x00\x10\x00\x18\x00M\x00\x00$4&\"\x06\x14\x162\x01!\x11#\"\x0f\x01\x06\x15\x004&\"\x06\x14\x162\x01\x11\x14\x0e\x04&#\x14\x06\"&5!\x14\x06\"&5#\"\x06.\x045463\x114&>\x03?\x01>\x01;\x015463!2\x16\x02\x80LhLLh\xfe\xcc\x01\x80\x9e\r\t\xc3\t\x05\x00LhLLh\x01L\b\x13\x0e!\f'\x03\x96Ԗ\xfe\x80\x96Ԗ@\x03'\f!\x0e\x13\b&\x1a\x01\x01\x04\t\x13\r\xc6\x13?\x1b\xa0&\x1a\x04\x00\x1a&LhLLhL\x02\x80\x01\x00\t\xc3\t\r\xfd\xaehLLhL\x04\xc0\xfc\x00\x0f\x17\x0e\t\x03\x01\x01j\x96\x96jj\x96\x96j\x01\x01\x03\t\x0e\x17\x0f\x1a&\x01@\b6\x16/\x1b\"\r\xc6\x13\x1a\xc0\x1a&&\x00\x00\x00\x01\x00\x00\xff\x80\x06\x00\x05\x80\x00J\x00\x00\x00\x10\x02\x04#\"'6767\x1e\x0132>\x0154.\x01#\"\x0e\x03\x15\x14\x16\x17\x167>\x0176'&54632\x16\x15\x14\x06#\"&7>\x0254&#\"\x06\x15\x14\x17\x03\x06\x17&\x0254\x12$ \x04\x06\x00\xce\xfe\x9f\xd1ok;\x13\t-\x14j=y\xbehw\xe2\x8ei\xb6\u007f[+PM\x1e\b\x02\f\x02\x06\x113ѩ\x97\xa9\x89k=J\x0e\b%\x1762>V\x19c\x11\x04\xce\xfe\xce\x01a\x01\xa2\x01a\x03Q\xfe^\xfe\x9f\xce ]G\"\xb1'9\x89\xf0\x96r\xc8~:`}\x86Ch\x9e \f \a0\x06\x17\x14=Z\x97٤\x83\xaa\xeeW=#uY\x1f2BrUI1\xfe^Fk[\x01|\xe9\xd1\x01a\xce\xce\x00\x00\x01\x00\x00\xff\x80\x06\x00\x05\x80\x00L\x00\x00\x012\x16\x15\x11\x14\x06#!6767\x1e\x0132\x1254.\x02#\"\x0e\x03\x15\x14\x16\x17\x1667676'&54632\x16\x15\x14\x06#\"&7>\x0254&#\"\x06\x15\x14\x17\x03\x06\x17#\"&5\x11463\x04\xe0w\xa9\xa9w\xfd+U\x17\t,\x15i<\xb5\xe5F{\xb6jh\xb5}Z+OM\r\x15\x04\n\x05\x06\x112ϧ\x95\xa7\x87jX\x96բ\x81\xa8\xecW<\"uW\x1f1AqSH1\xfebd\x9a\xa9w\x03\xc0w\xa9\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x1b\x00'\x007\x00\x00\x014'!\x153\x0e\x03#\"&4632\x177&#\"\x06\x10\x16326%35#5#\x15#\x153\x153\x01\x11\x14\x06#!\"&5\x11463!2\x16\x03\x95\x06\xfe\x96\xd9\x03\x1b0U6c\x8c\x8cc\\=hl\x95\xa0\xe0ࠥ\xcb\x01Ymmnnnn\x01\x12\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x02w\x1a&\x84\x1846#\x8eȎ;ed\xe1\xfe\xc2\xe1\xd2wnnnnn\x02\x85\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x02\x00\x00\xff\xa3\t\x00\x05]\x00#\x00/\x00\x00\x01\x14\x02\x04#\"$&\x02\x10\x126$3 \x17\a&#\"\x0e\x01\x14\x1e\x0132>\x037!5!\x16%\x15#\x15#5#5353\x15\x05\x9d\xae\xfe\xbeЕ\xfe\xf0\xc4tt\xc4\x01\x10\x95\x01\x1e\xcd\xc7u\xaf{\xd1zz\xd1{S\x8bZC\x1f\x06\xfe`\x02\xb4\f\x03c\xd1\xd2\xd1\xd1\xd2\x02o\xd0\xfe\xbb\xb7t\xc4\x01\x10\x01*\x01\x10\xc4t\xc0\xbfq|\xd5\xfc\xd5|.EXN#\xfc??\xd2\xd1\xd1\xd2\xd1\xd1\x00\x00\x00\x04\x00\x00\x00\x00\a\x80\x05\x00\x00\f\x00\x1c\x00,\x00<\x00\x00\x01!5#\x11#\a\x17673\x11#$\x14\x0e\x02\".\x024>\x022\x1e\x01\x01\x11\"&5!\x14\x06#\x112\x16\x15!46\x13\x11\x14\x06#!\"&5\x11463!2\x16\x03\x00\x01\x80\x80r\x94M*\r\x02\x80\x02\x00*M~\x96~M**M~\x96~M\x02*j\x96\xfb\x80\x96jj\x96\x04\x80\x96\xea&\x1a\xf9\x00\x1a&&\x1a\a\x00\x1a&\x01\x80`\x01\xc0\x89P%\x14\xfe\xe0挐|NN|\x90\x8c\x90|NN|\xfe*\x02\x00\x96jj\x96\xfe\x00\x96jj\x96\x03@\xfb\x80\x1a&&\x1a\x04\x80\x1a&&\x00\x00\x01\x00\x00\x01@\x04\x00\x03\x80\x00\r\x00\x00\x00\x14\a\x01\x06\"'\x01&463!2\x04\x00\x13\xfe@\x134\x13\xfe@\x13&\x1a\x03\x80\x1a\x03Z4\x13\xfe@\x13\x13\x01\xc0\x134&\x00\x00\x00\x00\x01\x00\x00\x01\x00\x04\x00\x03@\x00\r\x00\x00\x00\x14\x06#!\"&47\x0162\x17\x01\x04\x00&\x1a\xfc\x80\x1a&\x13\x01\xc0\x134\x13\x01\xc0\x01Z4&&4\x13\x01\xc0\x13\x13\xfe@\x00\x00\x00\x00\x01\x00@\x00\x80\x02\x80\x04\x80\x00\r\x00\x00\x01\x11\x14\x06\"'\x01&47\x0162\x16\x02\x80&4\x13\xfe@\x13\x13\x01\xc0\x134&\x04@\xfc\x80\x1a&\x13\x01\xc0\x134\x13\x01\xc0\x13&\x00\x00\x00\x01\x00\x00\x00\x80\x02@\x04\x80\x00\r\x00\x00\x00\x14\a\x01\x06\"&5\x11462\x17\x01\x02@\x13\xfe@\x134&&4\x13\x01\xc0\x02\x9a4\x13\xfe@\x13&\x1a\x03\x80\x1a&\x13\xfe@\x00\x00\x00\x00\x03\x00\x00\xff\x80\x06\x80\x05\x80\x00\x06\x00\r\x00\x1d\x00\x003!\x11!\x11\x14\x16%\x11!\x11!26\x13\x11\x14\x06#!\"&5\x11463!2\x16\xa0\x02`\xfd\x80\x13\x05m\xfd\x80\x02`\r\x13\x80^B\xfa\xc0B^^B\x05@B^\x04\x80\xfb\xa0\r\x13 \x04`\xfb\x80\x13\x04\xcd\xfb@B^^B\x04\xc0B^^\x00\x02\x00\x00\xff\xc0\x04\x00\x05@\x00\r\x00\x1b\x00\x00\x00\x14\a\x01\x06\"'\x01&463!2\x12\x14\x06#!\"&47\x0162\x17\x01\x04\x00\x13\xfe@\x134\x13\xfe@\x13&\x1a\x03\x80\x1a&&\x1a\xfc\x80\x1a&\x13\x01\xc0\x134\x13\x01\xc0\x01\xda4\x13\xfe@\x13\x13\x01\xc0\x134&\x01Z4&&4\x13\x01\xc0\x13\x13\xfe@\x00\x00\x00\x00\x01\x00\x00\xff\xc0\x04\x00\x02\x00\x00\r\x00\x00\x00\x14\a\x01\x06\"'\x01&463!2\x04\x00\x13\xfe@\x134\x13\xfe@\x13&\x1a\x03\x80\x1a\x01\xda4\x13\xfe@\x13\x13\x01\xc0\x134&\x00\x00\x00\x00\x01\x00\x00\x03\x00\x04\x00\x05@\x00\r\x00\x00\x00\x14\x06#!\"&47\x0162\x17\x01\x04\x00&\x1a\xfc\x80\x1a&\x13\x01\xc0\x134\x13\x01\xc0\x03Z4&&4\x13\x01\xc0\x13\x13\xfe@\x00\x00\x00\x00\x02\x00\x00\xff\x80\a\x00\x05\x00\x00\x1a\x00:\x00\x00\x01\x11\x14\x06#!\"&5\x11\x16\x17\x04\x17\x1e\x02;\x022>\x0176%6\x13\x14\x06\a\x00\a\x0e\x04+\x02\".\x03'&$'.\x015463!2\x16\a\x00^B\xfa@B^,9\x01j\x879Gv3\x01\x013vG9\xaa\x01H9+bI\xfe\x88\\\nA+=6\x17\x01\x01\x176=+A\n[\xfe\xaa\">nSM\x05\xc0A_\x03:\xfc\xe6B^^B\x03\x1a1&\xf6c*/11/*{\xde'\x01VO\x903\xfe\xfb@\a/\x1d$\x12\x12$\x1d/\a@\xed\x18*\x93?Nh^\x00\x03\x00\x00\xff\xb0\x06\x00\x05l\x00\x03\x00\x0f\x00+\x00\x00\x01\x11!\x11\x01\x16\x06+\x01\"&5462\x16\x01\x11!\x114&#\"\x06\a\x06\x15\x11!\x12\x10/\x01!\x15#>\x0332\x16\x01]\xfe\xb6\x01_\x01gT\x02Rdg\xa6d\x04\x8f\xfe\xb7QV?U\x15\v\xfe\xb7\x02\x01\x01\x01I\x02\x14*Gg?\xab\xd0\x03\x8f\xfc!\x03\xdf\x012IbbIJaa\xfc\xdd\xfd\xc8\x02\x12iwE3\x1e3\xfd\xd7\x01\x8f\x01\xf000\x90 08\x1f\xe3\x00\x00\x00\x00\x01\x00\x00\xff\x80\x06\x00\x05\x80\x004\x00\x00\x00\x10\x02\x06\x04#\"$'&6?\x0163\x16\x17\x1e\x0132>\x024.\x02#\"\x06\a\x17\x16\a\x06#!\"&5\x11476\x1f\x016$32\x04\x16\x06\x00z\xce\xfe䜬\xfe\xcam\a\x01\b\x89\n\x0f\x10\aI\xd4wh\xbd\x8aQQ\x8a\xbdhb\xb4F\x89\x1f\x11\x11*\xfe@\x1a&('\x1e\x82k\x01\x13\x93\x9c\x01\x1c\xce\x03\x1c\xfe\xc8\xfe\xe4\xcez\x91\x84\n\x19\b\x8a\t\x02\n_hQ\x8a\xbdн\x8aQGB\x8a\x1e'(&\x1a\x01\xc0*\x11\x11\x1f\x81eoz\xce\x00\x01\x00(\xff\x15\x06\xeb\x05\xd8\x00q\x00\x00!\x14\x0f\x01\x06#\"'\x01&547\x01\a\x06\"'\x1e\x06\x15\x14\a\x0e\x05#\"'\x01&54>\x047632\x1e\x05\x17&47\x0162\x17.\x06547>\x0532\x17\x01\x16\x15\x14\x0e\x04\a\x06#\".\x05'\x16\x14\x0f\x01\x01632\x17\x01\x16\x06\xeb%k'45%\xfe\x95&+\xff\x00~\x0e(\x0e\x02\x15\x04\x10\x04\b\x03\x1c\x03\x1b\v\x1a\x12\x1a\r(\x1c\xfeh\x1c\t\t\x16\v\x1e\x03\x1e&\n\x10\x11\n\x11\x06\x14\x02\x0e\x0e\x01\\\x0e(\x0e\x02\x15\x04\x10\x04\b\x03\x1c\x03\x1b\v\x1a\x12\x1a\r(\x1c\x01\x98\x1c\t\t\x16\v\x1e\x03\x1e&\n\x10\x11\n\x11\x06\x14\x02\x0e\x0e~\x01\x00+54'\x01k%5%l%%\x01l$65+\x01\x00~\x0e\x0e\x02\x14\x06\x11\n\x11\x10\n&\x1e\x03\x1e\v\x16\t\t\x1c\x01\x98\x1c(\r\x1a\x12\x1a\v\x1b\x03\x1c\x03\b\x04\x10\x04\x15\x02\x0e(\x0e\x01\\\x0e\x0e\x02\x14\x06\x11\n\x11\x10\n&\x1e\x03\x1e\v\x16\t\t\x1c\xfeh\x1c(\r\x1a\x12\x1a\v\x1b\x03\x1c\x03\b\x04\x10\x04\x15\x02\x0e(\x0e~\xff\x00+%\xfe\x95'\x00\x00\a\x00\x00\xff\x80\a\x00\x05\x00\x00\a\x00\x0f\x00!\x00)\x001\x009\x00K\x00\x00\x004&\"\x06\x14\x162\x004&\"\x06\x14\x162\x01\x136.\x01\x06\a\x03\x0e\x01\a\x06\x1e\x01676&$4&\"\x06\x14\x162\x004&\"\x06\x14\x162\x044&\"\x06\x14\x162\x01\x10\a\x06#!\"'&\x114\x126$ \x04\x16\x12\x01\x80KjKKj\x01\vKjKKj\x01\xf7e\x06\x1b2.\ae<^\x10\x14P\x9a\x8a\x14\x10,\x02bKjKKj\xfd\xcbKjKKj\x02\vKjKKj\x01\x8b\x8d\x13#\xfa\x86#\x13\x8d\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x01KjKKjK\x02\vjKKjK\xfe\x9f\x01~\x1a-\x0e\x1b\x1a\xfe\x82\x05M\x027>\x057&\x0254\x12$ \x04\x04L\xfeh\xfe\x9dя\x82W\x1b\x18.\x98{+9E=\xcc\x01c\xd1\xd1\x01Q\xf0\xfed\xf4FK\xc6\xfe\xfa1A\x05\x0f\x18\x04\x03\x05\x01\n\x02\f\x02\a0\x15)\x18\x1e\v\x9d\xb5\xf0\x01\x9c\x01\xe8\x01\x9c\x04\x80\x8b\xec\x89p\xcbJ2`[Q?l&\x06\b\x8b\xec\x01\x12\xec\xc7\xfe\xa4\xfe٫\b\xafC\x0e\b\x15\x11\x01\x04\x10\x04\x0f\x03\x0e\x02\b5\x178.H(Y\x01\x06\x96\xae\x01'\xab\xab\x00\x00\x03\x00\x00\xff\x80\a\x00\x05\x00\x00\x14\x00:\x00d\x00\x00\x00 \x04\x06\x15\x14\x16\x1f\x01\a6?\x01\x17\x1632$64&$ \x04\x16\x10\x06\x04#\"'\x06\a\x06\a#\"&'&4>\x057>\x047.\x01546\x01\x1e\x04\x17\x1e\x06\x14\a\x0e\x01'&'&'\x06# '\x1632$7>\x0154'\x1e\x01\x15\x14\x06\x03Y\xfe\xce\xfe\xf6\x9dj`a#\"\x1c,5NK\x99\x01\n\x9d\x9d\xfd\x9e\x01~\x01E\xbc\xbc\xfe\xbb\xbfVZ|\x9a$2\x03\v\x13\x02\x01\x01\x03\x02\x05\x03\x06\x01\x05$\x10\x1d\x15\n|\x8e\xbc\x05:\n\x15\x1d\x10$\x05\x01\x06\x03\x05\x02\x03\x01\x01\x03\x14\f2$\x9a|ZV\xfe\xf1\xc9:\x1e\xa1\x01(t}\x86\x17\x81\x96\x8e\x04\x80h\xb2fR\x9888T\x14\x13\x1f\n\x0eh\xb2̲\xe8\x89\xec\xfe\xea\xec\x89\x10X(\t\a\x10\r\x03\a\x06\x06\x04\a\x03\a\x01\x06&\x15%(\x18H\xd2w\x8b\xec\xfb\xf8\x18(%\x15&\x06\x01\a\x03\a\x04\x06\x06\a\x03\x0e\x10\x01\a\t(X\x10\x84\x04ZT\\\xf0\x86MKG\xd6{x\xd1\x00\x01\x00\x01\xff\x00\x03|\x05\x80\x00!\x00\x00\x01\x16\a\x01\x06#\"'.\x017\x13\x05\x06#\"'&7\x13>\x013!2\x16\x15\x14\a\x03%632\x03u\x12\v\xfd\xe4\r\x1d\x04\n\x11\x11\x04\xc5\xfej\x04\b\x12\r\x12\x05\xc9\x04\x18\x10\x01H\x13\x1a\x05\xab\x01\x8c\b\x04\x13\x03\xca\x14\x18\xfb{\x19\x02\x05\x1c\x10\x03(e\x01\v\x0f\x18\x039\x0e\x12\x19\x11\b\n\xfe1b\x02\x00\x00\x01\x00\x00\xff\x80\a\x00\x05\x80\x00U\x00\x00\x01\x11\x14\x06#!\"&5\x1146;\x015!\x1532\x16\x15\x11\x14\x06#!\"&5\x1146;\x015!\x1532\x16\x15\x11\x14\x06#!\"&5\x1146;\x015463!5#\"&5\x11463!2\x16\x15\x11\x14\x06+\x01\x15!2\x16\x1d\x0132\x16\a\x008(\xfe\xc0(88(`\xfe\x00`(88(\xfe\xc0(88(`\xfe\x00`(88(\xfe\xc0(88(`L4\x02\x00`(88(\x01@(88(`\x02\x004L`(8\x01 \xfe\xc0(88(\x01@(8\xc0\xc08(\xfe\xc0(88(\x01@(8\xc0\xc08(\xfe\xc0(88(\x01@(8\xc04L\xc08(\x01@(88(\xfe\xc0(8\xc0L4\xc08\x00\x00\x03\x00\x00\xff\x80\x06\x80\x05\xc0\x00\x13\x00O\x00Y\x00\x00\x01\x11\x14\x06\"&5462\x16\x15\x14\x16265\x1162\x05\x14\x06#\"'.\x01#\"\x06\a\x0e\x01\a\x06#\"'.\x01'.\x01\"\x06\a\x0e\x01\a\x06#\"'.\x01'.\x01#\"\x06\a\x06#\"&5476\x00$32\x04\x1e\x01\x17\x16\x01\x15&\"\a5462\x16\x03\x80\x98И&4&NdN!>\x03!\x13\r\v\f1X:Dx+\a\x15\x04\v\x11\x12\v\x04\x15\a+w\x88w+\a\x15\x04\v\x12\x11\v\x04\x15\a+xD:X1\f\v\r\x13\x01-\x00\xff\x01U\xbe\x8c\x01\r\xe0\xa5!\x01\xfd\x00*,*&4&\x02\xc4\xfd\xbch\x98\x98h\x1a&&\x1a2NN2\x02D\v&\r\x13\n..J<\n$\x06\x11\x11\x06$\n\x01767\x14\a\x0e\x02\a\x16\x15\x14\a\x16\x15\x14\a\x16\x15\x14\x06#\x0e\x01\"&'\"&547&547&547.\x02'&54>\x022\x1e\x02\x02\xe0\x13\x1a\x13l4\r\x13\x13\r2cK\xa0Eo\x87\x8a\x87oED\n)\n\x80\r\xe4\r\x80\n)\nD\x80g-;<\x04/\x19\x19-\r?.\x14P^P\x14.?\r-\x19\x19/\x04<;-gY\x91\xb7\xbe\xb7\x91Y\x03\xc0\r\x13\x13\r.2\x13\x1a\x13 L4H|O--O|HeO\v,\v\x99\x91\x91\x99\v,\vOe\x9bq1Ls2\x1c6%\x1b\x1b%4\x1d\x17\x18.2,44,2.\x18\x17\x1d4%\x1b\x1b%6\x1c2sL1q\x9bc\xabqAAq\xab\x00\x02\x00\x00\xff\xa0\a\x00\x04\xe0\x00\x1a\x004\x00\x00\x01\x15\x14\x06#!\x15\x14\x06#\"'\x01&547\x01632\x16\x1d\x01!2\x16\x10\x14\a\x01\x06#\"&=\x01!\"&=\x01463!54632\x17\x01\a\x00\x13\r\xfa\xa0\x13\r\f\f\xfe\xc1\t\t\x01@\t\x0e\r\x13\x05`\r\x13\t\xfe\xc0\t\x0e\r\x13\xfa\xa0\r\x13\x13\r\x05`\x12\x0e\f\f\x01?\x01`\xc0\r\x13\xc0\r\x13\n\x01@\t\r\x0e\t\x01@\t\x13\r\xc0\x13\x02!\x1c\t\xfe\xc0\t\x13\r\xc0\x13\r\xc0\r\x13\xc0\x0e\x12\n\xfe\xc1\x00\x00\x00\x00\x02\x00\x00\x00\x00\a\x80\x05\x80\x00\x19\x005\x00\x00\x014&+\x01\x114&+\x01\"\x06\x15\x11#\"\x06\x15\x14\x17\x01\x1627\x016\x05\x14\x06#!\"\x005467&54\x0032\x04\x17632\x16\x15\x14\a\x1e\x01\x05\x00\x12\x0e\xe0\x13\r\xc0\r\x13\xe0\r\x13\t\x01`\t\x1c\t\x01_\n\x02\x80\xe1\x9f\xfb\xc0\xb9\xfe\xf9\x8cv\x02\x01,Ԝ\x01\x03;G_j\x96)\x82\xa7\x02`\x0e\x12\x01`\r\x13\x13\r\xfe\xa0\x13\r\x0e\t\xfe\xa0\t\t\x01_\fԟ\xe1\x01\a\xb9\x82\xdc7\x1e\r\xd4\x01,\xae\x90>\x96jL>\x1f\xd1\x00\x02\x00\x00\x00\x00\a\x80\x05\x80\x00\x19\x005\x00\x00\x014'\x01&\"\a\x01\x06\x15\x14\x16;\x01\x11\x14\x16;\x01265\x11326\x01\x14\x06#!\"\x005467&54\x0032\x04\x17632\x16\x15\x14\a\x1e\x01\x05\x00\t\xfe\xa0\t\x1c\t\xfe\xa1\n\x12\x0e\xe0\x13\r\xc0\r\x13\xe0\r\x13\x02\x80\xe1\x9f\xfb\xc0\xb9\xfe\xf9\x8cv\x02\x01,Ԝ\x01\x03;G_j\x96)\x82\xa7\x02\xa0\x0e\t\x01`\t\t\xfe\xa1\f\f\x0e\x12\xfe\xa0\r\x13\x13\r\x01`\x13\xfe\xed\x9f\xe1\x01\a\xb9\x82\xdc7\x1e\r\xd4\x01,\xae\x90>\x96jL>\x1f\xd1\x00\x00\x00\x00\x03\x00\x00\xff\x80\x05\x80\x05\x80\x00\a\x00X\x00`\x00\x00$\x14\x06\"&462\x05\x14\x06#!\"&54>\x037\x06\x1d\x01\x0e\x01\x15\x14\x162654&'547\x16 7\x16\x1d\x01\"\x06\x1d\x01\x06\x15\x14\x162654'5462\x16\x1d\x01\x06\x15\x14\x162654'54&'46.\x02'\x1e\x04\x00\x10\x06 &\x106 \x01\x80&4&&4\x04&\x92y\xfc\x96y\x92\v%:hD\x16:Fp\xa0pG9\x19\x84\x01F\x84\x19j\x96 8P8 LhL 8P8 E;\x01\x01\x04\n\bDh:%\v\xfe\xc0\xe1\xfe\xc2\xe1\xe1\x01>\xda4&&4&}y\x8a\x8ayD~\x96s[\x0f4D\xcb\x14d=PppP=d\x14\xcb>\x1fhh\x1f>@\x96jY\x1d*(88(*\x1dY4LL4Y\x1d*(88(*\x1dYDw\"\nA\x1f4*\x13\x0f[s\x96~\x03\xd8\xfe\xc2\xe1\xe1\x01>\xe1\x00\x00\x00\x02\x00\x00\xff\x80\x05\x80\x05\x80\x00\a\x00M\x00\x00\x004&\"\x06\x14\x1627\x14\x06\a\x11\x14\x04 $=\x01.\x015\x114632\x17>\x0132\x16\x14\x06#\"'\x11\x14\x16 65\x11\x06#\"&4632\x16\x17632\x16\x15\x11\x14\x06\a\x15\x14\x16 65\x11.\x015462\x16\x05\x00&4&&4\xa6G9\xfe\xf9\xfe\x8e\xfe\xf9\xa4\xdc&\x1a\x06\n\x11<#5KK5!\x1f\xbc\x01\b\xbc\x1f!5KK5#<\x11\n\x06\x1a&ܤ\xbc\x01\b\xbc9Gp\xa0p\x03&4&&4&@>b\x15\xfeu\x9f\xe1ោ\x14ؐ\x02\x00\x1a&\x02\x1e$KjK\x12\xfenj\x96\x96j\x01\x92\x12KjK$\x1e\x02&\x1a\xfe\x00\x90\xd8\x14\x84j\x96\x96j\x01\x8b\x15b>Ppp\x00\x04\x00\x00\xff\x80\a\x00\x05\x80\x00\x03\x00\r\x00\x1b\x00%\x00\x00\x01!5!\x05\x11#\"&5\x11463!\x11!\x1135463!2\x16\x1d\x01\x05\x11\x14\x06+\x01\x1132\x16\x02\x80\x02\x00\xfe\x00\xfe\xa0@\\\x84\x84\\\x04\xa0\xfc\x00\x808(\x02@(8\x02\x00\x84\\@@\\\x84\x04\x80\x80\x80\xfb\x00\x84\\\x03@\\\x84\xfb\x00\x05\x00\xa0(88(\xa0\xe0\xfc\xc0\\\x84\x05\x00\x84\x00\x02\x00@\xff\x00\x06\xc0\x06\x00\x00\v\x003\x00\x00\x044#\"&54\"\x15\x14\x163\x01\x14\x06#!\x14\x06\"&5!\"&5>\x0454\x127&5462\x16\x15\x14\a\x16\x12\x15\x14\x1e\x03\x03\x90\x10;U gI\x03@L4\xfe@\x96Ԗ\xfe@4L2RX='\xea\xbe\b8P8\b\xbe\xea'=XR\xb0 U;\x10\x10Ig\x0104Lj\x96\x96jL4*\\\x93\xaa\xf2\x8b\x98\x01\x05\x1c\x13\x14(88(\x14\x13\x1c\xfe\xfb\x98\x8b\xf2\xaa\x93\\\x00\x00\x03\x00\x00\xff\x80\a@\x05\x00\x00\a\x00\x0f\x00\"\x00\x00\x004&+\x01\x1132\x01!\x14\x06#!\"&\x00\x10\x06+\x01\x15\x14\x06#!\"&5\x11463!2\x06\x80pP@@P\xf9\xf0\a\x00\x96j\xfb\x00j\x96\a@\xe1\x9f@\x84\\\xfd@\\\x84&\x1a\x04\x80\x9f\x030\xa0p\xfe\x80\xfd\xc0j\x96\x96\x04\t\xfe\xc2\xe1 \\\x84\x84\\\x02\xe0\x1a&\x00\x00\x02\x00\x00\xff\x00\x05\x80\x06\x00\x00-\x00B\x00\x00\x01\x11\x14\x06\a\x11\x14\x06+\x01\"&5\x11.\x015\x11462\x16\x15\x11\x14\x16265\x11462\x16\x15\x11\x14\x16265\x11462\x16\x05\x11\x14\x06+\x01\"&5\x11#\"&5\x11463!2\x16\x02\x80G9L4\x804L9G&4&&4&&4&&4&&4&\x03\x00L4\x804L\xe0\r\x13\xbc\x84\x01\x00\x1a&\x05\xc0\xfd\x80=d\x14\xfc\xf54LL4\x03\v\x14d=\x02\x80\x1a&&\x1a\xfe`\x1a&&\x1a\x01\xa0\x1a&&\x1a\xfe`\x1a&&\x1a\x01\xa0\x1a&&\x1a\xf9\xc04LL4\x02\x00\x13\r\x03 \x84\xbc&\x00\x06\x00\x00\xff\x00\x06\x00\x06\x00\x00\x13\x00\x1a\x00#\x003\x00C\x00S\x00\x00\x01\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x17\a\x11!&'\x01&\x01\x11!\"&5\x11!\x11\x01463!2\x16\x1d\x01\x14\x06#!\"&5\x052\x16\x1d\x01\x14\x06#!\"&=\x01463\x012\x16\x1d\x01\x14\x06#!\"&=\x01463\x05\xbc\x1c(8(\xfa\xc0(88(\x03\x80(`\x1c\x84\x01x\n\f\xfe\xc7\f\x01c\xfe`(8\xfd\x00\x01\x00\x12\x0e\x02\xc0\x0e\x12\x12\x0e\xfd@\x0e\x12\x02\xe0\x0e\x12\x12\x0e\xfd@\x0e\x12\x12\x0e\x02\xc0\x0e\x12\x12\x0e\xfd@\x0e\x12\x12\x0e\x04\x84\x1c`(\xfb\x80(88(\x06@(8(\x1cD\xfe\x88\x1d\f\x019\f\xfa\x12\x04\x008(\x01\xa0\xfa\x00\x03`\x0e\x12\x12\x0e@\x0e\x12\x12\x0e\xa0\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\xff\x00\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x00\x14\x00\x00\xff\x00\x05\x80\x06\x00\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00o\x00\u007f\x00\x8f\x00\x9f\x00\xaf\x00\xbf\x00\xcf\x00\xdf\x00\xef\x00\xff\x01\x0f\x01\x1f\x01-\x01=\x00\x00%\x15\x14\x06+\x01\"&=\x0146;\x012\x165\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x05\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x05\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01!\x11!\x11!5463!2\x16\x15\x01\x11\x14\x06#!\"&5\x11463!2\x16\x01\x80\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x01\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\x03\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\x03\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\x03\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\x02\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\x01\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x01\x80\xfb\x80\x01\x80\x13\r\x01@\r\x13\x02\x00&\x1a\xfb\x00\x1a&&\x1a\x05\x00\x1a&\xe0@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xfd\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xfd\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xfd\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xfe\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\xfa\x93\x06\x00\xfa\x00\xe0\r\x13\x13\r\x05`\xf9\x80\x1a&&\x1a\x06\x80\x1a&&\x00\r\x00\x00\xff\x00\x05\x80\x06\x00\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00o\x00\u007f\x00\x8f\x00\x9f\x00\xb7\x00\xdb\x00\xf5\x00\x00%\x15\x14\x06+\x01\"&=\x0146;\x012\x165\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x05\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x05\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01!\x11!\x15\x14\x06#!\"&=\x01!\x11!5463!2\x16\x15\x19\x014&+\x01\"\x06\x1d\x01#54&+\x01\"\x06\x15\x11\x14\x16;\x0126=\x013\x15\x14\x16;\x0126%\x11\x14\x06#!\"&5\x11463!\x11463!2\x16\x15\x11!2\x16\x01\x80\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x01\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\x03\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\x02\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x13\r@\r\x13\x13\r@\r\x13\x01\x00\x13\r@\r\x13\x13\r@\r\x13\xff\x00\x01\x80\xff\x008(\xfe@(8\xff\x00\x01\x80\x13\r\x01@\r\x13\x13\r@\r\x13\x80\x13\r@\r\x13\x13\r@\r\x13\x80\x13\r@\r\x13\x02\x00&\x1a\xfb\x00\x1a&&\x1a\x01@8(\x01\xc0(8\x01@\x1a&\xe0@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xfd\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\xfe\xf3@\r\x13\x13\r@\r\x13\x13\xf3@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\r@\r\x13\x13\xfc\x93\x04\x80 (88( \xfb\x80\xe0\r\x13\x13\r\x03\xc0\x01@\r\x13\x13\r``\r\x13\x13\r\xfe\xc0\r\x13\x13\r``\r\x13\x13-\xfb\x00\x1a&&\x1a\x05\x00\x1a&\x01 (88(\xfe\xe0&\x00\x05\x00@\xff\x80\a\x80\x05\x80\x00\a\x00\x10\x00\x18\x00<\x00c\x00\x00$4&\"\x06\x14\x162\x01!\x11#\x06\x0f\x01\x06\a\x004&\"\x06\x14\x162\x1354&+\x0154&+\x01\"\x06\x1d\x01#\"\x06\x1d\x01\x14\x16;\x01\x15\x14\x16;\x0126=\x01326\x01\x11\x14\x06+\x01\x14\x06\"&5!\x14\x06\"&5#\"&463\x1146?\x01>\x01;\x01\x11463!2\x16\x02\x80KjKKj\xfe\xcb\x01\x80\x9e\x0e\b\xc3\a\x02\x05\x00KjKKj\xcb\x12\x0e\xe0\x12\x0e\xc0\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\x12\x0e\xc0\x0e\x12\xe0\x0e\x12\x01\x00&\x1a\xc0\x96Ԗ\xfe\x80\x96Ԗ\x80\x1a&&\x1a\x1a\x13\xc6\x13@\x1a\xa0&\x1a\x04\x80\x1a&KjKKjK\x02\x80\x01\x00\x02\a\xc3\f\n\xfd\xadjKKjK\x03 \xc0\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\x12\x0e\xc0\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\x12\x02.\xfb\x80\x1a&j\x96\x96jj\x96\x96j&4&\x01\xa0\x1a@\x13\xc6\x13\x1a\x01@\x1a&&\x00\x00\x05\x00\x00\xff\x80\a\x00\x05\x80\x00#\x00'\x001\x00?\x00I\x00\x00\x0154&+\x0154&+\x01\"\x06\x1d\x01#\"\x06\x1d\x01\x14\x16;\x01\x15\x14\x16;\x0126=\x01326\x01!5!\x05\x11#\"&5\x11463!\x11!\x1135463!2\x16\x1d\x01\x05\x11\x14\x06+\x01\x1132\x16\x05\x00\x12\x0e\xe0\x12\x0e\xc0\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\x12\x0e\xc0\x0e\x12\xe0\x0e\x12\xfd\x80\x02\x00\xfe\x00\xfe\x80 \\\x84\x84\\\x04\xc0\xfb\xc0\xa08(\x02@(8\x02\x00\x84\\ \\\x84\x01\xa0\xc0\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\x12\x0e\xc0\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\x12\x02\ue000\xfb\x00\x84\\\x03@\\\x84\xfb\x00\x05\x00\xa0(88(\xa0\xe0\xfc\xc0\\\x84\x05\x00\x84\x00\x00\x00\x00\x01\x00\x00\x00\x00\a\x80\x04\x80\x00:\x00\x00\x01\x06\r\x01\a#\x0132\x16\x14\x06+\x0353\x11#\a#'53535'575#5#573\x173\x11#5;\x022\x16\x14\x06+\x01\x013\x17\x05\x1e\x01\x17\a\x80\x01\xfe\xe1\xfe\xa0\xe0@\xfe\xdbE\x1a&&\x1a`\xa0@@\xa0\xc0` \x80\xc0\xc0\x80 `\xc0\xa0@@\xa0`\x1a&&\x1aE\x01%@\xe0\x01`\x80\x90\b\x02@ @ @\xfe\xa0\t\x0e\t \x01\xa0\xe0 \xc0 \b\x18\x80\x18\b \xc0 \xe0\x01\xa0 \t\x0e\t\xfe\xa0@ \x1c0\n\x00\x00\x00\x02\x00@\x00\x00\x06\x80\x05\x80\x00\x06\x00\x18\x00\x00\x01\x11!\x11\x14\x163\x01\x15!57#\"&5\x11'7!7!\x17\a\x11\x02\x80\xff\x00K5\x04\x80\xfb\x80\x80\x80\x9f\xe1@ \x01\xe0 \x03\xc0 @\x02\x80\x01\x80\xff\x005K\xfe@\xc0\xc0\xc0\xe1\x9f\x01@@\x80\x80\xc0 \xfc\xe0\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00#\x003\x00\x00%\x114&+\x01\"\x06\x15\x11!\x114&+\x01\"\x06\x15\x11\x14\x16;\x01265\x11!\x11\x14\x16;\x0126\x01\x11\x14\x06#!\"&5\x11463!2\x16\x05\x00&\x1a\x80\x1a&\xfe\x00&\x1a\x80\x1a&&\x1a\x80\x1a&\x02\x00&\x1a\x80\x1a&\x01\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\xc0\x03\x80\x1a&&\x1a\xfe\xc0\x01@\x1a&&\x1a\xfc\x80\x1a&&\x1a\x01@\xfe\xc0\x1a&&\x03\xba\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00#\x003\x00\x00\x0154&#!\x114&+\x01\"\x06\x15\x11!\"\x06\x1d\x01\x14\x163!\x11\x14\x16;\x01265\x11!26\x01\x11\x14\x06#!\"&5\x11463!2\x16\x05\x00&\x1a\xfe\xc0&\x1a\x80\x1a&\xfe\xc0\x1a&&\x1a\x01@&\x1a\x80\x1a&\x01@\x1a&\x01\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x02@\x80\x1a&\x01@\x1a&&\x1a\xfe\xc0&\x1a\x80\x1a&\xfe\xc0\x1a&&\x1a\x01@&\x02:\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x02\x00-\x00M\x03\xf3\x043\x00\x14\x00)\x00\x00$\x14\x0f\x01\x06\"'\x01&47\x0162\x1f\x01\x16\x14\a\t\x01\x04\x14\x0f\x01\x06\"'\x01&47\x0162\x1f\x01\x16\x14\a\t\x01\x02s\n2\n\x1a\n\xfe.\n\n\x01\xd2\n\x1a\n2\n\n\xfew\x01\x89\x01\x8a\n2\n\x1a\n\xfe.\n\n\x01\xd2\n\x1a\n2\n\n\xfew\x01\x89\xad\x1a\n2\n\n\x01\xd2\n\x1a\n\x01\xd2\n\n2\n\x1a\n\xfew\xfew\n\x1a\n2\n\n\x01\xd2\n\x1a\n\x01\xd2\n\n2\n\x1a\n\xfew\xfew\x00\x00\x00\x02\x00\r\x00M\x03\xd3\x043\x00\x14\x00)\x00\x00\x00\x14\a\x01\x06\"/\x01&47\t\x01&4?\x0162\x17\x01\x04\x14\a\x01\x06\"/\x01&47\t\x01&4?\x0162\x17\x01\x02S\n\xfe.\n\x1a\n2\n\n\x01\x89\xfew\n\n2\n\x1a\n\x01\xd2\x01\x8a\n\xfe.\n\x1a\n2\n\n\x01\x89\xfew\n\n2\n\x1a\n\x01\xd2\x02M\x1a\n\xfe.\n\n2\n\x1a\n\x01\x89\x01\x89\n\x1a\n2\n\n\xfe.\n\x1a\n\xfe.\n\n2\n\x1a\n\x01\x89\x01\x89\n\x1a\n2\n\n\xfe.\x00\x00\x02\x00M\x00\x8d\x043\x04S\x00\x14\x00)\x00\x00$\x14\x0f\x01\x06\"'\t\x01\x06\"/\x01&47\x0162\x17\x01\x12\x14\x0f\x01\x06\"'\t\x01\x06\"/\x01&47\x0162\x17\x01\x043\n2\n\x1a\n\xfew\xfew\n\x1a\n2\n\n\x01\xd2\n\x1a\n\x01\xd2\n\n2\n\x1a\n\xfew\xfew\n\x1a\n2\n\n\x01\xd2\n\x1a\n\x01\xd2\xed\x1a\n2\n\n\x01\x89\xfew\n\n2\n\x1a\n\x01\xd2\n\n\xfe.\x01v\x1a\n2\n\n\x01\x89\xfew\n\n2\n\x1a\n\x01\xd2\n\n\xfe.\x00\x00\x00\x02\x00M\x00\xad\x043\x04s\x00\x14\x00)\x00\x00\x00\x14\a\x01\x06\"'\x01&4?\x0162\x17\t\x0162\x1f\x01\x12\x14\a\x01\x06\"'\x01&4?\x0162\x17\t\x0162\x1f\x01\x043\n\xfe.\n\x1a\n\xfe.\n\n2\n\x1a\n\x01\x89\x01\x89\n\x1a\n2\n\n\xfe.\n\x1a\n\xfe.\n\n2\n\x1a\n\x01\x89\x01\x89\n\x1a\n2\x02\xad\x1a\n\xfe.\n\n\x01\xd2\n\x1a\n2\n\n\xfew\x01\x89\n\n2\x01v\x1a\n\xfe.\n\n\x01\xd2\n\x1a\n2\n\n\xfew\x01\x89\n\n2\x00\x00\x01\x00-\x00M\x02s\x043\x00\x14\x00\x00\x00\x14\a\t\x01\x16\x14\x0f\x01\x06\"'\x01&47\x0162\x1f\x01\x02s\n\xfew\x01\x89\n\n2\n\x1a\n\xfe.\n\n\x01\xd2\n\x1a\n2\x03\xed\x1a\n\xfew\xfew\n\x1a\n2\n\n\x01\xd2\n\x1a\n\x01\xd2\n\n2\x00\x00\x00\x01\x00\r\x00M\x02S\x043\x00\x14\x00\x00\x00\x14\a\x01\x06\"/\x01&47\t\x01&4?\x0162\x17\x01\x02S\n\xfe.\n\x1a\n2\n\n\x01\x89\xfew\n\n2\n\x1a\n\x01\xd2\x02M\x1a\n\xfe.\n\n2\n\x1a\n\x01\x89\x01\x89\n\x1a\n2\n\n\xfe.\x00\x00\x00\x01\x00M\x01\r\x043\x03S\x00\x14\x00\x00\x00\x14\x0f\x01\x06\"'\t\x01\x06\"/\x01&47\x0162\x17\x01\x043\n2\n\x1a\n\xfew\xfew\n\x1a\n2\n\n\x01\xd2\n\x1a\n\x01\xd2\x01m\x1a\n2\n\n\x01\x89\xfew\n\n2\n\x1a\n\x01\xd2\n\n\xfe.\x00\x00\x00\x01\x00M\x01-\x043\x03s\x00\x14\x00\x00\x00\x14\a\x01\x06\"'\x01&4?\x0162\x17\t\x0162\x1f\x01\x043\n\xfe.\n\x1a\n\xfe.\n\n2\n\x1a\n\x01\x89\x01\x89\n\x1a\n2\x03-\x1a\n\xfe.\n\n\x01\xd2\n\x1a\n2\n\n\xfew\x01\x89\n\n2\x00\x00\x00\x02\x00\x00\xff\x80\a\x80\x06\x00\x00\x0f\x00/\x00\x00\x01\x114&#!\"\x06\x15\x11\x14\x163!26\x13\x11\x14\x06#!\x14\x1e\x01\x15\x14\x06#!\"&54>\x015!\"&5\x11463!2\x16\a\x00\x13\r\xf9\xc0\r\x13\x13\r\x06@\r\x13\x80^B\xfd\xe0 &\x1a\xfe\x00\x1a& \xfd\xe0B^^B\x06@B^\x02 \x03@\r\x13\x13\r\xfc\xc0\r\x13\x13\x03M\xfb\xc0B^%Q=\r\x1a&&\x1a\x0e\x01\x10&\x04\x10\x02\x04 $\x02\x10\x12$ \x04\x03\x94\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\x92\x92\x01r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x04\xa0\x92\xfa\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\xbd\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x02\x00\x00\x00\x00\x06\x80\x05\x80\x00!\x00C\x00\x00\x01\x11\x14\x06#!\"&5\x114>\x02;\x012\x16\x1d\x01\x14\x06+\x01\"\x06\x1d\x01\x14\x16;\x012\x16\x05\x11\x14\x06#!\"&5\x114>\x02;\x012\x16\x1d\x01\x14\x06+\x01\"\x06\x1d\x01\x14\x16;\x012\x16\x03\x00pP\xfe\x80PpQ\x8a\xbdh@\x1a&&\x1a@j\x968(\xe0Pp\x03\x80pP\xfe\x80PpQ\x8a\xbdh@\x1a&&\x1a@j\x968(\xe0Pp\x02@\xfe\x80PppP\x02\xc0h\xbd\x8aQ&\x1a\x80\x1a&\x96j (8pP\xfe\x80PppP\x02\xc0h\xbd\x8aQ&\x1a\x80\x1a&\x96j (8p\x00\x00\x00\x00\x02\x00\x00\x00\x00\x06\x80\x05\x80\x00!\x00C\x00\x00\x01\x11\x14\x0e\x02+\x01\"&=\x0146;\x0126=\x014&+\x01\"&5\x11463!2\x16\x05\x11\x14\x0e\x02+\x01\"&=\x0146;\x0126=\x014&+\x01\"&5\x11463!2\x16\x03\x00Q\x8a\xbdh@\x1a&&\x1a@j\x968(\xe0PppP\x01\x80Pp\x03\x80Q\x8a\xbdh@\x1a&&\x1a@j\x968(\xe0PppP\x01\x80Pp\x04\xc0\xfd@h\xbd\x8aQ&\x1a\x80\x1a&\x96j (8pP\x01\x80PppP\xfd@h\xbd\x8aQ&\x1a\x80\x1a&\x96j (8pP\x01\x80Ppp\x00\x00\x00\x00\b\x00@\xff@\x06\xc0\x06\x00\x00\t\x00\x11\x00\x19\x00#\x00+\x003\x00;\x00G\x00\x00$\x14\x06#\"&5462\x00\x14\x06\"&462\x00\x14\x06\"&462\x01\x14\x06#\"&462\x16\x00\x14\x06\"&462\x00\x14\x06\"&462\x00\x14\x06\"&462\x01\x14\x06#\"&54632\x16\x02\x0eK54LKj\x02=KjKKj\xfd\x8bKjKKj\x04\xfdL45KKjK\xfc<^\x84^^\x84\x04\xf0KjKKj\xfd\xcbp\xa0pp\xa0\x02\x82\x84\\]\x83\x83]\\\x84\xc3jKL45K\xfe\xe7jKKjK\x02ujKKjK\xfd\x8e4LKjKK\x03\xf1\x84^^\x84^\xfd\xa3jKKjK\x02\x90\xa0pp\xa0p\xfer]\x83\x83]\\\x84\x84\x00\x00\x00\x00\x01\x00\x00\xff\x80\x06\x00\x05\x80\x00\v\x00\x00\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x06\x00\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x03Q\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x01\x00\x00\xff\x80\a\x00\x05\xc0\x00,\x00\x00\x01\x14\x03\x0e\x02\a\x06#\"&5465654.\x05+\x01\x11\x14\x06\"'\x01&47\x0162\x16\x15\x113 \x13\x16\a\x00\u007f\x03\x0f\f\a\f\x10\x0f\x11\x05\x05#>bq\x99\x9bb\xe0&4\x13\xfe\x00\x13\x13\x02\x00\x134&\xe0\x02ɢ5\x01\xa0\xa6\xfe\xe3\a\"\x1a\t\x11\x14\x0f\t#\x06D7e\xa0uU6\x1f\f\xff\x00\x1a&\x13\x02\x00\x134\x13\x02\x00\x13&\x1a\xff\x00\xfem\x86\x00\x04\x00\x00\xff\x80\x06\x80\x05\x00\x00\v\x00\x17\x001\x00X\x00\x00\x00\x14\x0e\x01\".\x014>\x012\x16\x04\x14\x0e\x01\".\x014>\x012\x16\x174&#\"\a\x06\"'&#\"\x06\x15\x14\x1e\x03;\x012>\x03\x13\x14\a\x0e\x04#\".\x04'&547&5472\x16\x17632\x17>\x013\x16\x15\x14\a\x16\x02\x80\x19=T=\x19\x19=T=\x02\x99\x19=T=\x19\x19=T=\xb9\x8av)\x9aG\xacG\x98+v\x8a@b\x92\x86R\xa8R\x86\x92b@\xe0=&\x87\x93\xc1\x96\\N\x80\xa7\x8a\x88j!>\x88\x1b3l\xa4k\x93\xa2\x94\x84i\xa4k3\x1b\x88\x01hPTDDTPTDDTPTDDTPTDD|x\xa8\x15\v\v\x15\xa8xX\x83K-\x0e\x0e-K\x83\x01\b\xcf|Mp<#\t\x06\x13)>dA{\xd0\xed\x9fRXtfOT# RNftWQ\xa0\x00\x00\x00\x00\x02\x00\x00\x00\x00\x06\x80\x05\x80\x00\x17\x00,\x00\x00%\x114&#!\"&=\x014&#!\"\x06\x15\x11\x14\x163!26\x13\x11\x14\x06#!\"&5\x11463!2\x16\x1d\x01!2\x16\x06\x008(\xfd@(88(\xfe\xc0(88(\x04\xc0(8\x80\x84\\\xfb@\\\x84\x84\\\x01@\\\x84\x02\xa0\\\x84\xe0\x02\xc0(88(@(88(\xfc@(88\x02\xe8\xfd@\\\x84\x84\\\x03\xc0\\\x84\x84\\ \x84\x00\x00\x03\x00\x00\x00\x00\au\x05\x80\x00\x11\x00'\x00E\x00\x00\x014#!\"\x06\a\x01\x06\x15\x143!267\x016%!54&#!\"&=\x014&#!\"\x06\x15\x11\x01>\x01\x05\x14\a\x01\x0e\x01#!\"&5\x11463!2\x16\x1d\x01!2\x16\x1d\x0132\x16\x17\x16\x06\xf55\xfb\xc0([\x1a\xfe\xda\x125\x04@(\\\x19\x01&\x12\xfb\x8b\x03\x008(\xfd\xc0(88(\xfe\xc0(8\x01\x00,\x90\x059.\xfe\xd9+\x92C\xfb\xc0\\\x84\x84\\\x01@\\\x84\x02 \\\x84\xc06Z\x16\x0f\x02]#+\x1f\xfe\x95\x18\x10#,\x1f\x01k\x16\xb4\xa0(88(@(88(\xfc\xab\x01;5E\xa3>:\xfe\x955E\x84\\\x03\xc0\\\x84\x84\\ \x84\\\xa01. \x00\x00\x00\x00\x05\x00\x00\xff\x80\x06\x00\x05\x80\x00\x14\x00\x1c\x00$\x004\x00@\x00\x00\x01\x0e\x01\"&'&676\x16\x17\x1e\x01267>\x01\x1e\x01\x00\x14\x06\"&462\x04\x14\x06\"&462\x00\x10.\x02 \x0e\x02\x10\x1e\x02 >\x01\x12\x10\x02\x04 $\x02\x10\x12$ \x04\x04n%\xca\xfe\xca%\b\x18\x1a\x19/\b\x19\x87\xa8\x87\x19\b02\x18\xfe\nKjKKj\x02KKjKKj\x01Kf\xab\xed\xfe\xfc\xed\xabff\xab\xed\x01\x04\xed\xab\xe6\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01\xcdy\x94\x94y\x19/\b\b\x18\x1aPccP\x1a\x18\x10/\x01\xcfjKKjKKjKKjK\xfd\xfe\x01\x04\xed\xabff\xab\xed\xfe\xfc\xed\xabff\xab\x02@\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x05\x00\x00\xff\x80\x06\x00\x05\x80\x00\x14\x00\x1c\x00$\x004\x00@\x00\x00\x01\x16\x0e\x01&'.\x01\"\x06\a\x0e\x01'.\x017>\x012\x16\x00\x14\x06\"&462\x04\x14\x06\"&462\x00\x10.\x02 \x0e\x02\x10\x1e\x02 >\x01\x12\x10\x02\x04 $\x02\x10\x12$ \x04\x04n\b\x1820\b\x19\x87\xa8\x87\x19\b/\x19\x1a\x18\b%\xca\xfe\xca\xfe7KjKKj\x02KKjKKj\x01Kf\xab\xed\xfe\xfc\xed\xabff\xab\xed\x01\x04\xed\xab\xe6\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x013\x19/\x10\x18\x1aPccP\x1a\x18\b\b/\x19y\x94\x94\x02\tjKKjKKjKKjK\xfd\xfe\x01\x04\xed\xabff\xab\xed\xfe\xfc\xed\xabff\xab\x02@\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x05\x00\x00\xff\x80\x06\x00\x05\x80\x00\v\x00\x13\x00\x1b\x00+\x007\x00\x00\x00\x14\x06#!\"&463!2\x00\x14\x06\"&462\x04\x14\x06\"&462\x00\x10.\x02 \x0e\x02\x10\x1e\x02 >\x01\x12\x10\x02\x04 $\x02\x10\x12$ \x04\x04\x80&\x1a\xfd\x80\x1a&&\x1a\x02\x80\x1a\xfe&KjKKj\x02KKjKKj\x01Kf\xab\xed\xfe\xfc\xed\xabff\xab\xed\x01\x04\xed\xab\xe6\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01\xda4&&4&\x01\xb5jKKjKKjKKjK\xfd\xfe\x01\x04\xed\xabff\xab\xed\xfe\xfc\xed\xabff\xab\x02@\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x04\x00\x00\x00\x00\a\x80\x04\x00\x00#\x00+\x003\x00C\x00\x00\x0154&+\x0154&+\x01\"\x06\x1d\x01#\"\x06\x1d\x01\x14\x16;\x01\x15\x14\x16;\x0126=\x01326\x044&\"\x06\x14\x162\x004&\"\x06\x14\x162$\x10\x00#\"'#\x06#\"\x00\x10\x003!2\x03@\x12\x0e\xc0\x12\x0e\x80\x0e\x12\xc0\x0e\x12\x12\x0e\xc0\x12\x0e\x80\x0e\x12\xc0\x0e\x12\x02@KjKKj\x01KKjKKj\x01K\xfe\xd4\xd4\xc0\x92ܒ\xc0\xd4\xfe\xd4\x01,\xd4\x03\x80\xd4\x01\xc0\x80\x0e\x12\xc0\x0e\x12\x12\x0e\xc0\x12\x0e\x80\x0e\x12\xc0\x0e\x12\x12\x0e\xc0\x12gjKKjK\x01KjKKjK\xd4\xfeX\xfeԀ\x80\x01,\x01\xa8\x01,\x00\x00\x00\x0f\x00\x00\x00\x00\a\x80\x04\x80\x00\v\x00\x17\x00#\x00/\x00;\x00G\x00S\x00_\x00k\x00w\x00\x83\x00\x8f\x00\x9f\x00\xa3\x00\xb3\x00\x00\x01\x15\x14+\x01\"=\x014;\x0127\x15\x14+\x01\"=\x014;\x012'\x15\x14+\x01\"=\x014;\x012\x01\x15\x14#!\"=\x0143!2%\x15\x14+\x01\"=\x014;\x012'\x15\x14+\x01\"=\x014;\x012\x01\x15\x14+\x01\"=\x014;\x012'\x15\x14+\x01\"=\x014;\x012\x01\x15\x14+\x01\"=\x014;\x012\x01\x15\x14+\x01\"=\x014;\x012\x01\x15\x14+\x01\"=\x014;\x012\x05\x15\x14+\x01\"=\x014;\x012\x05\x11\x14+\x01\"=\x014;\x0154;\x012\x13\x11!\x11\x01\x11\x14\x06#!\"&5\x11463!2\x16\x01\x80\x10`\x10\x10`\x10\x80\x10\xe0\x10\x10\xe0\x10\x80\x10`\x10\x10`\x10\x04\x00\x10\xfc\xa0\x10\x10\x03`\x10\xfd\x80\x10`\x10\x10`\x10\x80\x10`\x10\x10`\x10\x01\x80\x10`\x10\x10`\x10\x80\x10`\x10\x10`\x10\x01\x80\x10`\x10\x10`\x10\x01\x80\x10`\x10\x10`\x10\xfe\x00\x10`\x10\x10`\x10\x01\x00\x10`\x10\x10`\x10\x01\x00\x10\xe0\x10\x10p\x10`\x10\x80\xf9\x80\a\x00K5\xf9\x805KK5\x06\x805K\x01p`\x10\x10`\x10\xf0`\x10\x10`\x10\xf0`\x10\x10`\x10\xfd\xf0`\x10\x10`\x10\xf0`\x10\x10`\x10\xf0`\x10\x10`\x10\xfe\xf0`\x10\x10`\x10\xf0`\x10\x10`\x10\xfe\xf0`\x10\x10`\x10\xfe\xf0`\x10\x10`\x10\x01\xf0`\x10\x10`\x10\x10`\x10\x10`\x10\x10\xfe\xa0\x10\x10`\x10\xf0\x10\xfd\x00\x03\x80\xfc\x80\x03\x80\xfc\x805KK5\x03\x805KK\x00\x00\x00\x00\x03\x00@\xff\x80\a\x00\x05\x80\x00\x16\x00*\x00V\x00\x00\x01\x11\x06#\"'.\x01#\"\a\x11632\x1e\x02\x1f\x01\x1632\x01\x14\x06\a\x11\x14\x06+\x01\"&5\x11.\x015462\x16\x05\x11\x14\a\x06\a\x06#\"/\x01.\x02#\"\x04\a\x06#\"'&5\x1147>\x0332\x16\x17\x16327676\x17\x16\x06\x80\xa9\x89R?d\xa8^\xad\xe6\xf5\xbc7ac77\x1c,9x\xfbm#\x1d\x12\x0e@\x0e\x12\x1d#KjK\x05\xc0#\n\aڗXF\x1c@Fp:f\xfe\xf5_\x0f\x12\x10\x10 \x1f#W\x8d\xa4Ip\xc2p&3z\xbc\x16\t\x1f\x1f\x1f\x01\xeb\x02h[ 17\u007f\xfd\xa9q\x0f%\x19\x1b\x0e\x16\x03q#:\x11\xfb\x0e\x0e\x12\x12\x0e\x04\xf2\x11:#5KKu\xfd\x05'\x12\x05\x04t#\x0e!\x1e\x1cX:\t\b\x13%\x02\xe6#\x14\x15+=&>7\x13p\f\x05\x10\x12\x14\x00\x00\x06\x00@\xff\x80\a\x00\x05\x80\x00\x05\x00\v\x00*\x002\x00F\x00r\x00\x00\x015\x06\a\x156\x135\x06\a\x156\x015\x06'5&'.\t#\"\a\x1532\x16\x17\x16\x17\x15\x1632\x135\x06#\"'\x15\x16\x01\x14\x06\a\x11\x14\x06+\x01\"&5\x11.\x015462\x16\x05\x11\x14\a\x06\a\x06#\"/\x01.\x02#\"\x04\a\x06#\"'&5\x1147>\x0332\x16\x17\x16327676\x17\x16\x03@\xb5\xcbͳ\xac\xd4\xd7\x03\xe9\xeb\x95\x14\x13\x058\r2\x13.\x1a,#,\x16\x17\x1a\x13f\xb5k\x13\x14*1x\xad\xa9\x89-!\x94\xfb\xac#\x1d\x12\x0e@\x0e\x12\x1d#KjK\x05\xc0#\n\aڗXF\x1c@Fp:f\xfe\xf5_\x0f\x12\x10\x10 \x1f#W\x8d\xa4Ip\xc2p&3z\xbc\x16\t\x1f\x1f\x1f\x02\x18\xc0\x10e\xb9`\x01\xb0\xc5\bv\xbdo\xfe8\xb8t-\xe0\x06\t\x03\x1c\x06\x18\a\x13\x06\v\x04\x04\x03\xde:5\t\x06\xbc\x11\x02\a\xbd[\b\xc4*\x01\xee#:\x11\xfb\x0e\x0e\x12\x12\x0e\x04\xf2\x11:#5KKu\xfd\x05'\x12\x05\x04t#\x0e!\x1e\x1cX:\t\b\x13%\x02\xe6#\x14\x15+=&>7\x13p\f\x05\x10\x12\x14\x00\x02\x00\r\x00\x00\x06\x80\x043\x00\x14\x00$\x00\x00\t\x01\x06\"/\x01&47\t\x01&4?\x0162\x17\x01\x16\x14\x01\x15\x14\x06#!\"&=\x01463!2\x16\x02I\xfe.\n\x1a\n2\n\n\x01\x89\xfew\n\n2\n\x1a\n\x01\xd2\n\x04-\x12\x0e\xfc@\x0e\x12\x12\x0e\x03\xc0\x0e\x12\x02)\xfe.\n\n2\n\x1a\n\x01\x89\x01\x89\n\x1a\n2\n\n\xfe.\n\x1a\xfe-@\x0e\x12\x12\x0e@\x0e\x12\x12\x00\x00\x00\x00\x03\x00-\xff\x93\aS\x04\xed\x00\x14\x00$\x009\x00\x00%\a\x06\"'\x01&47\x0162\x1f\x01\x16\x14\a\t\x01\x16\x14\t\x01\x0e\x01/\x01.\x017\x01>\x01\x1f\x01\x1e\x01\t\x01\x06\"/\x01&47\t\x01&4?\x0162\x17\x01\x16\x14\x02i2\n\x1a\n\xfe.\n\n\x01\xd2\n\x1a\n2\n\n\xfew\x01\x89\n\x02E\xfe\x8b\x04\x17\f>\r\r\x04\x01u\x04\x17\f>\r\r\x02\x8d\xfe.\n\x1a\n2\n\n\x01\x89\xfew\n\n2\n\x1a\n\x01\xd2\n\x892\n\n\x01\xd2\n\x1a\n\x01\xd2\n\n2\n\x1a\n\xfew\xfew\n\x1a\x04!\xfa\xf5\r\r\x04\x11\x04\x17\r\x05\v\r\r\x04\x11\x04\x17\xfdh\xfe.\n\n2\n\x1a\n\x01\x89\x01\x89\n\x1a\n2\n\n\xfe.\n\x1a\x00\x00\x02\x00\x00\xff\x80\a\x00\x05\xbb\x00\x15\x00;\x00\x00\x01\x15\x14\a\x06#\"'\x01&47\x016\x17\x16\x1d\x01\x01\x06\x14\x17\x01\x14\x0e\x03\a\x06#\"'&7\x12'.\x01'\x15\x14\a\x06#\"'\x01&47\x016\x17\x16\x15\x11\x04\x17\x16\x02\x80'\r\f\x1b\x12\xfe\x00\x13\x13\x02\x00\x1d)'\xfes\x13\x13\x06\r\"+5\x1c\x06\b\x14\x06\x03\x19\x02+\x95@ա'\r\f\x1b\x12\xfe\x00\x13\x13\x02\x00\x1d)'\x01\x9b\xbc\xa9\x01\xc6F*\x11\x05\x13\x02\x00\x134\x13\x02\x00\x1f\x11\x11*E\xfer\x134\x13\xfeM:\x97}}8\f\x11\x01\b\x1a\x01\x90\xa5GO\r\xfb*\x11\x05\x13\x02\x00\x134\x13\x02\x00\x1f\x11\x11*\xfe\xfa\x1c\xc1\xad\x00\x00\x00\x00\x02\x00\x02\xff\xad\x06~\x05\xe0\x00\n\x00(\x00\x00\x01-\x01/\x01\x03\x11\x17\x05\x03'\t\x01\x13\x16\x06#\"'%\x05\x06#\"&7\x13\x01&67%\x13632\x17\x13\x05\x1e\x01\x04\xa2\x01\x01\xfe\x9cB\x1e\x9f;\x01><\f\x01\xf5\xfe\x95V\x05\x16\x17\x11\x17\xfe?\xfe?\x17\x11\x17\x16\x05V\xfe\x94 \x12-\x01\xf6\xe1\x14\x1d\x1c\x15\xe1\x01\xf6-\x12\x02C\xfa4\n<\x01B\xfc=\x1f\xa8\x01cB\x015\xfe\x9e\xfe\f!%\f\xec\xec\f%!\x01\xf4\x01b 7\aI\x01\xc7))\xfe9I\a7\x00\x00\x00\x01\x00\x02\xff\x80\x05\x80\x05\x00\x00\x16\x00\x00\t\x01\x06#\"'.\x015\x11!\".\x0167\x01632\x17\x1e\x01\x05y\xfd\x80\x11(\x05\n\x16\x1b\xfd\xc0\x16#\n\x12\x14\x05\x00\r\x10\x1b\x12\x0f\a\x04\xa3\xfb\x00#\x02\x05#\x16\x02@\x1b,(\n\x02\x80\a\x13\x0e)\x00\x00\x03\x00\x00\xff\x00\x06\x80\x05\x80\x00\x02\x00\x05\x008\x00\x00\x01!\x11\t\x01!\x01\x15\x14\x06+\x01\x15\x14\x06+\x01\"&=\x01!\"&5\x11#\"&=\x0146;\x01546;\x012\x16\x1d\x01!762\x17\x16\x14\x0f\x01\x1132\x16\x02-\x02S\xfd\x80\x02S\xfd\xad\x04\x80\x12\x0e\xe0\x12\x0e\xc0\x0e\x12\xfc\xa0\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\x12\x0e\xc0\x0e\x12\x03S\xf6\n\x1a\n\t\t\xf7\xe0\x0e\x12\x01\x00\x02S\xfd\xda\x02S\xfd`\xc0\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\x12\x0e\x03`\x12\x0e\xc0\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\xf7\t\t\n\x1a\n\xf6\xfc\xad\x12\x00\x00\x00\x04\x00\x00\xff\x80\x04\x00\x05\x80\x00\a\x00\x0f\x00\x17\x00K\x00\x00$4&\"\x06\x14\x162\x124&\"\x06\x14\x162\x044&\"\x06\x14\x1627\x14\x06\a\x02\a\x06\a\x0e\x01\x1d\x01\x1e\x01\x15\x14\x06\"&5467\x11.\x015462\x16\x15\x14\x06\a\x1167>\x055.\x015462\x16\x01 8P88P88P88P\x02\xb88P88P\x984,\x02\xe0C\x88\x80S,4p\xa0p4,,4p\xa0p4,6d7AL*'\x11,4p\xa0p\x18P88P8\x04\xb8P88P8HP88P8`4Y\x19\xfe\xe1\u007f&+(>E\x1a\x19Y4PppP4Y\x19\x034\x19Y4PppP4Y\x19\xfe\x0f\x1a\x1f\x11\x19%*\x0154&#\"\a\x06\a\x06#\"/\x01.\x017\x12!2\x1e\x02\x02\xc0\x18\x10\xf0\x10\x18\x18\x10\xf0\x10\x18\x01<\x1f'G,')7\x18\x10\xf0\x0f\x15\x82N;2]=A+#H\r\x12\f\r\xa4\r\x05\b\xa0\x010P\xa2\x82R\x01\x18\xf0\x10\x18\x18\x10\xf0\x10\x18\x18\x02H6^;<\x1b\x16\x17T\x19\x11\x1f%\x13-S\x93#\x1b:/*@\x1d\x19Z\x10\b}\n\x1e\r\x01\n>h\x97\x00\x00\x00\x02\x00\x00\x00\x00\x02\x80\x05\x80\x00\x1e\x00.\x00\x00%\x15\x14\x06#!\"&=\x0146;\x01\x11#\"&=\x01463!2\x16\x15\x1132\x16\x03\x15\x14\x06#!\"&=\x01463!2\x16\x02\x80&\x1a\xfe\x00\x1a&&\x1a@@\x1a&&\x1a\x01\x80\x1a&@\x1a&\x80&\x1a\xff\x00\x1a&&\x1a\x01\x00\x1a&\xc0\x80\x1a&&\x1a\x80\x1a&\x01\x80&\x1a\x80\x1a&&\x1a\xfd\xc0&\x04f\xc0\x1a&&\x1a\xc0\x1a&&\x00\x00\x02\x00b\x00\x00\x02\x1e\x05\x80\x00\x0f\x00\x1f\x00\x00\x01\x15\x14\x06#!\"&=\x01463!2\x16\x13\x03\x0e\x01#!\"&'\x03&63!2\x16\x02\x00&\x1a\xff\x00\x1a&&\x1a\x01\x00\x1a&\x1e\x1c\x01'\x1a\xff\x00\x1a'\x01\x1c\x01%\x1a\x01@\x1a%\x01 \xe0\x1a&&\x1a\xe0\x1a&&\x04\x06\xfd\x00\x1a&&\x1a\x03\x00\x1a&&\x00\x02\x00\x05\x00\x00\x05\xfe\x05k\x00%\x00J\x00\x00%\x15#/\x01&'#\x0e\x02\a\x06\x0f\x01!53\x13\x03#5!\x17\x16\x17\x16\x1736?\x02!\x15#\x03\x13\x01\x15!'&54>\x0454&#\"\a\x06\a'67632\x16\x15\x14\x0e\x04\a35\x03\x81\xf8\x9f\x18\b\x03\x03\x01\x03\x04\x01\n\x0f\x9b\xfe\xfe\x80Ź\x89\x01\x14\x8b\x02\x15\b\x03\x03\x03\b\x19\x8c\x01\x01}\xb8\xcc\x02\xea\xfd\xfe\x03\x044NZN4;)3.\x0e\x16i\x1a%Sin\x881KXL7\x03觧\xfc*\t\f\x03\a\t\x02\x14\x18\xfa\xa7\x01#\x01\x10\xa8\xe4\x04&\t\f\t\f*\xe4\xa8\xfe\xf5\xfe\xd8\x02\xa7\xce\x1b\x1c\x12@jC?.>!&1'\v\x1b\\%\x1dAwc8^;:+\x0454&#\"\a\x06\a'67632\x16\x15\x14\x0e\x03\a35\x03\x81\xf8\x9f\x18\b\x03\x03\x01\x03\x04\x01\n\x0f\x9b\xfe\xfe\x80Ź\x89\x01\x14\x8b\x02\x15\b\x03\x03\x03\b\x19\x8c\x01\x01}\xb8\xcc\x02\xec\xfd\xfe\x04\x034NZN4;)3.\x0e\x16i\x1a%Pln\x88EcdJ\x04觧\xfc*\t\f\x03\a\t\x02\x14\x18\xfa\xa7\x01#\x01\x10\xa8\xe4\x04&\t\f\t\f*\xe4\xa8\xfe\xf5\xfe\xd8\xd9\xce\x1b-\x01@jC?.>!&1'\v\x1b\\%\x1dAwcBiC:D'P\x00\x00\x00\x02\x00\x01\x00\x00\a\u007f\x05\x00\x00\x03\x00\x17\x00\x00%\x01!\t\x01\x16\x06\a\x01\x06#!\"&'&67\x0163!2\x16\x03\x80\x01P\xfd\x00\xfe\xb0\x06\xf5\x0f\v\x19\xfc\x80&:\xfd\x00&?\x10\x0f\v\x19\x03\x80&:\x03\x00&?\x80\x01\x80\xfe\x80\x045\"K\x1c\xfc\x00,)\"\"K\x1c\x04\x00,)\x00\x00\x01\x00\x00\xff\xdc\x06\x80\x06\x00\x00h\x00\x00\x01\x14\x06#\".\x02#\"\x15\x14\x16\a\x15\"\a\x0e\x02#\"&54>\x0254&#\"\x06\x15\x14\x1e\x02\x15\x14\a\x06#\"'.\x01/\x01\"'\"5\x11\x1e\x02\x17\x16327654.\x0254632\x16\x15\x14\x0e\x02\x15\x14\x163267\x15\x0e\x02\a\x06\x15\x14\x17\x1632>\x0232\x16\x06\x80YO)I-D%n \x01\x16\v\"\u007fh.=T#)#lQTv\x1e%\x1e.%P_\x96\t%\t\r\x01\x02\x02\x02\x1f%\x03\x96_P%.\x1e%\x1evUPl#)#T=@\xe8/\x01\x05\x05\x01\x18#,-\x1691P+R[\x01\xb6Ql#)#|'\x98'\x05\x01\x03\x11\n59%D-I)OY[R+P19\x16-,#\x18\x02\x04\x02\x02\x01\x01\x04\x00\x01\x05\x05\x01\x18#,-\x1691P+R[YO)I-D%95\x1e\x02\x02\x02\x1f%\x03\x96_P%.\x1e%\x1ev\x00\x00\x02\x00\x00\xff\x80\x04\x80\x06\x00\x00'\x003\x00\x00\x01\x15\x14\x00\a\x15!2\x16\x14\x06#!\"&463!5&\x00=\x01462\x16\x1d\x01\x14\x00 \x00=\x01462\x16\x01\x11\x14\x06 &5\x1146 \x16\x04\x80\xfe\xd9\xd9\x01\x00\x1a&&\x1a\xfd\x80\x1a&&\x1a\x01\x00\xd9\xfe\xd9&4&\x01\a\x01r\x01\a&4&\xff\x00\xbc\xfe\xf8\xbc\xbc\x01\b\xbc\x03@\x80\xdd\xfe\xb9\x18\x84&4&&4&\x84\x18\x01G݀\x1a&&\x1a\x80\xb9\xfe\xf9\x01\a\xb9\x80\x1a&&\x01f\xfe\x00\x84\xbc\xbc\x84\x02\x00\x84\xbc\xbc\x00\x03\x00\r\xff\x80\x05s\x06\x00\x00\v\x00C\x00K\x00\x00\x01\a&=\x01462\x16\x1d\x01\x14\t\x01\x15\x14\x06#\"'\a\x1632\x00=\x01462\x16\x1d\x01\x14\x00\a\x15!2\x16\x14\x06#!\"&463!5&'\a\x06\"/\x01&47\x0162\x1f\x01\x16\x14%\x01\x114632\x16\x01\x0fe*&4&\x04i\xfe\x97\xbc\x8476`al\xb9\x01\a&4&\xfe\xd9\xd9\x01\x00\x1a&&\x1a\xfd\x80\x1a&&\x1a\x01\x00}n\xfe\n\x1a\nR\n\n\x04\xd2\n\x1a\nR\n\xfez\xfd\x93\xbc\x84f\xa5\x02Oego\x80\x1a&&\x1a\x805\x02\x1e\xfe\x97\x80\x84\xbc\x13`3\x01\a\xb9\x80\x1a&&\x1a\x80\xdd\xfe\xb9\x18\x84&4&&4&\x84\rD\xfe\n\nR\n\x1a\n\x04\xd2\n\nR\n\x1az\xfd\x93\x02\x00\x84\xbcv\x00\x00\x00\x02\x00\x00\xff\x80\x05\x00\x05\x80\x00\x06\x00\"\x00\x00\x01\x11!\x11676\x13\x11\x14\x0e\x05\a\x06\"'.\x065\x11463!2\x16\x04@\xfe@w^\xeb\xc0Cc\x89t~5\x10\f\x1c\f\x105~t\x89cC&\x1a\x04\x80\x1a&\x02@\x02\x80\xfb\x8f?J\xb8\x03\xb0\xfd\x00V\xa9\x83|RI\x1a\a\x06\x06\a\x1aIR|\x83\xa9V\x03\x00\x1a&&\x00\x00\x00\x00\x04\x00\x00\xff\x00\x06\x80\x06\x00\x00\x03\x00\x13\x00#\x00G\x00\x00\x17!\x11!%\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126%\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126%\x11\x14\x06#!\"&5\x1146;\x01546;\x012\x16\x1d\x01!546;\x012\x16\x1d\x0132\x16\x80\x05\x80\xfa\x80\x01\x80\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x03\x00\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x01\x80L4\xfa\x804LL4\x80^B@B^\x01\x80^B@B^\x804L\x80\x04\x00\xc0\x01 \x0e\x12\x12\x0e\xfe\xe0\x0e\x12\x12\x0e\x01 \x0e\x12\x12\x0e\xfe\xe0\x0e\x12\x12N\xfb\x004LL4\x05\x004L`B^^B``B^^B`L\x00\x00\x00\x02\x00\x03\xff\x80\x05\x80\x05\xe0\x00\a\x00L\x00\x00\x004&\"\x06\x14\x162%\x11\x14\a\x06#\"'%.\x015!\x15\x1e\x01\x15\x11\x14\x06#!\"&5\x114675#\"\x0e\x03\a\x06#\"'.\x017>\x047&5462\x16\x15\x14\a!467%632\x17\x16\x02\x00&4&&4\x03\xa6\f\b\f\x04\x03\xfe@\v\x0e\xff\x00o\x91&\x1a\xfe\x00\x1a&}c ;pG=\x14\x04\x11(\x10\r\x17\x11\f\x05\x138Ai8\x19^\x84^\x0e\x01.\x0e\v\x01\xc0\x03\x04\f\b\f\x05&4&&4&`\xfe\xc0\x10\t\a\x01`\x02\x12\vf\x17\xb0s\xfc\xe0\x1a&&\x1a\x03 j\xa9\x1eo/;J!\b#\a\f2\x18\n KAE\x12*,B^^B!\x1f\v\x12\x02`\x01\a\t\x00\x00\x02\x00$\xff \x06\x80\x05\x80\x00\a\x00-\x00\x00\x004&\"\x06\x14\x162\x01\x14\x02\a\x06\a\x03\x06\a\x05\x06#\"/\x01&7\x13\x01\x05\x06#\"/\x01&7\x1367%676$!2\x16\x05\xa08P88P\x01\x18\x97\xb2Qr\x14\x02\x0e\xfe\x80\a\t\f\v@\r\x05U\xfe\xe7\xfe\xec\x03\x06\x0e\t@\x11\f\xe0\n\x10\x01{`P\xbc\x01T\x01\x05\x0e\x14\x04\x18P88P8\x01\x80\xf9\xfe\x95\xb3P`\xfe\x85\x10\n\xe0\x04\t@\x0e\x12\x01\x14\x01\x19U\x01\t@\x13\x14\x01\x80\x0e\x02\x14rQ\xbb\x8e\x13\x00\x00\x00\x01\x00\x00\x00\x00\x06\xd1\x05\x00\x00\x16\x00\x00\x01\x03!\x136'&+\x01\x03!\x13!\x03!\x13\x03!2\x16\x17\x1e\x01\x06Ѥ\xfe\xb2\xb2\r\x1c\x1b8\xa9\xcc\xfe\xb2\xcc\xfe\xe2\xcc\xfe\xb2̙\x04\xfce\xb1;<*\x02\xfb\xfd\x05\x03@8 !\xfcG\x03\xb9\xfcG\x03\xb9\x01GQII\xbf\x00\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x14\x00 \x00\x00%764'\t\x0164/\x01&\"\a\x01\x06\x14\x17\x01\x162\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x03\x8df\x13\x13\xfe\xcd\x013\x13\x13f\x134\x13\xfe:\x13\x13\x01\xc6\x134\x02\x86\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x8df\x134\x13\x013\x013\x134\x13f\x13\x13\xfe:\x134\x13\xfe:\x13\x02\xd7\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x14\x00 \x00\x00%\x0164'\x01&\"\x0f\x01\x06\x14\x17\t\x01\x06\x14\x1f\x01\x162\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x02\xcd\x01\xc6\x13\x13\xfe:\x134\x13f\x13\x13\x013\xfe\xcd\x13\x13f\x134\x03F\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x8d\x01\xc6\x134\x13\x01\xc6\x13\x13f\x134\x13\xfe\xcd\xfe\xcd\x134\x13f\x13\x02\xd7\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x14\x00 \x00\x00\x01764'\x01&\"\a\x01\x06\x14\x1f\x01\x1627\t\x01\x162\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04\x8df\x13\x13\xfe:\x134\x13\xfe:\x13\x13f\x134\x13\x013\x013\x134\x01\x86\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01\x8df\x134\x13\x01\xc6\x13\x13\xfe:\x134\x13f\x13\x13\x013\xfe\xcd\x13\x01\xd7\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x14\x00 \x00\x00%\x0164/\x01&\"\a\t\x01&\"\x0f\x01\x06\x14\x17\x01\x162\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x03-\x01\xc6\x13\x13f\x134\x13\xfe\xcd\xfe\xcd\x134\x13f\x13\x13\x01\xc6\x134\x02\xe6\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xed\x01\xc6\x134\x13f\x13\x13\xfe\xcd\x013\x13\x13f\x134\x13\xfe:\x13\x02w\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x02\x00\x00\xff@\x05\x80\x05\x80\x00\x11\x00\x16\x00\x00\x017!\x13!\x0f\x01/\x01#\x13\x0535%\x13!'\x01!\x03\x05%\x04j\x10\xfc\x8c/\x02d\x16\xc5\xc4\r\xaf\x16\x01j\x04\x01g2\xfd|\x0f\xfe8\x05\x80\x80\xfd\xbe\xfd\xc2\x03\xab\xaf\xfd\xea\xe455\x8c\xfe\xead\x01c\x02 \xb5\x01\xd5\xfab\xa2\xa2\x00\x00\x00\x01\x00\f\xff@\x06\xf4\x05\x80\x00\x0f\x00\x00\x01!\t\x02\x13!\a\x05%\x13!\x13!7!\x01\x13\x05\xe1\xfe\xf6\xfc\xdc\xfdFG\x01)\x1d\x01\xa6\x01\xe6D\xfbH:\x04\xb9&\xfbH\x05\x80\xfa\xcb\xfe\xf5\x01\v\x01d\x93\xa1\xa1\x01S\x01)\xbf\x00\x00\x00\x02\x00\x00\xff\x10\a\x00\x06\x00\x00\a\x00U\x00\x00\x004&\"\x06\x14\x162\x01\x11\x14\a\x06#\"/\x01\x06\x04 $'\a\x06#\"'&5\x11463!2\x17\x16\x0f\x01\x1e\x01\x17\x11#\"&=\x0146;\x015.\x015462\x16\x15\x14\x06\a\x1532\x16\x1d\x01\x14\x06+\x01\x11>\x017'&763!2\x16\x03\xc0&4&&4\x03f\x14\b\x04\f\v]w\xfeq\xfe4\xfeqw]\t\x0e\x04\b\x14\x12\x0e\x01`\x16\b\b\x0fdC\xf5\x95\xc0\x1a&&\x1a\xc0:F\x96ԖF:\xc0\x1a&&\x1a\xc0\x95\xf5Cd\x0f\b\b\x16\x01`\x0e\x12\x04\xe64&&4&\xfc\xa0\xfe\xa0\x16\b\x02\t]\x8f\xa7\xa7\x8f]\t\x02\b\x16\x01`\x0e\x12\x14\x13\x10d[}\x14\x02\x87&\x1a\x80\x1a&\xa3\"uFj\x96\x96jFu\"\xa3&\x1a\x80\x1a&\xfdy\x14}[d\x10\x13\x14\x12\x00\x01\x00\x00\x00\x00\x04\x80\x06\x00\x00#\x00\x00\x012\x16\x15\x11\x14\x06#!\"&5\x1146;\x01\x114\x00 \x00\x15\x14\x06+\x01\"&54&\"\x06\x15\x11\x04 (88(\xfc@(88( \x01\a\x01r\x01\a&\x1a@\x1a&\x96Ԗ\x03\x008(\xfd\xc0(88(\x02@(8\x01@\xb9\x01\a\xfe\xf9\xb9\x1a&&\x1aj\x96\x96j\xfe\xc0\x00\x00\x00\x00\x05\x00\x00\xff\x80\x06\x00\x05\x80\x00\a\x00\x0f\x00\x17\x00'\x003\x00\x00\x00\x14\x06\"&462\x00\x10& \x06\x10\x16 \x00\x10\x00 \x00\x10\x00 \x00\x10.\x02 \x0e\x02\x10\x1e\x02 >\x01\x12\x10\x02\x04 $\x02\x10\x12$ \x04\x04\x00\x96Ԗ\x96\xd4\x01\x16\xe1\xfe\xc2\xe1\xe1\x01>\x01a\xfe\xd4\xfeX\xfe\xd4\x01,\x01\xa8\x01\xacf\xab\xed\xfe\xfc\xed\xabff\xab\xed\x01\x04\xed\xab\xe6\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02\xeaԖ\x96Ԗ\xfea\x01>\xe1\xe1\xfe\xc2\xe1\x02T\xfeX\xfe\xd4\x01,\x01\xa8\x01,\xfd~\x01\x04\xed\xabff\xab\xed\xfe\xfc\xed\xabff\xab\x02@\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x00\x03\x00\x00\x02\x00\x05\x80\x03\x80\x00\x0f\x00\x1f\x00/\x00\x00\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x05\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x05\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x808(\xc0(88(\xc0(8\x02\x008(\xc0(88(\xc0(8\x02\x008(\xc0(88(\xc0(8\x03 \xc0(88(\xc0(88(\xc0(88(\xc0(88(\xc0(88(\xc0(88\x00\x00\x00\x00\x03\x00\x00\x00\x00\x01\x80\x05\x80\x00\x0f\x00\x1f\x00/\x00\x00\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x11\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x11\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x808(\xc0(88(\xc0(88(\xc0(88(\xc0(88(\xc0(88(\xc0(8\x01 \xc0(88(\xc0(88\x01\xd8\xc0(88(\xc0(88\x01\xd8\xc0(88(\xc0(88\x00\x00\x04\x00\x00\xff\x80\x06\x00\x05\x80\x00\a\x00\x1b\x005\x00E\x00\x00$4&\"\x06\x14\x162%&\x00'&\x06\x1d\x01\x14\x16\x17\x1e\x01\x17\x1e\x01;\x0126%&\x02.\x01$'&\a\x06\x1d\x01\x14\x16\x17\x16\x04\x12\x17\x1e\x01;\x01276\x01\x11\x14\x06#!\"&5\x11463!2\x16\x02\x00KjKKj\x01\xaa\r\xfe\xb9\xe9\x0e\x14\x11\r\x9a\xdc\v\x01\x12\r\x80\r\x14\x01\u007f\x05f\xb1\xe9\xfe\xe1\x9a\x0e\t\n\x12\r\xcc\x01\\\xd1\a\x01\x12\r\x80\r\n\v\x01\x1f\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\xcbjKKjK\"\xe9\x01G\r\x01\x14\r\x80\r\x12\x01\vܚ\r\x11\x14\r\x9a\x01\x1f\xe9\xb1f\x05\x01\n\n\r\x80\r\x12\x01\a\xd1\xfe\xa4\xcc\r\x12\n\t\x03\xcd\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\v\x00\x1b\x00\x00\x00 \x04\x12\x10\x02\x04 $\x02\x10\x12\x0164'\x01&\a\x06\x15\x11\x14\x17\x16327\x02/\x01\xa2\x01a\xce\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x03\xb2 \xfd\xe0\x1f! \x10\x10\x11\x0f\x05\x80\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xfd\x97\x12J\x12\x01@\x13\x12\x13%\xfd\x80%\x13\b\t\x00\x03\x006\xff5\x06\xcb\x05\xca\x00\x03\x00\x13\x00/\x00\x00\t\x0564'\x01&\"\a\x01\x06\x14\x17\x01\x162\t\x01\x06\"/\x0164&\"\a'&47\x0162\x1f\x01\x06\x14\x1627\x17\x16\x14\x04\x00\x01<\xfd\xc4\xfe\xc4\x01i\x02j\x13\x13\xfe\x96\x126\x12\xfd\x96\x13\x13\x01j\x126\x03\x8b\xfcu%k%~8p\xa08}%%\x03\x8b%k%}8p\xa08~%\x04<\xfe\xc4\xfd\xc4\x01<\xfei\x02j\x134\x13\x01j\x12\x12\xfd\x96\x134\x13\xfe\x96\x12\x02\x8f\xfct%%~8\xa0p8~%k%\x03\x8a%%}8\xa0p8}%k\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x1f\x00\x00\x0154&#!\"\x06\x1d\x01\x14\x163!26\x01\x11\x14\x06#!\"&5\x11463!2\x16\x05\x00&\x1a\xfc\x80\x1a&&\x1a\x03\x80\x1a&\x01\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x02@\x80\x1a&&\x1a\x80\x1a&&\x02:\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x03\x00\x00\x00\x00\x05\x80\x05\x80\x00\x0f\x00\x1f\x00/\x00\x00\x01\x15\x14\x06#!\"&=\x01463!2\x16\x13\x114&#!\"\x06\x15\x11\x14\x163!26\x13\x11\x14\x06#!\"&5\x11463!2\x16\x04\x80\x12\x0e\xfc\xc0\x0e\x12\x12\x0e\x03@\x0e\x12\x80^B\xfc\xc0B^^B\x03@B^\x80\xa9w\xfc\xc0w\xa9\xa9w\x03@w\xa9\x02\xe0@\x0e\x12\x12\x0e@\x0e\x12\x12\xfe2\x03@B^^B\xfc\xc0B^^\x03\x82\xfc\xc0w\xa9\xa9w\x03@w\xa9\xa9\x00\x00\x01\x00\x03\x00\x00\x03\xfa\x05\u007f\x00\x1c\x00\x00\x01\x06+\x01\x11\x14\x06#!\"'&?\x0163!\x11#\"'&7\x0162\x17\x01\x16\x03\xfa\x12(\xc0\x12\x0e\xfd@\x15\b\b\f\xa0\t\x10\x01@\xc0(\x12\x11\x1a\x01@\x12>\x12\x01@\x1b\x03\xa5%\xfc\xa0\x0e\x12\x12\x14\x0f\xc0\v\x02\x80%%\x1f\x01\x80\x16\x16\xfe\x80 \x00\x00\x00\x01\x00\x03\xff\x80\x03\xfa\x05\x00\x00\x1b\x00\x00\x13!2\x16\x15\x1132\x16\a\x01\x06\"'\x01&76;\x01\x11!\"/\x01&76 \x02\xc0\r\x13\xc0($\x1b\xfe\xc0\x12>\x12\xfe\xc0\x1a\x11\x12(\xc0\xfe\xc0\x0e\v\xa0\r\t\t\x05\x00\x13\x0e\xfc\xa1J \xfe\x80\x16\x16\x01\x80\x1f&%\x02\x80\v\xc0\x0e\x14\x13\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x14\x00$\x00\x00%\x0164/\x01&\"\a\x01'&\"\x0f\x01\x06\x14\x17\x01\x162\x01\x11\x14\x06#!\"&5\x11463!2\x16\x02\xad\x02f\x13\x13f\x134\x13\xfe-\xd3\x134\x13f\x13\x13\x01f\x134\x03f\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\xed\x02f\x134\x13f\x13\x13\xfe-\xd3\x13\x13f\x134\x13\xfe\x9a\x13\x03\x86\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x05\x00\x00\xff\x80\x06\x00\x05\x80\x00\x06\x00\x10\x00\x15\x00\x1f\x00/\x00\x00\x01\x17\a#5#5\x01\x16\a\x01\x06'&7\x016\t\x03\x11\x01764/\x01&\"\x0f\x01%\x11\x14\x06#!\"&5\x11463!2\x16\x01\x94\x9848`\x01\xd2\x0e\x11\xfe\xdd\x11\r\x0e\x11\x01#\x11\xfe\xfb\x02 \xfe\xe0\xfd\xe0\x03\x80\\\x1c\x1c\x98\x1cP\x1c\\\x02\xa0\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x01\xac\x984`8\x01\xba\r\x11\xfe\xdd\x11\x0e\r\x11\x01#\x11\xfd@\x02 \x01 \xfd\xe0\xfe\xe0\x02`\\\x1cP\x1c\x98\x1c\x1c\\`\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x19\x00)\x00\x00\x01\x114&#!\"\a\x06\x1f\x01\x01\x06\x14\x1f\x01\x1627\x01\x17\x163276\x01\x11\x14\x06#!\"&5\x11463!2\x16\x05\x00&\x1a\xfe *\x11\x11\x1f\x90\xfd\xea\x13\x13f\x134\x13\x02\x16\x90\x12\x1b\f\r'\x01\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x02`\x01\xe0\x1a&')\x1d\x90\xfd\xea\x134\x13f\x13\x13\x02\x16\x90\x13\x05\x11\x02*\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00%\x005\x00\x00\t\x0164'\x01&\a\x06\x1d\x01\"\x0e\x05\x15\x14\x17\x163276'\x027>\x013\x15\x14\x17\x1632\x01\x11\x14\x06#!\"&5\x11463!2\x16\x03\xed\x01`\x13\x13\xfe\xa0\x1e'(w\u0083a8!\n\xa7\v\x0e\a\x06\x16\x03,j.\xa8\x8c(\f\f\x1a\x02&\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x01\xb3\x01`\x134\x13\x01`\x1f\x11\x11*\xa0'?_`ze<\xb5\xdf\f\x03\t\x18\x01bw4/\xa0*\x11\x05\x02\xc0\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x04\x00\x00\xff\x80\x06\x00\x05\x80\x00\x02\x00\x06\x00\x12\x00\x1e\x00\x00\x01-\x01\x01\x11\x01\x11\x00\x10.\x01 \x0e\x01\x10\x1e\x01 6\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x02\x80\x01\x00\xff\x00\x01\x80\xfe\x00\x03 \x92\xfa\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\x01r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01\xc0\x80\x80\x01O\xfd\xe2\xff\x00\x02\x1e\xfe\xdd\x01(\xfa\x92\x92\xfa\xfe\xd8\xfa\x92\x92\x02_\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\r\x00\x1d\x00-\x00\x00\x01\x16\a\x01\x06\"'\x01&763!2\x13\x114&#!\"\x06\x15\x11\x14\x163!26\x01\x11\x14\x06#!\"&5\x11463!2\x16\x04y\x12\x17\xfe\xc0\x13B\x13\xfe\xc0\x17\x12\x11(\x02\x80(\x98\x13\r\xfc@\r\x13\x13\r\x03\xc0\r\x13\x01\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x03]#\x1f\xfe@\x1b\x1b\x01\xc0\x1f##\xfd \x03\xc0\r\x13\x13\r\xfc@\r\x13\x13\x03\xcd\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\r\x00\x1d\x00-\x00\x00\x01\x06#!\"'&7\x0162\x17\x01\x16\x13\x114&#!\"\x06\x15\x11\x14\x163!26\x01\x11\x14\x06#!\"&5\x11463!2\x16\x04y\x11(\xfd\x80(\x11\x12\x17\x01@\x13B\x13\x01@\x17u\x13\r\xfc@\r\x13\x13\r\x03\xc0\r\x13\x01\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x01\xa3###\x1f\x01\xc0\x1b\x1b\xfe@\x1f\xfe\xda\x03\xc0\r\x13\x13\r\xfc@\r\x13\x13\x03\xcd\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\r\x00\x1d\x00-\x00\x00\x00\x14\a\x01\x06'&5\x11476\x17\x01\x13\x114&#!\"\x06\x15\x11\x14\x163!26\x01\x11\x14\x06#!\"&5\x11463!2\x16\x04@\x1b\xfe@\x1f####\x1f\x01\xc0\xdb\x12\x0e\xfc@\x0e\x12\x12\x0e\x03\xc0\x0e\x12\x01\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x02\xa1B\x13\xfe\xc0\x17\x12\x11(\x02\x80(\x11\x12\x17\xfe\xc0\xfd\xec\x03\xc0\x0e\x12\x12\x0e\xfc@\x0e\x12\x12\x03\xce\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x01\x00\x00\x00\x00\x03\xf3\x05\x80\x00`\x00\x00%\x17\x16\x06\x0f\x01\x0e\a#\"\x00'#\"&=\x0146;\x01&7#\"&=\x0146;\x016\x0032\x17\x16\x17\x16\x0f\x01\x0e\x01/\x01.\x05#\"\x06\a!2\x17\x16\x0f\x01\x06#!\x06\x17!2\x17\x16\x0f\x01\x0e\x01#!\x1e\x0132>\x04?\x016\x17\x16\x03\xd0#\x03\f\v\x05\x04\r\x13\x18\x1b!\"'\x13\xea\xfe\xa2?_\r\x13\x13\rB\x02\x03C\x0e\x12\x12\x0ebC\x01a\xe0f\\\v\t\x06\x03+\x03\x16\r\x04\x04\x0f\x14\x19\x1b\x1f\x0e~\xc82\x01\xd4\x10\t\n\x03\x18\x05\x1b\xfe\x18\x03\x03\x01\xcb\x0f\n\t\x03\x18\x02\x12\v\xfe}0\xcb\u007f\x12$\x1f\x1c\x15\x10\x04\x05\r\r\f\xe5\x9f\f\x15\x04\x01\x02\x03\x06\x05\x05\x05\x04\x02\x01\x05\xdd\x13\rq\r\x1390\x12\x0er\x0e\x12\xd2\x01\x00\x17\x03\f\v\r\x9f\r\r\x04\x01\x01\x03\x04\x03\x03\x02\x80p\f\f\x0er\x1a%D\f\f\x0fp\v\x0fu\x89\x03\x04\x05\x05\x04\x01\x02\x05\a\a\x00\x00\x01\x00\x00\x00\x00\x03\xfc\x05\x80\x00?\x00\x00\x01\x11\x14\x06#!\"&=\x0146;\x01\x11#\"&=\x0146;\x0154632\x17\x1e\x01\x0f\x01\x06\a\x06'.\x02#\"\x06\x1d\x01!2\x16\x1d\x01\x14\x06#!\x11!546;\x012\x16\x03\xfc\x12\x0e\xfcD\x0e\x12\x13\ra_\x0e\x12\x12\x0e_\xf7\xbf\xb9\x96\t\x02\bg\t\r\r\n\x05*`-Uh\x011\r\x13\x13\r\xfe\xcf\x01\x9e\x12\x0e\xa2\x0e\x12\x01\x8f\xfe\x91\x0e\x12\x12\x0e\x96\r\x13\x01\u007f\x13\r\x83\x0e\x12߫\xde}\b\x19\n\u007f\v\x01\x02\t\x05\x1c$^L\xd7\x12\x0e\x83\r\x13\xfe\x85\xb5\r\x13\x13\x00\x00\x00\x01\x004\xff\x00\x03\xd2\x06\x00\x00b\x00\x00\x01\x14\x06\a\x15\x14\x06+\x01\"&=\x01.\x04'&?\x01676\x170\x17\x16\x17\x1632654.\x03'.\b5467546;\x012\x16\x1d\x01\x1e\x04\x17\x16\x0f\x01\x06\a\x06'.\x04#\"\x06\x15\x14\x1e\x04\x17\x1e\x06\x03\xd2ǟ\x12\x0e\x87\r\x13B{PD\x19\x05\x11\x0fg\a\x10\x0f\t\x02q\x82%%Q{\x1e%P46'-N/B).\x19\x11ĝ\x13\r\x87\x0e\x129kC<\x12\x06\x11\fQ\b\x0f\x0e\r\x03\x177>W*_x\x11*%K./58`7E%\x1a\x01_\x99\xdd\x1a\xaf\x0e\x12\x13\r\xaf\t,-3\x18\x06\x15\x14\x87\n\x02\x02\v\x02c\x1a\bVO\x1c2\")\x17\x15\x10\x12#\x1b,)9;J)\x8a\xd0\x1e\xb4\r\x13\x12\x0e\xb0\x06\"!*\x10\x06\x12\x14\x92\x0f\x01\x03\n\x03\x12#\x1d\x17VD\x1a,'\x1b#\x13\x12\x14\x17/&>AX\x00\x01\x00\x00\x00\x00\x03\x82\x05\x80\x00>\x00\x00\x01\x15\x14\x06+\x01\x0e\x01\a\x16\x01\x16\a\x06+\x01\"'\x00'&=\x0146;\x01267!\"&=\x01463!&+\x01\"&=\x01463!2\x16\x1d\x01\x14\x06+\x01\x16\x1732\x16\x03\x82\x12\x0e\xa8\x17Ԫ\xa7\x01$\x0e\n\b\x15\xc3\x10\t\xfe\xce\xc0\t\x13\rp\x84\xa1\x16\xfeU\x0e\x12\x12\x0e\x01\x9d9ӑ\r\x13\x12\x0e\x03@\x0e\x12\x12\x0e\xe9/\x11\xab\x0e\x12\x04*f\x0e\x12\x90\xb4\x14\xb2\xfe\x9a\x10\x12\x12\f\x01o\xcc\t\r\u007f\r\x13VR\x12\x0ef\x0e\x12q\x13\r\x85\x0e\x12\x12\x0ef\x0e\x12=S\x12\x00\x01\x00\x04\x00\x00\x03\xff\x05\x80\x00E\x00\x00!#\"&5\x11!\"&=\x01463!5!\"&=\x0146;\x01\x01&76;\x012\x17\x13\x16\x17>\x017\x136;\x012\x17\x16\a\x0132\x16\x1d\x01\x14\x06#!\x15!2\x16\x1d\x01\x14\x06#!\x11\x14\x06\x02[\xac\r\x13\xfe\xe0\r\x13\x13\r\x01 \xfe\xe0\r\x13\x13\r\xd6\xfe\xbf\b\b\n\x12\xc2\x13\n\xd7\x13%\n)\a\xbf\b\x15\xbf\x11\n\t\b\xfe\xc7\xd7\r\x13\x13\r\xfe\xde\x01\"\r\x13\x13\r\xfe\xde\x13\x12\x0e\x01J\x12\x0eg\r\x13U\x12\x0eh\r\x13\x02B\x10\x10\x10\x12\xfeW&W\x18X\x11\x01\xa4\x13\x10\x0e\x11\xfd\xbd\x13\rh\x0e\x12U\x13\rg\x0e\x12\xfe\xb6\r\x13\x00\x02\x00\x00\x00\x00\x05\x00\x05\x80\x00\a\x008\x00\x00\x004&#!\x11!2\x00\x10\x06#!\x15!2\x16\x1d\x01\x14\x06#!\x15\x14\x06+\x01\"&=\x01#\"&=\x0146;\x015#\"&=\x0146;\x01\x11463!2\x04\x13\x82j\xfe\xc0\x01@j\x01o\xfd\xc8\xfe\xac\x01\xf9\x0e\x12\x12\x0e\xfe\a\x13\r\xa7\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\xe0\x0e\x12\x12\x0e\xe0\x12\x0e\x02\x1b\xc8\x03g\xc8|\xfe@\x01\xa1\xfe~\xf4v\x12\x0e\x80\x0e\x12\xc0\x0e\x12\x12\x0e\xc0\x12\x0e\x80\x0e\x12v\x12\x0e\x95\r\x13\x02u\x0e\x12\x00\x06\x00\x00\x00\x00\a\x00\x05\x80\x00\b\x00\f\x00\x10\x00\x19\x00\x1d\x00n\x00\x00\x01\x13#\x13\x16\x14\x1746\x137!\x17!3'#\x01\x13#\x13\x14\x16\x1746\x137!\x17\x05\x15\x14\x06+\x01\x03\x06+\x01\"'\x03#\x03\x06+\x01\"&'\x03#\"&=\x0146;\x01'#\"&=\x0146;\x01\x03&76;\x012\x17\x13!\x136;\x012\x17\x13!\x136;\x012\x17\x16\a\x0332\x16\x1d\x01\x14\x06+\x01\a32\x16\x02\x02Q\x9fK\x01\x01\x01t#\xfe\xdc \x01\xa1\x8b#F\x01\x9fN\xa2Q\x01\x01\x01o!\xfe\xd7\"\x02\x80\x12\x0eդ\a\x18\x9f\x18\a\xa6ѧ\a\x18\x9f\v\x11\x02\xa0\xd0\x0e\x12\x12\x0e\xaf!\x8e\x0e\x12\x12\x0emY\x05\n\n\x10\x89\x1a\x05Z\x01ga\a\x18~\x18\ab\x01m]\x05\x1a\x89\x10\n\n\x05[o\x0e\x12\x12\x0e\x91\"\xb3\x0e\x12\x01U\x01+\xfe\xd4\x01\x04\x01\x01\x05\x01\xac\x80\x80\x80\xfd\xd4\x01,\xfe\xd5\x01\x05\x01\x01\x04\x01\xad\x80\x80 @\x0e\x12\xfd\x98\x18\x18\x02h\xfd\x98\x18\x0e\n\x02h\x12\x0e@\x0e\x12\x80\x12\x0e@\x0e\x12\x01X\x0f\r\f\x18\xfe\x98\x01h\x18\x18\xfe\x98\x01h\x18\f\r\x0f\xfe\xa8\x12\x0e@\x0e\x12\x80\x12\x00\x00\x03\x008\xff\x00\x04\xe8\x05\x80\x003\x00H\x00\\\x00\x00\x01\x16\a\x1e\x01\a\x0e\x04\a\x15#5\"'\x15#\x11\"&+\x017327\x113&#\x11&+\x015\x172753\x156353\x15\x1e\x03\x034.\x04\"\x06#\x112\x162>\x06\x034.\x04\x0e\x01#\x112\x16>\x06\x04\x8f\x12\x95ut\r\a3Nt\u007fR\x9aP*\x9a\x12H\x13\xc8\x1fo2\b\x10\x06\n\rLo\xd4@!\x9aR(\x9aOzh=\xd1\x1e,GID2F\xfd\x9e\n\xfe\xc1\n\r\f\v\xfe\xc0\x0f\b\b\x16\xc0\x12\x0e\xc0\x0e\x12\xc0\x0e\x12\x02\xee\x1a8PuE>.\x18\x12'\x0f\x10%&Te\x10\x02\x15Q,j\x86\x90m{\xa4\x1e\xfe+\xa7\x01\x02\a\b\x12>R\xc0{\xdf?jJrL6V\f\f\xfe\xc1\t\t\x01@\x10\x13\x14\x05`\x0e\x12\x12\x0e\xfa\xa0\x127>wmR1\x10\b\aq\a\x04\ruW\x17\x1c\x8fei\x92\xbd\x02/rr\x01\xb0\a\x18\x05\x10\f\r\x12:V\xb9\xfdr\x00\x00\x00\x00\x04\x00\"\xff\x00\x05\xce\x06\x00\x00\n\x00$\x007\x00V\x00\x00\x014&#\"\x06\x14\x16326\x01\x14\a\x01\x06#\"'\x01&76;\x01\x1146;\x012\x16\x15\x1132\x16\x05\x15!53\x1146=\x01#\a\x06\x0f\x01'73\x11\x13\x14\x0e\x03#\"'&'7\x16\x17\x163267#\x0e\x01#\"&54632\x16\x05BX;4>ID2F\xfd\x9e\n\xfe\xc1\n\r\f\v\xfe\xc0\x0f\b\b\x16\xc0\x12\x0e\xc0\x0e\x12\xc0\x0e\x12\x02\xd0\xfe+\xa7\x01\x02\a\b\x12>R\xc0{\xc3\x1a8PuE>.\x18\x12'\x0f\x10%&Te\x10\x02\x15Q,j\x86\x90m{\xa4\x04\xdf?jJrL6\xfb\xaa\f\f\xfe\xc1\t\t\x01@\x10\x13\x14\x05`\x0e\x12\x12\x0e\xfa\xa0\x12\xfcrr\x01\xb0\a\x18\x05\x10\f\r\x12:V\xb9\xfdr\x053>wmR1\x10\b\aq\a\x04\ruW\x17\x1c\x8fei\x92\xbd\x00\x00\x03\x00\x00\xff\x80\x06@\x05\x80\x00\v\x00\x1b\x00\\\x00\x00%4&#\"\x06\x15\x14\x16326\x13\x11\x14\x06#!\"&5\x11463!2\x16\x05\x14\a\x16\x15\x16\a\x16\a\x06\a\x16\a\x06\a+\x02\".\x01'&'.\x015\x11467>\x01767>\x027>\x027632\x1e\x05\x15\x14\x0e\x01\a\x0e\x02\a!2\x16\x01\x00&\x1a\x1b%%\x1b\x1a&\xa0&\x1a\xfe\xe0\x1a&&\x1a\x01 \x1a&\x04\xa07\x0f\x03.\x11\x11\x0f'\t:@\x85$L\x11B\x9cWM{#\x1a&$\x19\x18h1D!\x12\x1a\t\t\a\v\x1c\x14\x13\x1a.I/!\x0f\t\x01\x13\x13\x12\x03\x0e\b\x04\x01\x15Nr\xc0\x1a&&\x1a\x1b%%\x02\x1b\xfd\x80\x1a&&\x1a\x02\x80\x1a&&\x1aV?, L=8=9%pEL\x02\x1f\x1b\x1a+\x01\x01%\x1a\x02\x81\x19%\x02\x02r@W!\x12<%*',<\x14\x13\x15\x1f2(<\x1e\x18&L,\"\x06\x18\x14\x0er\x00\x00\x00\x00\x03\x00\x00\xff\x00\x06@\x05\x00\x00\v\x00\x1b\x00\\\x00\x00\x01\x14\x06#\"&54632\x16\x13\x114&#!\"\x06\x15\x11\x14\x163!26%\x16\x15\x0e\x01#!\x1e\x02\x17\x1e\x02\x15\x14\x0e\x05#\"'.\x02'.\x02'&'.\x01'.\x015\x1146767>\x02;\x03\x16\x17\x16\a\x16\x17\x16\a\x16\a\x14\x01\x00&\x1a\x1b%%\x1b\x1a&\xa0&\x1a\xfe\xe0\x1a&&\x1a\x01 \x1a&\x04i7\x01qN\xfe\xeb\x04\b\x0e\x03\x12\x12\x14\x01\t\x0f!/I.\x1a\x13\x14\x1c\v\a\t\t\x1a\x12!D1h\x18\x19$&\x1a#{MW\x9cB\x11L$\x85@:\t'\x0f\x11\x11.\x03\x03\xc0\x1a&&\x1a\x1b%%\xfd\xe5\x02\x80\x1a&&\x1a\xfd\x80\x1a&&\xaf=XNr\x0e\x14\x18\x06%(M&\x18\x1e<(2\x1f\x15\x13\x14<,'*%<\x12!W@r\x02\x02%\x19\x02\x81\x1a%\x01\x01+\x1a\x1b\x1f\x02LEp%9=8=L \x00\x00\f\x00\x00\xff\x80\x06\x00\x05\x80\x00\t\x00\x0f\x00\x17\x00+\x00=\x00\\\x00d\x00\u007f\x00\x8c\x00\x9e\x00\xb2\x00\xc2\x00\x00%54#\"\a\x15\x16327354\"\x15%\x15#\x11#\x11#5\x05\x11#5\x06#\"'&5\x113\x11\x14\x17\x16327\x11\x05\x15\x14\a\x06#\"'\x15#\x113\x15632\x17\x16\x17\x15\x14\a\x06\a\x06#\"'&=\x014762\x17\x16\x1d\x01#\x15\x143274645\x01\x15\x14\"=\x0142\x014'.\x01'&! \a\x0e\x01\a\x06\x15\x14\x17\x1e\x01\x17\x16 7>\x0176\x01\x13#\a'#\x1e\x01\x17\x16\x17\x153%54'&#\"\a\x06\x1d\x01\x14\x17\x163276\x173\x11#\x11\x06#\"'&5\x11#\x11\x14\x17\x16327\x01\x11\x14\x06#!\"&5\x11463!2\x16\x03\x97\x1d\x11\x10\x10\x11\x1d\xb8BB\xfd\xc5PJN\x01\xb1C'%!\t\x06B\x01\x01\x0e\x14\x16\x01?\a\f)#!CC $)\f\a\xfb\x02\x03\f\x1b54\x1d\x15\x14\x1df\x1b\x15\x85\"\x18\x06\x01\xfe\x81@@\x02\x15\x13\nB+\x88\xfe\xec\xfe\xed\x88,A\n\x14\x14\nA+\x89\x02&\x89+A\n\x14\xfd\rZK35N\a \b#\vJ\x01!\x15\x1d13\x1b\x15\x15\x1b31\x1d\x15\xb5CC\x16\x14\x0f\x01\x01C\x06\v $)\x01\xf7\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\xe9\x9d2\x10\xe0\x10\xab\"33\xe8F\xfeY\x01\xa7F~\xfe\x91(-\x1c\x11%\x01\"\xfe\xf2\x18\x02\x0f\x1f\x01\x18o\x924\x15*)$\x01\xed\xa1(*\x15\xb6\t\x1d\x0e\x16\x12(&\x1b;\x81;\x1b&&\x1d9LA3\x1a\x01\f\x15\v\x038\x9c33\x9c4\xfd\x03\xb1S,;\x05\x0f\x0f\x05;,W\xad\xb0T+<\x05\x0f\x0f\x05<+T\x03;\x01(\xc3\xc3\x17\\\x17g7\xc9x\x82:\x1d&&\x1d:\x82:\x1d&&\x1b<\x01r\xfe\xe5\x1f\x10\x02\x18\x01\x10\xfe\xdb%\x12\x1b-\x01\b\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\v\x00\x1b\xff\x00\x05\xe5\x06\x00\x00\t\x00\x0f\x00\x17\x00+\x00=\x00[\x00c\x00}\x00\x89\x00\x9b\x00\xaf\x00\x00\x01\x15\x14#\"'\x11632\x05\x15#542%35!\x153\x113!3\x11#\x11\x06#\"'&5\x11#\x11\x14\x17\x16327%54'&#\"\a5#\x1135\x163276%5#\x14\a\x06#\"=\x01354'&#\"\a\x06\x1d\x01\x14\x17\x16327676\x0154\"\x1d\x01\x142\x01\x14\a\x0e\x01\a\x06 '.\x01'&547>\x0176 \x17\x1e\x01\x17\x16\x013\x03\x11#\x11&'&'3\x13\x05\x15\x14\a\x06#\"'&=\x0147632\x17\x16%\x11#5\x06#\"'&5\x113\x11\x14\x17\x16327\x11\x03\xcb'\x17\x16\x16\x17'\x01RZZ\xfc:k\xfe\xc8id\x01 YY\x1e\x1b\x12\x03\x01Y\b\f.06\x01\xad\t\x1162+YY-06\x11\t\x01R[\x02\a!.\xb3\x1b'CD'\x1c\x1d'EH$\x12\x03\x02\xfd\xa0VV\x02\xcf\x1a\x0eX:\xb8\xfd\x1a\xb8:Y\r\x1a\x1a\x0eX;\xb7\x02\xe6\xb8:Y\r\x1a\xfc\x1afyd\x0e/%\x1cjG\x01\xb6\x1c&DC&\x1c\x1c&CD&\x1c\x01O[52.\r\b[\x01\x03\x12\x1b\x1e\x01$\xd3C\x16\x01-\x16D..D\x96^^\xfd\xc7\x01\xee\xfe\x86*\x15\x03 \x01l\xfey1\x18%=^\xc5I\x1a86\xd9\xfdi077\x1bS\r3\n$EWgO%33%O\xadO%35\x1b\x1b\t\x03\xc2\xd2EE\xd2F\xfdW\xeat;P\x06\x15\x15\x06P;p\xee\xeat;P\a\x14\x14\aP;p\x04\x0e\xfeq\xfe\xf1\x01\x0fJ\x8agT\xfe\xf9F\xafQ%33&P\xafP%33%R\xfe\r7>%\x183\x01\x8a\xfe\x91!\x02\x16+\x01}\x00\x00\x02\x00\x05\xff\x80\x05{\x05\xf6\x00\x13\x00'\x00\x00\x01\x06\x03\x06+\x01\"&7\x132'\x03&76;\x012\x17\x01\x16\a\x01\x15\x01\x16\a\x06+\x01\"'\x016\x016;\x012\x02U\n\xf7\x1b&\xef\x15\x14\n\xfd\x01\x01\xa1\f\v\t\x17\xef(\x1a\x03\xca\v\v\xfd\xf0\x01P\v\n\n\x16\xef*\x18\xfe\xad\x12\x02\x01\x19'\xf1\x16\x03e\x12\xfeJ.\"\x13\x01\xc0\x01\x01\x17\x16\x0f\x0f-\x01d\x10\x15\xfcZ\x01\xfd\x99\x14\x11\x0f-\x02n \x03\x8e-\x00\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x13\x00'\x007\x00\x00\x014'&+\x01\"\a\x06\x1f\x01\x15\x03\x06\x17\x16;\x0127\x01&+\x01\"\a\x01\x16\x01\x16;\x01276'\x015\x016\x17\x11\x14\x06#!\"&5\x11463!2\x16\x02\xad~\x15\x1f\xb8\x12\b\a\b}\xc4\t\t\b\x10\xb9\x1f\x13\x037\a\x11\xbb\x1e\x13\xfee\x01\x01\x05\x14 \xb8\x12\a\b\t\xfe\xfc\x01\x99\b۩w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x03\x03\x01\xdd\"\v\f\x11\xd8\x01\xfe\xa6\x0e\x0e\r$\x03Q\f#\xfd'\x02\xfe!#\f\r\x0f\x01\xdc\x01\x02\xd3\x10\x88\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x00\x02\x00\x00\x00\n\a\x00\x04\xf6\x00\x02\x00I\x00\x00\x01-\x01\x132\x04\x1f\x012\x1e\x05\x17\x1e\x02\x17\x1e\x01\x17\x1d\x01\x16\a\x0e\x01\x0f\x01\x0e\x06#\x06!&$/\x02.\x02'.\x02'.\x01'=\x01&7>\x01?\x01>\x0636\x02\xc7\x01\xe4\xfe\x1c\xb9\xa8\x019II\x01 \x0e!\x18 \x1e\x0e\x06\x13'\a\b\t\x01\x01\x13\a$\x0e\x0e\x0e\x1e \x18!\x0f\x1f\x01\xfb\xfe\x88\xcf\xfe\xcf01$$%A\x18\x06\x13'\a\b\t\x01\x01\x13\a$\x0e\x0e\x0e\x1e \x18!\x0e \x01\xfb\x01\x98\xfa\xfd\x01g\t\x05\x04\x03\x03\x06\n\x10\x17\x0f\x06\x19\\7@\x91)(\x88\x91\x917Y\x11\x11\x0f\x17\x0f\n\x06\x03\x03\x13\x02\t\x03\x04\x04\x05\n \x19\x06\x19\\7@\x91)(\x88\x91\x917Y\x11\x11\x0f\x17\x10\n\x06\x03\x03\x12\x00\x00\x05\x00@\xff\x80\x06\xc0\x05\x8a\x00\x03\x00\x13\x00\x17\x00\x1b\x00\x1f\x00\x00\t\x04\x15\x01\x15'\a5\x015\x17\x015\x177\x15\t\f\x01\x92\x01\xee\xfe\xaa\xfe\x16\x05,\xfe\x16\x01\x01\xfe\x17\x93\x01V\x01\x01\x01W\xfdQ\x01V\xfe\x12\xfe\xae\x05.\x01R\xfe\x17\xfe\xa9\x01W\x01\xe9\xfe\xae\xfe\x12\x03=\xfe\xcf\xfe\xe3\x01?\xfe\xe4l\xfe\xdb\x01\x01\x01\x01\x01%l`\x01\x1c\x02\x01\x01\x02\xfe\xe4\x04\xd8\xfe\xe3\xfe\xd0\x01\x0e\xfe\xf2\xfe\xf1\xfe\xc1\x01\x1d\x03~\xfe\xc1\xfe\xf2\x010\x00\x06\x00\v\xff\x00\x05\xf5\x06\x00\x00\a\x00\v\x00\x0f\x00\x13\x00\x17\x00\x1b\x00\x00\x05!\x11#\x11!\x11#%7\x05\a\x017\x01\a\x017\x01\a\x03\x01\a\t\x015!\x15\x05\t\xfb\xa2\xa0\x05\x9e\xa0\xfcR!\x03\x0f!\xfdXC\x02\xd5C\xfd\xf4f\x02ff\xd9\x01݀\xfe#\xfd\xb2\x03 `\x01\xe0\xfd\x80\x02\x80,\x9d\xa5\x9c\x02\x1a\x92\xfe\xad\x91\x02\xb6{\xfd\xff{\x03{\xfd\u007f`\x02\x81\xfa\xa1\x9f\x9f\x00\x00\x00\x05\x00\x00\xff\x80\x06\x00\x05\x80\x00\a\x00\x0f\x00\x17\x00O\x00g\x00\x00\x004&\"\x06\x14\x162\x00\x10\x06 &\x106 $\x14\x06\"&462$\"&\x0e\x02\a\x0e\x01\a\x0e\x03\x16\x14\x06\x1e\x02\x17\x1e\x01\x17\x1e\x0362\x16>\x027>\x017>\x03&46.\x02'.\x01'.\x03\x00\x10\a\x0e\x01\a\x06 '.\x01'&\x107>\x0176 \x17\x1e\x01\x17\x04\x00\x96Ԗ\x96\xd4\x01 \xe6\xfe\xb8\xe6\xe6\x01H\x01R6L66L\xfeG\x0e\x8bHyU\x1d2L\x14\v\x0f\x05\x01\x01\x01\x01\x05\x0f\v\x14L2\x1dUyH\x8b\x0e\x8bHyU\x1d2L\x14\v\x0f\x05\x01\x01\x01\x01\x05\x0f\v\x14L2\x1dUyH\x02n\x05\n\xe4\xd0X\xfe6X\xd0\xe4\n\x05\x05\n\xe4\xd0X\x01\xcaX\xd0\xe4\n\x02\x16Ԗ\x96Ԗ\x01\xa4\xfe\xb8\xe6\xe6\x01H\xe66L66L6\x80\x01\x01\x05\x0f\v\x14L2\x1dUyH\x8b\x0e\x8bHyU\x1d2L\x14\v\x0f\x05\x01\x01\x01\x01\x05\x0f\v\x14L2\x1dUyH\x8b\x0e\x8bHyU\x1d2L\x14\v\x0f\x05\x01\xfen\xfe6X\xd0\xe4\n\x05\x05\n\xe4\xd0X\x01\xcaX\xd0\xe4\n\x05\x05\n\xe4\xd0\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x17\x00\x1f\x00\x00\x012\x16\x15\x11\x14\x06#!\"&5\x11463\x004&\"\x06\x14\x162$4&\"\x06\x14\x162\x04\xe0w\xa9\xa9w\xfc@w\xa9\xa9w\x01\x9a|\xb0||\xb0\x02\xb0|\xb0||\xb0\x05\x80\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\xfc\xa8\xb0||\xb0||\xb0||\xb0|\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x02\x00\t\x00\x15\x00\x00\x01\x13!\x053\t\x0137!\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x03\x00\xc9\xfen\x026^\xfe5\xfe5^h\x02\n\x01\xfb\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x03\x92\xfe\xce\xe0\x02\xb3\xfdM\xa0\x011\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x05\x00\x00\xffP\x05\x81\x05\xa3\x00\n\x00\x16\x00*\x00C\x00g\x00\x00\x01\x16\x06'.\x01676\x1e\x01\x17.\x01\a\x0e\x01\x17\x1e\x017>\x01\x13.\x02'$\x05\x0e\x02\a\x1e\x02\x17\x167>\x02\x13\x0e\x03\a\x0e\x01&'.\x03'&'?\x01\x16 7\x1e\x01\x06\x13\x06\x03\x0e\x02\a\x06%&'.\x04'.\x03'>\x04767$\x05\x16\x17\x1e\x01\x03/\bu5'\x1d\x1c&$I7o\x0e\xc6b?K\x03\x04\x93\\[z\xe4\x14H,1\xfe\xdd\xfe\xed+.@\x12\x1e\\7<\xe4\xdc?5\\V\b\x0f\r,$V\xcf\xc5g.GR@\x14\x19 \x06\x12\xdf\x027\xe0\x15\x06\x10\xb5\x1aU\x05,+!\xfc\xfe\x9a\xf8\x92\x0f\x15\r\x05\a\x02\t#\x15\x1a\t\x03\x1d\"8$\x1e}\xbc\x01{\x01)\x9b<\x10\x01\x02\xa5?L \x11RR\x11\x12\f;\x11kr,\x1cyE[\x80\b\b\x98\x02z\x1b#\t\b/1\a\n\"\x1a\x1c#\t\a\x1d\x1c\b\b#\xfc\x12\x1aeCI\x140/\x03\x11\b\x14\"5#`\xc4\x10\t\x94\x94\x06\"8\x03\xb8\xa7\xfe\x18\x1e4\x1c\x11~&\x1bp\f\x1d)\x1b4\t2\xc8{\xacH\x1a-\x1e\x1e\x0f\v.\x12%W.L\x14>\x00\x06\x00\x00\xff\x80\x06\x00\x05\x80\x00\b\x00\x13\x00'\x00:\x00Y\x00i\x00\x00\x014&\a\x06\x16\x17\x1667\x16\x0e\x01&'&676\x16\x13\x0e\x02\a\x06'.\x02'>\x0276\x17\x1e\x02\x1346&'\x06 '\x0f\x01\x16\x17\x16\x17\x167>\x02\x136'&'&\x05\x06\a\x0e\x02\a\x1e\x02\x17\x1e\x03\x17\x16\x17\x047>\x027\x12\x01\x11\x14\x06#!\"&5\x11463!2\x16\x03PR$+\x01+'TJ\bX\x84j\x03\x027-F\x8f\xb6\x14C',\x9b\xa9,&C\x15\r.\"\x1e\xc6\xd2!$28\v\x05\x0f\xa1\xfeh\xa2\f\x05\x1a\x0f/\x9d\xf9\xb3\"\x1e\x0f\x87\t\x11+p\xd8\xfe\xf1\x84^&+3\x04\b\x16$\x06\x01\b\x06\x12\ri\xb3\x01\x03\xb5\x18\x1f\x1f\x040\x01(\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x02\x9a+.\x16\x14i\x12\x176=Bn\f\\C1X\x14\x1fR\x01:\x15\x1a\x06\x05\x14\x14\x06\a\x19\x14\x13\x18\a\x05#\"\x05\a\x19\xfd\x03\a'\x19\x04jj\x06\f\x9a8Q\x1b.c\x13Aj\x02\xc75\x167!?\x1b\f\"\x0f\x140\x1eD\x8c\xca$\x054\x14\"\vP\x14\x1c[\r\x14&\x15\x01\v\x012\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x00\x01\x00D\xff\x80\x04\x00\x06\x00\x00\"\x00\x00%\x17\x0e\x01\a\x06.\x035\x11#5>\x047>\x01;\x01\x11!\x15!\x11\x14\x1e\x0276\x03\xb0P\x17\xb0Yh\xadpN!\xa8HrD0\x14\x05\x01\a\x04\xf4\x01M\xfe\xb2\r C0N\xcf\xed#>\x01\x028\\xx:\x02 \xd7\x1aW]oW-\x05\a\xfeX\xfc\xfd\xfa\x1e45\x1e\x01\x02\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x1f\x00/\x00\x00%'\x06#\x06.\x025\x11!5!\x11#\"\a\x0e\x03\a\x153\x11\x14\x1e\x027>\x01\x01\x11\x14\x06#!\"&5\x11463!2\x16\x04p>,;$4\x19\n\x01\x01\xff\x00\xbc\b\x01\x05\x195eD\x82+W\x9bcE\x87\x01\xa2\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9K\xb7\x16\x01\x17()\x17\x01\x8e\xc2\x01F\n,VhV\x19\xa5\xfe^9tjA\x02\x010\x04/\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x01\x00\x03\xff@\x02\xfd\x06\x00\x00\x17\x00\x00\x00\x16\a\x01\x06#\"'\x01&76;\x01\x1146;\x012\x16\x15\x113\x02\xf5\x10\r\xfe\xa2\n\r\x0e\n\xfe\x9d\r\b\t\x14\xe0\x12\x0e\xc0\x0e\x12\xe0\x01\x00&\x10\xfe\x80\n\n\x01\x80\x10\x13\x13\x04\xe0\x0e\x12\x12\x0e\xfb \x00\x00\x00\x01\x00\x03\xff\x00\x02\xfd\x05\xc0\x00\x17\x00\x00\x01\x06+\x01\x11\x14\x06+\x01\"&5\x11#\"&7\x01632\x17\x01\x16\x02\xfd\t\x14\xe0\x12\x0e\xc0\x0e\x12\xe0\x15\x10\r\x01^\n\r\x0e\n\x01c\r\x04\x13\x13\xfb \x0e\x12\x12\x0e\x04\xe0&\x10\x01\x80\n\n\xfe\x80\x10\x00\x00\x00\x00\x01\x00@\x01\x03\a\x00\x03\xfd\x00\x17\x00\x00\x01\x15\x14\x06#!\x15\x14\x06'\x01&547\x016\x17\x16\x1d\x01!2\x16\a\x00\x12\x0e\xfb &\x10\xfe\x80\n\n\x01\x80\x10\x13\x13\x04\xe0\x0e\x12\x02\xe0\xc0\x0e\x12\xe0\x15\x10\r\x01^\n\r\x0e\n\x01b\x0e\b\t\x14\xe0\x12\x00\x00\x00\x01\x00\x00\x01\x03\x06\xc0\x03\xfd\x00\x17\x00\x00\x01\x14\a\x01\x06'&=\x01!\"&=\x01463!546\x17\x01\x16\x06\xc0\n\xfe\x80\x10\x13\x13\xfb \x0e\x12\x12\x0e\x04\xe0&\x10\x01\x80\n\x02\x83\x0e\n\xfe\x9e\x0e\b\t\x14\xe0\x12\x0e\xc0\x0e\x12\xe0\x15\x10\r\xfe\xa2\n\x00\x00\x00\x02\x00\x00\xff\x80\x05q\x06\x00\x00&\x008\x00\x00\x01\x06\a\x06#\"'&#\"\a\x06#\"\x03\x02547632\x17\x16327632\x17\x16\x17\x06\a\x06\x15\x14\x16\x01\x14\a\x06\a\x06\a\x06\a6767\x1e\x01\x17\x14\x16\x05q'T\x81\x801[VA=QQ3\x98\x95\x93qq\xabHih\"-bfGw^44O#A\x8a\xfe\xe1\x1d\x1e?66%C\x03KJ\xb0\x01\x03\x01\x01\x01A}}\xc4 !\"\x01\x03\x01\x05\xf2䒐\x1e\x1e\"\"A$@C3^q|\xc6\x04z=KK?6\x12\v\x06\x95lk)\x03\x10\x03\x04\f\x00\x00\x04\x00\x00\xff\x00\x06\x80\x05\x80\x00\x03\x00\a\x00\v\x00\x0f\x00\x00\x01\x11%\x11\x01\x11!\x11\x01\x11%\x11\x01\x11!\x11\x02\xaa\xfdV\x02\xaa\xfdV\x06\x80\xfcu\x03\x8b\xfcu\x02\x12\xfdu^\x02-\x02\xe7\xfdm\x025\xfdw\xfc\xee}\x02\x95\x03n\xfc\xe6\x02\x9d\x00\x00\x00\x06\x00\x00\xff\x00\x05\x80\x05~\x00\a\x00\x0f\x00\x1c\x007\x00M\x00[\x00\x00\x00264&\"\x06\x14\x04264&\"\x06\x14\x052\x16\x15\x11\x14\x06\"&5\x1146\x05\x11\x14\x06+\x01\x15\x14\x06\"&=\x01#\x15\x14\x06#\"&5'#\"&5\x11\x01\x1e\x01\x15!467'&76\x1f\x0162\x1776\x17\x16\a\x01\x11\x14\x06#\"&5\x114632\x16\x01\xdd \x17\x17 \x16\x01\xbc \x16\x16 \x17\xfc\xfb*<;V<<\x04O@-K\x03<\x01&\x014'>\x03&4.\x02'.\x01'\x16\x17\x16\a\x06\a\x06.\x01'.\x04'.\x03'&6&'.\x01'.\x01676\x16\a\x06\x167645.\x03'\x06\x17\x14#.\x01\x06'6&'&\x06\a\x06\x1e\x017676\a\"&'&6\x172\x16\x06\a\x06\a\x0e\x01\a\x0e\x01\x17\x1e\x03\x17\x167>\x0376\x17\x1e\x01\x06\a\x0e\x01\a\x06\a\x06'&\x17\x16\x17\x167>\x05\x16\x17\x14\x0e\x05\a\x0e\x02'&'&\a\x06\x15\x14\x0e\x02\x17\x0e\x01\a\x06\x16\a\x06'&'&76\a\x06\a\x06\x17\x1e\x01\x17\x1e\x01\x17\x1e\x01\x06\a\x1e\x02\x156'.\x027>\x01\x17\x167676\x17\x16\a\x06\a\x06\x16\x17>\x0176&6763>\x01\x16\x016&'&\x15\x16\x172\a\x0632\x05.\x02'.\x04\a\x06\x16\x17\x166'4.\x01\a\"\x06\x16\x17\x16\x17\x147674.\x01'&#\x0e\x01\x16\a\x0e\x02\x17\x16>\x017626\x01\x1e\x02\x0e\x05\a\x0e\x01\a\x0e\x01'.\x03'&#\"\x06\a\x0e\x03'.\x01'.\x04'&676.\x0167>\x017>\x015\x16\a\x06'&\a\x06\x17\x1e\x03\a\x14\x06\x17\x16\x17\x1e\x01\x17\x1e\x027>\x02.\x01'&'&\a\x06'&7>\x027>\x03767&'&67636\x16\x17\x1e\x01\a\x06\x17\x16\x17\x1e\x01\x17\x16\x0e\x01\a\x0e\x03'.\x04'&\x0e\x01\x17\x16\a\x06\x1667>\x017>\x01.\x01'.\x0167\x1e\x05\x02\x97\v\t\x04\x05\x13\x05\\\x04\x0f\n\x18\b\x03\xfe\x9b\x04\x04\x05\x03\x03\a\n\t\x04\x11\x04\x01\x02\x02\x01\x02\x03U7\x04\a\x03\x03\x02\a\x01\t\x01\nJ#\x18!W!\v'\x1f\x0f\x01\v\t\x15\x12\r\r\x01\x0e\"\x19\x16\x04\x04\x14\v'\x0f;\x06\b\x06\x16\x19%\x1c\n\v\x12\x15\r\x05\x11\x19\x16\x10k\x12\x01\t)\x19\x03\x01\"\x1c\x1b\x1d\x02\x01\t\x11\a\n\x06\x04\v\a\x11\x01\x01\x14\x18\x11\x14\x01\x01\x16\t\b'\x01\r\x05\n\x0e\x16\n\x1b\x16/7\x02*\x1b \x05\t\v\x05\x03\t\f\x14I\t,\x1a\x196\n\x01\x01\x10\x19*\x11&\"!\x1b\x16\r\x02\x02\x06\x06\v\a\r\x03\x1cO6\x16\x15*\x16\x03\x01\x1e\x1d\r\x12\x17O\b\x02\x01\x06\b\x15 \x04\x02\x06\x04\x05\x02\x02$.\x05(\x04\x14\xa8\t\x10\x03\x1f\x1e\b*\x0e.'\x04\r\x06\x01\x03\x14\n.x\x85,\x17\v\f\x02\x01\x16\t\x06\x15\x03\x17\x02\x02\x11\x02\x16\x0f$\x01CN\xfd\xa1\x03\v\x06\t\x02\x03\n\x03\x03\v\x03\x01\xa3\x02\t\x11\x06\x05\t\x05\x06\x02\x03\x0e*\x12\t\v\xb4\n\f\x03\x06\x04\x04\x03\x0e\x04\b\x026\x05\r\x03\x0f\t\t\x05\x03\x02\x01\n\x02\x04\x04\b\x0e\b\x01\x10\x0e\x027\x14\x16\x02\a\x18\x17%\x1a&\b&_\x1c\x11f&\x12\x17\n\"\x1e,V\x13L\x14,G$3\x1c\x1d\xa4@\x13@$+\x18\x05\n\"\x01\x01\n\n\x01\n\x0eV\x11\x1e\x18\x155 3\"\t\r\x12\x02\f\x05\x04\x01\"\x03\x03\"\x14\x81#\x18dA\x17++\x03\x12\x14\ny0D-\v\x04\x03\x01\x01\x12\x1e\a\b%\x16&\x14n\x0e\f\x04\x024P'A5j$9E\x05\x05#\"c7Y\x0f\b\x06\x12\v\n\x1b\x1b6\"\x12\x1b\x12\t\x0e\x02\x16&\x12\x10\x14\x13\n8Z(;=I50\v' !!\x03\x0e\x01\x0e\x0f\x1a\x10\x1b\x04e\x01\x13\x01\x06\f\x03\x0e\x01\x0f\x03\v\r\x06\xfeR\x01\b\x11\x05\x05\b\v\x01\x01\x10\n\x03\b\x04\x05\x03\x03\x02\xfe\x9a\x12\x18\x0f\x19\x1b\x10\x1d\n\"\a+\x050n\x14\x14?\xa2t(\x02\x04-z.'<\x1f\x12\f\x01>R\x1e$\x16\x15A\"\b\x03\x1e\x01\x0124\x01\x03B\x19\x13\x0f\a\x04@\x05\x1e(\x15\t\x03\b~\x0f\t\x03\x04\a9B\x01\x019\x1f\x0f,\x1f\x02\x03\v\t\x01\x1d\x13\x16\x1e\x01*$\x04\x0f\x0e\f\x17\x01\x0e\x1a\x05\b\x17\x0f\v\x01\x02\x11\x01\f\t\x11\t\x0e\x06\x03\v\r\x03\x06\x1f\x04\x13\x04\x05\a\x02\x04\x04\x0f\x17\x01\x01\f\x10\x13\x0f\t\x04\t\x02\x05\x05\x04\x06\x03\a\x01\x0e<\x1a\f\v>\x1f\t\x03\a\x19?0D\x1d\x06\xa89\x12f\b\x18\x15\x1f?\x1c\x1c\x13\x01\x01\x04Ae\f \x04\x17\x87\t\x0f.(\x03\x0f;1.\x18D\b\x10\b\x02\x05\t\a4\x10\x0fH&\b\x06.\x19C\x17\x1d\x01\x13t \x15iY\x1a\x12% \v\x03*\x11\x1a\x02\x02\t\x05\x01\x0f\x14\xc2\b\a\x03\x04\x03\n\x06\a\x01\x02\x107\x04\x01\x12\xe0\v\x11\b\x01\x04\x04\x01\x04\x1b\x03\x05\x02\xea\x02\x06\b\x02\x0f\x01\r\r\x06\x04\r\x05\x06\x03\x06\f\x03\x01\x04\xfa\xc8\f\x19\x17\x16\x16\x11\x14\r\x12\x04\x13J\x1b\x10\a\x12\t\x1d\x16\x11\x01\x01\x03\x01\x01\x1c \x19\x01\x01<\r\x04\v\a\f\x11\v\x17W\v\x100%$\t\f\x04\n\x12\"\"I!\x14\x05\x03\r\x0f*\x06\x18\f\x16\v\x0fD\x0e\x11\t\x06\x19\b\x06 \x0e\x03\x06,4A'\x11\xbe4J\"\t\x18\x10\x16\x1d.0\x12\x15f6D\x14\x8f4p\xc6Z{+\x15\x01\x1d\x1b*\x9fD_wqi;\xd0W1G(\x02\x02\"%\x1e\x01\x01\b\x13\f\x1d\x05%\x0eT7F}AG\x05!1#\x19\x12% \x19\v\vJG\f\x1f3\x1e\x1b\v\x0f\x00\b\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0e\x00 \x00'\x00.\x002\x00>\x00V\x00b\x00\x00%&\x03#\a\x0e\x04\a'\x1632\x03&'\x04!\x06\x15\x14\x16\x17>\x03?\x01>\x01'&'\x0e\x01\a \x05&\a\x16\x17>\x01\x01\"\a6\x05&#\"\a\x16\x17>\x04\x13&'\a\x0e\x04\a\x16\x17\x1e\x01\x17>\x012\x1e\x04\x176\x10\x02\x04 $\x02\x10\x12$ \x04\x04\x00*b\x02\x02\x106\x94~\x88#\x0f\xb8\xea\x84=\x15 \xfe\xc9\xfe\x96\x01XP2\x93\x8a{&%\x04\x12gx|\x8a\xc0 \x01.\x03\xdc\xd2\xc7W)o\x94\xfc\xf1\x01\x01\x01\x02O\xb9\xf8LO\x83sEzG<\x0f\xe4\x03\x92\x01\t\x14CK}E\x19\x13\x02\t\x03$MFD<5+\x1e\nz\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a$\xf1\x01\x01\x01\x06\x15MW\x8eM\v\x96\x02\x931>]\a\x0e|\xe1YY\x9b^D\x0e\r\x01\x05\xd6եA\xf2\x97\xef<\x1f\xef\xe6K\xe5\x03m\x01\x01\x91\xa4\x13\xaa\xd4\x1aE6<\x15\xfe\"\xe8\xb2\x01\f\x19@9I\x1c5*\x05\x18\x05\x05\x04\x03\x05\x06\a\x05\x02\xc8\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00>\x00^\x00\x00\x014.\x03/\x01.\x045432\x1e\x0332654.\x01#\"\x0e\x02\x15\x14\x1e\x02\x1f\x01\x16\x17\x16\x15\x14\x06#\".\x03#\"\x06\x15\x14\x1632>\x02\x05\x14\x06#\"'\x06#\"$&\x02547&54632\x17632\x04\x16\x12\x15\x14\a\x16\x04\x95':XM1h\x1e\x1c*\x12\x0f\x90+D($,\x1a/9p\xac`D\x80oC&JV<\x92Z\x16 PA3Q1*2\x1d23\xf4\xa9I\x86oB\x01kែhMI\x8f\xfe\xfb\xbdo\x10PែhMI\x8f\x01\x05\xbdo\x10P\x01\xd92S6,\x18\v\x18\a\a\x10\x10\x1a\x11M\x18!\"\x18@-7Y.\x1f?oI=[<%\x0e$\x16\x0e\x14('3 -- <-\\\x83%Fu\x90\x9f\xe1P\x10o\xbd\x01\x05\x8fIMh\x82\x9f\xe1P\x10o\xbd\xfe\xfb\x8fIMh\x00\x00\x00\x03\x00,\xff\x80\x04\xcb\x06\x00\x00#\x00?\x00D\x00\x00\x0176&#!\"\x06\x15\x11\x147\x01>\x01;\x01267676&#!\"&=\x01463!267\x06\n\x01\a\x0e\x04#!\"\a\x06\x01\x0e\x01'&5\x11463!2\x16\a\x036\x1a\x01\x03\xe8%\x05\x1c\x15\xfd8\x17\x1f\x06\x01#\x17\x1e!\xef\x16\x1e\x03\x18\r\x04\x1f\x15\xfe\xda\x1d&&\x1d\x01Z\x12\"\xe6\x0fM>\x04\x06\x06\x16\x1b2!\xfe\xf1\r\t\b\xfe^\x16I\f7LR\x03x_@\x16\x9e\x04>M\x04N\xc2\x17\"\"\x14\xfb\xb3\a\x06\x01`\x1a\x0f\x1d\x0f\x82=\x15&&\x1d*\x1d%\x1b\xeeI\xfe}\xfe\xc7\x11\x16\x15,\x16\x14\n\t\xfe\x1b\x19\a\t\x16L\x05\x827_jj\xfc\xea\x11\x019\x01\x83\x00\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00\x00%\x114&#!\"\x06\x15\x11\x14\x163!26\x01\x114&#!\"\x06\x15\x11\x14\x163!26\x13\x11\x14\x06#!\"&5\x11463!2\x16\x02\xc0\x12\x0e\xfe \x0e\x12\x12\x0e\x01\xe0\x0e\x12\x02\xa0\x12\x0e\xfe \x0e\x12\x12\x0e\x01\xe0\x0e\x12\xa0&\x1a\xfa\x80\x1a&&\x1a\x05\x80\x1a&\xc0\x04\x00\x0e\x12\x12\x0e\xfc\x00\x0e\x12\x12\x01\x8e\x02\x80\x0e\x12\x12\x0e\xfd\x80\x0e\x12\x12\x03\x0e\xfa\x80\x1a&&\x1a\x05\x80\x1a&&\x00\x00\x00\x00\x02\x00\x00\xff\x00\x05\x00\x05\xe0\x001\x009\x00\x00\x01\x14\x06#\"'\x03#\x15\x13\x16\x15\x14\x06+\x01\x11\x14\x06+\x01\"&5\x11#\"&547\x135#\x03\x06#\"&547\x0163!2\x17\x01\x16\x00\x14\x06\"&462\x05\x008(3\x1d\xe3-\xf7\t&\x1a\xc0B.\xa0.B\xc0\x1a&\t\xf7-\xe3\x1d3(8\x10\x01\x00Ig\x01\x80gI\x01\x00\x10\xfe`\x83\xba\x83\x83\xba\x01\xe0(8+\x01U\x84\xfee\x0f\x12\x1a&\xfe\xf0.BB.\x01\x10&\x1a\x12\x0f\x01\x9b\x84\xfe\xab+8(\x1d\x18\x01\x80kk\xfe\x80\x18\x03`\xba\x83\x83\xba\x83\x00\x02\x00\x00\xff\x00\x04\x00\x05\xe0\x00%\x00-\x00\x00\x01\x11\x14\x06\"&5\x11#\x11\x14\x06\"&5\x11#\x11\x14\x06\"&5\x11#\x11\x14\x06\"&5\x11463!2\x16\x00\x14\x06\"&462\x04\x008P8@B\\B@B\\B@8P8pP\x02\x80Pp\xfe\xe0\x83\xba\x83\x83\xba\x03@\xfe`(88(\x01`\xfcp.BB.\x01\xd0\xfe0.BB.\x03\x90\xfe\xa0(88(\x01\xa0Ppp\x01ͺ\x83\x83\xba\x83\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x15\x00!\x00\x00%\x01>\x01&'&\x0e\x01\a\x06#\"'.\x02\a\x0e\x01\x16\x17$\x10\x02\x04 $\x02\x10\x12$ \x04\x03\x05\x01^\x10\x11\x1d/(V=\x18$<;$\x18=V).\x1d\x11\x10\x04X\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xea\x01\xd9\x16J`\x1f\x1a\x01\"\x1c((\x1c\"\x01\x1a\x1f`J\x16\x8e\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x02\x00,\xff\x00\x06\xd4\x05\xff\x00\x0f\x00I\x00\x00\x004.\x02\"\x0e\x02\x14\x1e\x022>\x01%\x06\a\x05\x11\x14\a\x06'%\a\x06\"/\x01\x05\x06'&5\x11%&'&?\x01'&767%\x11476\x17\x05762\x1f\x01%6\x17\x16\x15\x11\x05\x16\x17\x16\x0f\x01\x17\x16\x05\xc0[\x9b\xd5\xea՛[[\x9b\xd5\xea՛\x01o\x04\x10\xfe\xdc\r\x0f\x0e\xfeܴ\n \n\xb4\xfe\xdc\x0e\x0f\r\xfe\xdc\x10\x04\x05\t\xb4\xb4\t\x05\x04\x10\x01$\r\x0f\x0e\x01$\xb4\t\"\t\xb4\x01$\x0e\x0f\r\x01$\x10\x04\x05\t\xb4\xb4\t\x02\v\xea՛[[\x9b\xd5\xea՛[[\x9b5\x0f\x05`\xfe\xce\x10\n\n\x06^\xf8\r\r\xf8^\x06\n\n\x10\x012`\x05\x0f\x11\f\xf8\xf8\r\x10\x0f\x05`\x012\x10\n\n\x06^\xf8\f\f\xf8^\x06\n\n\x10\xfe\xce`\x05\x0f\x10\r\xf8\xf8\f\x00\x02\x00\x00\xff\x80\x05\xbe\x05\u007f\x00\x12\x001\x00\x00%\x06#\"$\x02547\x06\x02\x15\x14\x1e\x0232$%\x06\x04#\"$&\x0254\x126$76\x17\x16\a\x0e\x01\x15\x14\x1e\x013276\x17\x1e\x01\x04\xee68\xb6\xfeʴh\xc9\xfff\xab킐\x01\x03\x01&^\xfe\x85\xe0\x9c\xfe\xe4\xcezs\xc5\x01\x12\x99,\x11\x12!V[\x92\xfa\x94vn)\x1f\x0e\a\xe9\t\xb4\x016\xb6\xc0\xa5<\xfe\xaeׂ\xed\xabf{\xc3\xcb\xf3z\xce\x01\x1c\x9c\x99\x01\x17\xcc}\x06\x02))\x1fN\xcfs\x94\xfa\x923\x12\x1f\x0e(\x00\x03\x00@\xff\x80\x06\xc0\x05\x80\x00\v\x00\x1b\x00+\x00\x00\x004&#!\"\x06\x14\x163!2\x01\x11\x14\x06#!\"&5\x11463!2\x16\x13\x11\x14\x06#!\"&5\x11463!2\x16\x04@&\x1a\xff\x00\x1a&&\x1a\x01\x00\x1a\x02f&\x1a\xfa\x80\x1a&&\x1a\x05\x80\x1a&@&\x1a\xfa\x00\x1a&&\x1a\x06\x00\x1a&\x02\xa64&&4&\x01\x00\xfc@\x1a&&\x1a\x03\xc0\x1a&&\x01\xa6\xff\x00\x1a&&\x1a\x01\x00\x1a&&\x00\x00\x02\x00 \xff\xa0\x06`\x05\xc0\x00B\x00H\x00\x00\x00\x14\x06+\x01\x14\a\x17\x16\x14\a\x06\"/\x01\x0e\x04#\x11#\x11\".\x02/\x01\a\x06#\"'.\x01?\x01&5#\"&46;\x01\x11'&462\x1f\x01!762\x16\x14\x0f\x01\x1132\x01!46 \x16\x06`&\x1a\xe0C\xd0\x13\x13\x126\x12\xc6\x05\x14@Bb0\x803eI;\x0e\x0f\xb7\x14\x1c\x18\x13\x13\x03\x11\xca:\xe0\x1a&&\x1a\xe0\xad\x13&4\x13\xad\x03L\xad\x134&\x13\xad\xe0\x1a\xfeF\xfd\x80\xbb\x01\n\xbb\x02Z4&\xabw\xd1\x134\x13\x13\x13\xc5\x05\x10) \x1a\x03\x80\xfc\x80\x1b''\r\x0e\xcf\x15\x10\x125\x14\xe3r\xa0&4&\x01&\xad\x134&\x13\xad\xad\x13&4\x13\xad\xfe\xda\x02\x00\x85\xbb\xbb\x00\x00\x01\xff\xff\x00\x01\a}\x04G\x00\x85\x00\x00\x01\x16\a\x06\a\x0e\x02\x1e\x02\x17\x16\x17\x16\x17\x1e\x02\x0e\x01#\x05\x06&/\x01.\x03\a\x0e\x04\x17\x14\x06\x0f\x01\x06\a#\x06.\x02/\x01.\x03\x02'&4?\x0163%\x1e\x01\x1f\x01\x16\x17\x1e\x01\x1f\x01\x1e\x0327>\x04'.\x01/\x01&'&7676\x17\x16\x17\x1e\x03\x14\x0e\x01\x15\x14\x06\x1e\x02\x17\x1e\x01>\x02767>\x01?\x01>\x02\x17%6\x16\x17\a}\x17\xad\x18)(\x1e\x1f\a\x13.\"\x04\x01\x8d2\x03\a\a\b*&\xff\x00\x18@\x14\x14\x1eP9A\x18\x03\n\x18\x13\x0f\x01\a\x04\x04\x12#sG\x96q]\x18\x19\n#lh\x8d<\x06\x03\x04\x0f*\x01\x12\f\x16\x05\x05\x10\b\x144\x0f\x10\x1d6+(\x1c\r\x02\x06\x12\t\n\x05\x02\x0e\a\x06\x19<\r\x12\x10\x165\xbaR5\x14\x1b\x0e\a\x02\x03\x02\x01\x06\x11\x0e\b\x12\"*>%\"/\x1f\t\x02\x04\x1a+[>hy\n\x0f\x03\x03\x01\x03\x03\x01\x02\x05\x0f\t\x00\a\x00\x00\xff\xaa\x06\xf7\x05K\x00\n\x00\x15\x00!\x00/\x00U\x00i\x00\u007f\x00\x00%6&'&\x06\a\x06\x1e\x01676&'&\x06\a\x06\x17\x166\x17\x0e\x01'.\x017>\x01\x17\x1e\x01%.\x01$\a\x06\x04\x17\x1e\x01\x0476$%\x14\x0e\x02\x04 $.\x0154\x1276$\x17\x16\a\x06\x1e\x016?\x0162\x17\x16\a\x0e\x01\x1e\x01\x17\x1e\x02\x02\x1e\x01\a\x0e\x01'.\x0176&\a\x06&'&676%\x1e\x01\a\x0e\x01.\x0176&'.\x01\a\x06.\x01676\x16\x02\xa3\x15\x14#\"N\x15\x16\x12DQt\b\t\r\x0e\x1d\a\x11\x1e\x0e\x1e\xb5-\xe2okQ//\xd1jo_\x01\v\t\xa0\xfe\xff\x92\xdf\xfe\xdb\x0e\t\xa0\x01\x01\x92\xdf\x01%\x01&J\x90\xc1\xfe\xfd\xfe\xe6\xfe\xf4Ղ\x8b\x80\xa9\x01YJA-\x04\x06\x0e\x0f\x06\x06\x8b\xd6.--\x02\x05\x0e\n\f9\\DtT\x19\x13\b+\x17\x17\x16\a\x14X?\x18*\x04\x05\x1a\x18<\x01UW3'\t26\x1a\b\x1c$>>\xacW\x1c0\f\x1f\x1c{\xf2\xfc\"F\x0f\x0e\x1a!\"E \x1b\x9b\r\x1b\x05\x05\v\r\x1f\x0e\x05\v^f`$\"\xb9_]\\\x1b\x1d\xb5<`\x94F\x0e\x17\xed\x92`\x94F\x0e\x17\xed\x8eD\x8f\x83h>Cw\xb7ls\x01\x04\x80\xa9\x86J@\x91\x0e\f\x02\x03\x02\x02;=?s\r\x0e\v\x04\x04\x12:i\x02_^{8\x17\x16\a\b+\x17?`\r\x05\x1a\x18\x18)\x05\rO`\xfds\x1b\x1a\x122\x1bR\xb4DE5\x12\x06\x1f8/\x06\x1aK\x00\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05r\x00\t\x00\x13\x00\x1d\x00\x00\x05\x06#\"'>\x017\x1e\x01\x01\x11\x14\x02\a&\x114\x12$\x01\x10\a&\x025\x11\x16\x04\x12\x04m\xab\xc5ī\x8a\xc3\"#\xc3\xfe\x9b\xfd̵\xa7\x01$\x045\xb5\xcc\xfd\xb3\x01$\xa7\"^^W\xf8\x90\x90\xf8\x05=\xfe\x1b\xfc\xfeac\xd7\x01\x18\xbb\x01E\xd6\xfd*\xfe\xe8\xd7c\x01\x9f\xfc\x01\xe5\x1e\xd6\xfe\xbb\x00\x00\x00\x01\x00\x00\xff\x00\x05z\x06\x00\x00k\x00\x00\x01\x0e\x03.\x03/\x01\x06\x00\a\"&4636$7\x0e\x02.\x03'>\x01\x1e\x02\x1767\x0e\x02.\x05'>\x01\x1e\x05\x1f\x0165.\x0567\x1e\x04\x0e\x02\x0f\x01\x16\x14\a>\x05\x16\x17\x0e\x06&/\x01\x06\a>\x05\x16\x05z X^hc^O<\x10\x11q\xfe\x9f\xd0\x13\x1a\x1a\x13\xad\x01+f$H^XbVS!rȇr?\x195\x1a\a\x16GD_RV@-\x06F\u007fbV=3!\x16\x05\x04\f\b\x1bG84\x0e&3Im<$\x05\x06\x14\x12\b\a\x01\x01\x03\x0e/6X_\x81D\x02'=NUTL;\x11\x11\x172\x06\x18KPwt\x8e\x01\xb1Pt= \x03\x0e\x1e\x19\n\n\xe4\xfe\xf9\x01\x1a&\x19\x01ռ\x0e\x12\b\r,J~S/\x14#NL,\x83\xa0\x01\x03\x02\x03\x11\x1d8JsF\x1c\x11\x13);??1\x0f\x10zI\x06\x14EJpq\x8dD\x19IPZXSF6\x0f\x0f\x04\\\x1a\a\x17?5:\x1f\x02\x17N\u007fR=\x1e\x12\x01\x03\x03\x03\x93\x88\a\x17;.&\x021\x00\x04\x00\x15\xff\x00\x04\xeb\x05\x00\x00\f\x00\x10\x00\x14\x00\x1e\x00\x00\x01\x15\x14\x06+\x01\x01\x11!\"&=\x01\x01\x15!\x11\x01\x15!\x11%\x15!5463!2\x16\x04\xebsQ9\xfe\xfc\xfd\xefQs\x04\xd6\xfb*\x04\xd6\xfb*\x04\xd6\xfb*sQ\x03NQs\x01\x1bBUw\xfe\xf3\x01\rwUB\x01F\xff\x00\xff\x01H\xff\x00\xff\x8cCCTww\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x19\x00%\x001\x00\x00\x00\x14\a\x01\x06#\"&=\x01!\"&=\x01463!54632\x17\x01\x16\x10.\x01 \x0e\x01\x10\x1e\x01 6\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04\x80\t\xfe\xc0\t\x0e\r\x13\xfe\xa0\r\x13\x13\r\x01`\x12\x0e\f\f\x01?\xa9\x92\xfa\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\x01r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02\x8e\x1c\t\xfe\xc0\t\x13\r\xc0\x13\r\xc0\r\x13\xc0\x0e\x12\n\xfe\xc1\xab\x01(\xfa\x92\x92\xfa\xfe\xd8\xfa\x92\x92\x02_\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x19\x00%\x001\x00\x00\x01\x15\x14\x06#!\x15\x14\x06#\"'\x01&47\x01632\x16\x1d\x01!2\x16\x12\x10.\x01 \x0e\x01\x10\x1e\x01 6\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04\x80\x13\r\xfe\xa0\x12\x0e\f\f\xfe\xc1\t\t\x01@\t\x0e\r\x13\x01`\r\x13\xa0\x92\xfa\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\x01r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02\xe0\xc0\r\x13\xc0\x0e\x12\n\x01?\t\x1c\t\x01@\t\x13\r\xc0\x13\xfe\xff\x01(\xfa\x92\x92\xfa\xfe\xd8\xfa\x92\x92\x02_\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00\x00\x01\x11\x14\x06#\"'\x01&47\x01632\x16\x01\x114&#!\"\x06\x15\x11\x14\x163!26\x01\x11\x14\x06#!\"&5\x11463!2\x16\x04\x00&\x1a\x14\x11\xfe@\x1b\x1b\x01\xc0\x11\x14\x1a&\x01\x00\x13\r\xfc@\r\x13\x13\r\x03\xc0\r\x13\x01\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x03\xc0\xfd\x80\x1a&\f\x01@\x13B\x13\x01@\f&\xfc\xc6\x03\xc0\r\x13\x13\r\xfc@\r\x13\x13\x03\xcd\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\a\x00\x13\x00\x1f\x00\x00\x00\x14\x06\"&462\x12 \x0e\x01\x10\x1e\x01 >\x01\x10&\x04\x10\x02\x04 $\x02\x10\x12$ \x04\x04\x00\x96Ԗ\x96\xd4*\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\x92\x92\x01r\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x02\xeaԖ\x96Ԗ\x01 \x92\xfa\xfe\xd8\xfa\x92\x92\xfa\x01(\xfa\xbd\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x00\x02\x00\x00\xff\x00\x06]\x05\xe0\x00\x15\x006\x00\x00\x01\x17\x06\x04#\"$\x0254\x127\x17\x0e\x01\x15\x14\x0032>\x01%\x17\x05\x06#\"'\x03!\"&'\x03&7>\x0132\x16\x15\x14\x06'\x13!\x15!\x17!2\x17\x13\x03\xfff:\xfeл\x9c\xfe\xf7\x9bѪ\x11z\x92\x01\a\xb9~\xd5u\x02\x1b:\xff\x00\r\x10(\x11\xef\xfe(\x18%\x03`\x02\b\x0eV6B^hD%\x01\xa7\xfei\x10\x01\xc7(\x11\xe4\x01]̳ޛ\x01\t\x9c\xb5\x01*>\x836߅\xb9\xfe\xf9\x82\xdd\x1ar\x80\a#\x01\xdd!\x18\x03\v\x11\x193?^BEa\a\xfe߀\x80#\xfe9\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00#\x003\x00\x00\x016'&\x03632\a\x0e\x01#\"'&'&\a\x06\a\x0e\x01\a\x17632\x17\x1e\x01\x17\x1632\x13\x12\x13\x11\x14\x06#!\"&5\x11463!2\x16\x05\f\n\xab\xe7Q,&U\v\x04\x8c#+'\r \x1e\x82;i\x1bl\x1b4L\v92\x0f<\x0fD`\x9d\xe2\xdc\xfa\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x03\x82\xd8\x06\b\xfe\xf3\x13`9ܩ6ɽ\f\a]\x18`\x18C4\xb37\xdb7\xb3\x01&\x01\x1b\x01\u007f\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x01\x00\x00\x00\x00\x04\x80\x05\x80\x00D\x00\x00\x01\x14\x02\x04+\x01\"&5\x11\a\x06#\"'&=\x014?\x015\a\x06#\"'&=\x014?\x01546;\x012\x16\x1d\x01%6\x16\x1d\x01\x14\a\x05\x15%6\x16\x1d\x01\x14\a\x05\x116\x00546;\x012\x16\x04\x80\xbd\xfe\xbc\xbf\xa0\x0e\x12\xd7\x03\x06\n\t\r\x17\xe9\xd7\x03\x06\n\t\r\x17\xe9\x12\x0e\xa0\x0e\x12\x01w\x0f\x1a\x17\xfew\x01w\x0f\x1a\x17\xfew\xbc\x01\x04\x12\x0e\xa0\x0e\x12\x02\xc0\xbf\xfe\xbc\xbd\x12\x0e\x02cB\x01\x06\n\x10\x80\x17\bG]B\x01\x06\n\x10\x80\x17\bG\xfa\x0e\x12\x12\x0e\xb5t\x05\x14\x10\x80\x17\by]t\x05\x14\x10\x80\x17\by\xfe\x19\r\x01\x14\xbe\x0e\x12\x12\x00\x03\x00\x00\x00\x00\x05\x80\x05\x80\x00#\x003\x00C\x00\x00\x01\x15\x14\x06#!\x11\x14\x06+\x01\"&5\x11!\"&=\x01463!\x1146;\x012\x16\x15\x11!2\x16\x13\x114&#!\"\x06\x15\x11\x14\x163!26\x13\x11\x14\x06#!\"&5\x11463!2\x16\x04\x80\x12\x0e\xfe\xa0\x12\x0e@\x0e\x12\xfe\xa0\x0e\x12\x12\x0e\x01`\x12\x0e@\x0e\x12\x01`\x0e\x12\x80^B\xfc\xc0B^^B\x03@B^\x80\xa9w\xfc\xc0w\xa9\xa9w\x03@w\xa9\x02\xe0@\x0e\x12\xfe\xa0\x0e\x12\x12\x0e\x01`\x12\x0e@\x0e\x12\x01`\x0e\x12\x12\x0e\xfe\xa0\x12\xfe2\x03@B^^B\xfc\xc0B^^\x03\x82\xfc\xc0w\xa9\xa9w\x03@w\xa9\xa9\x00\x00\x00\x00\x04\x00\x00\xff\x80\b\x80\x05\x00\x00'\x00/\x00?\x00P\x00\x00\x01\x06+\x015#\"&547.\x01467&546;\x01532\x17!\x1e\x01\x17\x1e\x02\x14\x0e\x01\a\x0e\x01\a7\x16\x14\a\x1764'\x01!\x06\a\"\x06\x0f\x01\x01\x0e\x01+\x01\x0332\x03#\x1332\x16\x17\x01\x1e\x043\x05!&\x02ln\x9e\x80@\r\x13\a:MM:\a\x13\r@\x80\x9en\x04Y*\x81\x10Yz--zY\x10\x81*\x0655QDD\xfbU\x03\xf7\xd9\xef9p\x1b\x1c\xfe\xe0\x1aY-`]\x1d\x9d\x9d\x1d]`.X\x1a\x01 \x04\x0e/2I$\x01\xc8\xfc\tt\x01\xa0@@/!\x18\x19\x02\x11\x18\x11\x02\x19\x18!/@@\a\x16\x03\x0f3,$,3\x0f\x03\x16\a\xfc$p$\x1e0\x940\xfe\xd6&*0\x18\x18\xfe\xe0\x1a&\x01\xd0\x01\xe0\x01\xd0&\x1a\xfe\xe0\x04\r!\x19\x15P@\x00\x02\x00\x00\xff\x80\x06\x80\x06\x00\x00R\x00V\x00\x00\x012\x16\x15\x14\x0f\x01\x17\x16\x15\x14\x06#\"&/\x01\x05\x17\x16\x15\x14\x06#\"&/\x01\a\x06#\"&546?\x01\x03\a\x06#\"&546?\x01'&54632\x16\x1f\x01%'&54632\x16\x1f\x017632\x16\x15\x14\x06\x0f\x01\x1376\x01%\x03\x05\x05\xef>S]\xac8\aT;/M\x0f7\xfe\xca7\bT\x057%>\x01\x04\xe0w\xa9\xa9w\xfc@w\xa9\xa9w\x03\xe0\x1f!\"\xc55bBBb/\xbe/\f*\n8(\x03@(87)\xfc\xc0(8=%/\xb5'\x03\x1c\x0e\x1c\x13\x18\x15\x14\x15\x18\x13\x1c\x0e\x1c\x03\x01\v#?\x05\x80\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\xfb\xe0\x01\xb4#\x14\x16~$EE y \b&\b\xfeL(88\x02e):8(%O\x19 r\x1a\x02\x13\t\x11\t\n\x05\x05\n\t\x11\t\x13\x02\xae\x17O\x00\x00\x00\x00\x06\x00\x00\xff\x00\a\x00\x06\x00\x00\x05\x00?\x00G\x00Q\x00a\x00q\x00\x00\x1347\x01&\x02\x01\x14\x0e\x03\a\x03\x0167>\x01&\x0f\x01&'&\x0e\x01\x1e\x01\x1f\x01\x13\x03\x0167>\x01&\x0f\x01\"$32\x04\x17#\"\x06\x15\x14\x1e\x06\x17\x16\x05\x13\x16\x17\x06#\"'\x01\x16\x15\x14\x02\a\x13654\x00 \x04\x16\x12\x10\x02\x06\x04 $&\x02\x10\x126\x00 $6\x12\x10\x02&$ \x04\x06\x02\x10\x12\x16\u007fC\x01o\xc4\xee\x05\b\x05\x0f\b\x1b\x04L\xfe\xea.*\x13\x0e\x13\x13\xcdK\u007f\f\x11\x06\x03\x0f\fPx\xa8\xfe\xe8.*\x13\x0e\x13\x13\xcd\a \ni\x01SƓ\x01\vi\n7J\x04\x04\f\x06\x12\a\x16\x03?\xfe\x06\xed\x01\x04~\x81pi\x03{_Я\xeb;\xfc\xa2\x01l\x01L\xf0\x8e\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01U\x01Z\x01=刈\xe5\xfe\xc3\xfe\xa6\xfe\xc3刈\xe5\x02\x80\xa3\x96\xfc\x13_\x01t\x01\b\x13'<\x1cZ\r\xff\x00\x03:\x03\x05\x02!\x1d\x01\n\x01\t\x01\f\x12\x13\x0e\x01\b\xfe\xb8\xfe\b\x03@\x03\x05\x02!\x1d\x01\n\x01\xa0\xbbj`Q7\f\x18\x13\x1b\x0f\x1e\f$\x05k\xd3\xfdy\x06\x05, \x04R\xae\xc3\xd1\xfe\x9ff\x02\xa6\xa9k*\x024\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\xf9\xb7\x88\xe5\x01=\x01Z\x01=刈\xe5\xfe\xc3\xfe\xa6\xfe\xc3\xe5\x00\x00\x00\x02\x00\x00\xff\x80\a\x00\x06\x00\x00\x12\x00\x1b\x00\x00\x01\x11\x05&$&546$7\x15\x06\x04\x15\x14\x04\x17\x11\x01\x13%7&'5\x04\x17\x04>\xfe\xf0\xe4\xfe\x8c\xd6\xc9\x01]\xd9\xd9\xfe\xe9\x015\xea\x03\xad%\xfd\xf3\x93w\xa1\x01\x15\xcc\x06\x00\xfa\x00\x80\x14\xa4\xfd\x92\x8c\xf7\xa4\x1a\xac&\xe0\x8f\x98\xe6\x1e\x05P\xfe?\xfezrSF\x1d\xac!|\x00\x00\x00\x03\x00\x00\xff\x00\a\x80\x06\x00\x00\f\x00&\x000\x00\x00\t\x01\x15#\x14\x06#!\"&5#5\x01!\x113\x11!\x113\x11!\x113\x11!\x1132\x16\x1d\x01!546;\x01\x052\x16\x1d\x01!5463\x03\xc0\x03\xc0\x80)\x1c\xfa\n\x1c)\x80\x01\x00\x01\x00\x80\x01\x00\x80\x01\x00\x80\x01\x00;\x1c)\xf9\x80)\x1c;\x06;\x1c)\xf8\x80)\x1c\x06\x00\xfe\x80\x80\x1a&&\x1a\x80\xff\x00\xfd\x00\x03\x00\xfd\x00\x03\x00\xfd\x00\x03\x00\xfd\x00&\x1a@@\x1a&\xc0&\x1a\x80\x80\x1a&\x00\x00\x02\x00\x00\xff\x80\t\x00\x05\x80\x00\r\x006\x00\x00\x01\x13\x16\x06\x04 $&7\x13\x05\x1627\x00\x14\a\x01\x06\"'%\x0e\x01\a\x16\x15\x14\a\x13\x16\a\x06+\x01\"'&7\x13&54767%&47\x0162\x17\x01\x06\xee\x12\x04\xac\xfe\xd6\xfe\xa4\xfe֬\x04\x12\x02>\x164\x16\x04P\x16\xfb\xa0\x04\f\x04\xfdt+8\x06?::\x02\n\t\x0f\xc0\x0f\t\n\x02::A\vW\xfe\xb3\x16\x16\x04`\x04\f\x04\x04`\x02\xbc\xfe\xc4EvEEvE\x01<\xb5\a\a\x02\x10.\b\xfe\xa0\x01\x01\xce\"\x9be$IE&\xfeO\x0e\v\v\v\v\x0e\x01\xb1&EI&\xcf{h\b.\b\x01`\x01\x01\xfe\xa0\x00\x01\x00m\xff\x80\x05\x93\x06\x00\x00\"\x00\x00\x01\x13&#\"\a\x13&\x00\x02'\x16327\x1e\x01\x12\x17>\x037\x163271\x0e\x03\a\x06\x03[\r>+)@\r(\xfe\xff\xb0]:2,C?\x8d\xc1*%\x91Zx/658:\x1c@#N\n\x92\x02C\xfd=\v\v\x02\xc3E\x01\xc5\x01(\x8b\x0f\x0fo\xed\xfe\xc4E=\xe9\x93\xcdW\x0e\x0e'c:\x86\x11\xf8\x00\x00\x01\x00\x00\xff\x80\x05\xe1\x05\x80\x00#\x00\x00\x01!\x16\x15\x14\x02\x04#\"$&\x02\x10\x126$3 \x17\a&#\"\x0e\x01\x10\x1e\x0132>\x037!\x03\x00\x02\xd5\f\xb6\xfe\xafڝ\xfe\xe4\xceyy\xce\x01\x1c\x9d\x01,\xd7\xd1{\xb7\x81ۀ\x80ہW\x92^F!\x06\xfeL\x02\xeeC=\xd9\xfe\xab\xc0y\xce\x01\x1c\x01:\x01\x1c\xcey\xc9\xc9w\x82\xdf\xfe\xf8߂0H\\R%\x00\x00\x05\x00\x00\xff\x00\a\x00\x06\x00\x00\x10\x00\x19\x00\"\x00N\x00^\x00\x00\x01\x16\a\x06 '&762\x17\x1632762$\x14\x06\"&5462\x05\x14\x06\"&462\x1674&\"\a&'\x13\x17\x14\x16264&#\"\a'&\a\x03\x06\a&#\"\x06\x15\x14\x16\x17\x06\x15\x14\x0432$54'>\x01$\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x04G\x10\x10>\xfe\xee>\x10\x10\x06\x12\x060yx1\x06\x12\xfe\xd34J55J\x01\xbf5J44J5\xfbFd$\x82\xb5?\xc84J55%6\x1a\xdd\x13\x06E\xb4\x81#42F%\x1f\x06\x01\x18\xc5\xc6\x01\x18\a\x1e$\x01f\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x01q\x10\x0f>>\x0f\x10\x06\x0611\x06\xd4J44%&4Z%44J54R1F$Z\x06\x01\x1b-%45J521\x05\x15\xfe\xc8\aZ%F1#:\x0f\x1b\x1d\x8e\xcaʎ \x19\x0f9\xbb\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x8e\xf0\x00\x00\x00\x00\x05\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x19\x00#\x00Q\x00a\x00\x00\x01\x16\a\x06\"'&762\x17\x162762%\x14\x06\"&5462\x16\x05\x14\x06\"&5462\x1674&#\"\a&'7\x17\x1e\x013264&#\"\a'&\a\x03\x06\a&#\"\x06\x15\x14\x16\x17\x06\x15\x14\x1632654'>\x01\x01\x11\x14\x06#!\"&5\x11463!2\x16\x03\xab\r\r5\xec5\r\r\x05\x10\x05*\xce*\x05\x10\xfe\xfe.>.-@-\x01R.>.-@-\xd7<+*\x1fq\x9a6\xab\x01-\x1f -- 0\x15\xbd\x11\x04<\x9ao\x1e,+< \x1a\x05\xf0\xa9\xaa\xf0\x06\x19\x1f\x013\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x01\x97\r\r55\r\r\x06\x06**\x06\x96\x1f..\x1f -- \x1f..\x1f --G*<\x1fN\x04\xf3' ,-@-+*\x05\x12\xfe\xf4\x06M <*\x1e2\r\x19\x17z\xad\xadz\x19\x18\r1\x01\xe4\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x1e\x000\x00<\x00\x00\x01754&\"\x06\x15\x11\x14\x06\"&=\x01#\x15\x14\x163265\x114632\x16\x1d\x01\x055#\x15\x14\x06#\"&=\x01\a'\x15\x14\x1626\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x03bZt\xa0t\x1c&\x1b\x97sRQs\x1b\x14\x13\x1b\x01\x89\x96\x1b\x14\x13\x1bZOpoO\xfe\xe5\x14\x1b\x1b\x14xzRrqP\x01\x18\x13\x1c\x1c\x136\xdfz~\x14\x1b\x1c\x13{\x1a\x1c{Prr\x01\xad\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x02\x00\x00\xff\xa3\a\x80\x05]\x00\x1e\x000\x00\x00\x0154&\"\x06\x15\x11\x14\x06#\"&5\x11!\x11\x14\x16265\x114632\x16\x1d\x01\a\x05!\x11\x14\x06#\"&5\x11\x177\x11\x14\x16265\x04&\x02'&\a\x0e\x01#\".\x01'&'\x04#\"&5467%&4>\x037>\x0132\x16\x17632\x16\x15\x14\x06\x0f\x02\x06\x1632654.\x02547'654'632\x1e\x05\x177\x0e\x03\x177.\a'.\x02*\x01#\"\a>\x057\x1e\x02?\x01\x15\x1767>\b?\x01\x06\a\x0e\x01\a\x0e\x02\a\x1e\x01\x15\x14\x03>\x0132\x1e\x03\x17\x06#\"'\x017\x17\a\x01\x16\x15\x14\x0e\x03\a'>\x023\x01\a'>\x0132\x133\x17\a\x015\x15\x0f\x01?\x02\x04\xc6K\x89cgA+![,7*\x14\x15\n\x18\f2\x03(-#\x01=\x05\x11\a\x0e\x06\n\a\t\x04\a\x0f\x1a\x12/\x0e~[\x10(D?\x1dG\b\f \x16\f\x16\xf7|\x1c,)\x19\"\x0e#\v+\b\a\x02)O\xfc\xb4\x0e8,\x11\x03+\xf7'\xb96\t\x1b\x1d\x17\x19\x02y{=@\xfe\xf90mI\x01\xa1\x03#938\x04\a\x15OA\x1c\xfeE`\x06\n-\f\x13\xd3\x1f\n)\x03y\x01\x02\x01\x02\x01\x02_\x03/FwaH8j7=\x1e7?\x10%\x9c\xad\xbc\x95a\x02\x04\x05\t\x05%\a\x1d\f\x1e\x19%\x16!\x1a?)L\x0f\x01\x15\n\x10\x1fJ\x16\r9=\x15\x02\x1a5]~\x99\x14\x04\x1ap\x16\x10\x0f\x17\x03j\x0e\x16\r\n\x04\x05\x02\x01\r \x11%\x16\x11\x0f\x16\x03(\x10\x1a\xb7\xa01$\"\x03\x14\x18\x10\x12\x13,I\x1a \x10\x03\x0e\r$\x1f@\x1c\x19((\x02\v\x0f\xd6\x05\x15\b\x0f\x06\n\x05\x05\x02\x03\x04\x01+\x1e!\x1a.\x1bS\t\t-\x1c\x01\x01L\x01__\x15$'\x17-\x119\x13L\x0f\t5V\xa5\xc6+\x03\t\n\t\x136\a\v\xfcT\x1a+\x1f6.8\x05-\v\x03$\f\xb10\xfe\xd0\x0f\x01\a\x0f\v\b\a\x01+\x02\r\a\x02t\x14\x11\x01\f\xfd|S\f\x061\x01\x01\x05\x02\x03\x04\x01\x00\x00\x04\x00\x00\xff\x12\x06\x00\x05\xee\x00\x17\x006\x00]\x00\x83\x00\x00\x05&\a\x0e\x01#\"'&#\"\a\x0e\x01\x17\x1e\x0167>\x0276'&'&#\"\a\x06\a\x06\x17\x1667>\a32\x1e\x01\x17\x1e\x0176\x014.\x02#\"\x0e\x01#\x06.\x03\a\x0e\x01\a\x06\x17\x1e\x0132>\x02\x17\x1e\x03\x17\x1667>\x017\x14\x02\x06\x04 $&\x0254>\x057>\x037>\x017\x16\x17\x1e\x01\x17\x1e\x06\x04\x8f\x05\x13\x1erJ\x81@\x05\b\v\x0f\a\x01\b\"kb2)W+\a\f,\x13\x14\x175/\x18\x1d1\x1a\x0e\t\x11\x17\x03\x0f\x06\x0e\t\x10\x0e\x13\v\x1b#\v\b\n\x05\n\x17\x01Z\n\x17-\x1e!\x80\x82$\x1bIOXp7s\xa4\x02\x02L\x1dCF9\x96vz \x1aNAG\x14#/ \x1c\x1d5|\xd0\xfe\xeb\xfe\xd0\xfe\xe6Հ';RKR/\x13\x0eJ#=\x1e$,\b\x819,\xac+\x15$UCS7'2\x13\x0e\x16\"1\x04\f\x06\x14\n \x1c\x03\x03\x04!\x1b\a\f\x84/\x0e\x0f\n\f,\x18\x14\b\a\x14\x02\r\x04\n\x04\x06\x03\x02\x0f\x0e\x0f\x11\x06\x04\f\x01/\x16--\x1cST\x01(::(\x01\x01\x9bep4\x14\x11AM@\x01\x01=I>\x01\x03\".)xΤ\xfe\xe7\xbfls\xc7\x01\x1c\xa0Y\xa7|qK@\x1d\n\b%\x14(\x18\x1cYQ\x9b&\x1dN\x1b\r\x18EHv~\xab\x00\x00\x00\x04\x00\x00\xff\x80\x06\x00\x05\x80\x00\x1e\x00<\x00Z\x00x\x00\x00\x01\x0f\x02\x0e\x01'\x0e\x01#\"&5467&6?\x01\x17\a\x06\x14\x17\x162?\x03\x03\x17\a'&\"\x06\x14\x1f\x03\a/\x02.\x017.\x0154632\x16\x176\x16\x01\x14\x06#\"&'\x06&/\x017\x17\x16264/\x037\x1f\x02\x1e\x01\a\x1e\x01\x03\x14\x06\a\x16\x06\x0f\x01'764&\"\x0f\x03'?\x02>\x01\x17>\x0132\x16\x04.\xa0\x97\x1eA\xadU\x10pIUxYE\x16.A\f\x97\v%%%h%\x1e\x97\xa1\xbe\f\x98\f%hJ%\x1d\x98\xa0\x97\xa1\x97\x1eD,\x1bFZxULs\fT\xab\x03gxUJr\x0eV\xbbD\v\x97\f%hJ%\x1e\x98\xa0\x98\xa0\x98\x1d@/\x15Le\x02fL\x1a.C\f\x97\f%Jh%\x1e\x98\xa0\x98\xa1\x98\x1dC\xb8V\vsNUx\x01Ϡ\x98\x1e@.\x15FZyUHp\x10V\xaeA\f\x98\v%h&%%\x1e\x98\xa0\x02\x12\f\x98\f%Ji%\x1d\x98\xa0\x98\xa0\x98\x1eC\xb9W\x0fpIUybJ\x14/\xfb\x95Uy^G\x1c,D\f\x98\f%Jh%\x1e\x98\xa0\x98\xa0\x98\x1e@\xadU\vs\x04\x17Mt\vU\xb7C\f\x98\f%hJ%\x1e\x98\xa0\x98\xa0\x98\x1eC-\x1aKfy\x00\x00\b\x00\x00\xff\x00\x06\x00\x06\x00\x00E\x00X\x00[\x00_\x00g\x00j\x00\x89\x00\xa3\x00\x00\x01\x06&/\x01&'.\x01'\x06\a\x06\a\x0e\x01'67>\x017>\x017&\a\x0e\x02\a\x06\x14\a\x06\a\x06'&'&'>\x0176763>\x017>\x02\x17\x16\a\x14\x0e\x01\a\x06\a\x17\x1e\x01\x17\x1e\x01\x03\x16\a\x06\a\x06#&'&'7\x1e\x0167672\x05\x17'\x01%\x11\x05\x01\x17\x03'\x03\x177\x17\x01\x05\x11\x01\x17\a'\x06\a\x06+\x01\"&'&54632\x1e\x01\x17\x1e\x013267>\x027\x01\x11%\x06\x04#\"'4'\x11676767\x11\x052,\x0132\x15\x11\x02\x8e\x01\x17\x14\x14,+\aD\x04CCQ\x18\x04\x1f\x03\x06L\x15\x81\x0e\x11D\x02\bf\b'\x1e\x02\x02\x01\x05\x1a\x17\x18\x12\n\x04\x01\x06%\v:/d\x02\nB\v\t\x19\x04\x04\x02\x03\x19\x1c\x03\x194@\f}\x05\x04\r\xcf\x03\a\f&\x1e\x1e\x1a\x17\x0e\x04\x01\x03!\x140$\x13\x11\x02\xbe?\x8b\xfb\xf8\x02\xb6\xfdJ\x04\xd9f\xb5d\xd8f-\xd3\xfe.\x02=\xfe\xfa\x9e6(\x82\x92:!TO\xf1?\b\n\b\x04\x1c!\x04I\xadG_\x90U\x0f\x1f%\n\x01\x95\xfc\xfa\x0e\xfd.\a\r\x05\x01\x03\x01\x05\x0fk*\x02.\x02\x01=\x01;\x04\x14\x01\xca\x03\a\b\t\x14\x1d\x055\x02gN_\x0f\x02\x04\x02\x04X\x18\xb6\x1b\x1e\x89\t\x01\"\x02\v\b\x01\x02\x11\x01\n\x05\a\a\x04\x11\x06\x11\x02\x06\x03\x10\x10#\x02#\x04\x03\n\x01\x01\f\x15\x0229\x052Q\x1c\x064\x02\x011\x01\xe0\x0f\r\x17\x0f\f\x03\x17\x0f\x1a\x03\x03\x04\x04\x0e\f\x02\x92\xe3*\xfd\x99\xe8\x04\b\xe9\xfd6\x1f\x02\x91\x1f\xfd\xe8\x1fnA\x03;\xb8\x01|\xfa\x11\r\xa0BS\x19\fN.\a\t\b\v\x0f\x12\x02%1\x1d$\a\x11\x15\x06\x04\x80\xfb\xc9\xf6\x06\xf3\r\x01\x02\x046\t\x01\x06\x05$\x0e\x01\x80\xc6nk\x15\xfe^\x00\f\x00\x00\xff\x00\a\x00\x06\x00\x00\x0f\x00'\x007\x00G\x00W\x00g\x00w\x00\x87\x00\x97\x00\xa7\x00\xb7\x00\xc0\x00\x00\x012\x16\x15\x11\x14\x06+\x01\"&5\x11463\x05\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x1f\x01\x1e\x01\x15\x0154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x0154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x0154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x13\x11#\"&=\x01!\x11\x01 B^^B\x80B^^B\x05\xe0:F\x96j\xfc\xa0B^8(\x02\xa0(`\x1c\x98\x1c(\xfd \x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x01\x00\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x01\x00\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12`\xa0(8\xfd\x80\x04\x80^B\xfb\xc0B^^B\x04@B^\xa3\"vE\xfd\x00j\x96^B\x06\x00(8(\x1c\x98\x1c`(\xfb\x80\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x01\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x01\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\xfe\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x01\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x01\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\xfe\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x01\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x01\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x12\x01\x8e\x01\x008(\xa0\xfe\x00\x00\x14\x00\x00\xff\x00\x05\x80\x06\x00\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00o\x00\u007f\x00\x8f\x00\x9f\x00\xaf\x00\xbf\x00\xcf\x00\xdf\x00\xef\x00\xff\x01\x0f\x01\x1f\x01/\x01?\x00\x00\x012\x16\x15\x11\x14\x06#!\"&5\x11463\x01\x15\x14\x16;\x0126=\x014&+\x01\"\x06\x11\x15\x14\x16;\x0126=\x014&+\x01\"\x06\x11\x15\x14\x16;\x0126=\x014&+\x01\"\x06\x11\x15\x14\x16;\x0126=\x014&+\x01\"\x06\x0354&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x0154&#!\"\x06\x1d\x01\x14\x163!26\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x0154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x05@\x1a&&\x1a\xfb\x00\x1a&&\x1a\x01\xc0\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x80\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x02\x00\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x01\x00\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x06\x00&\x1a\xf9\x80\x1a&&\x1a\x06\x80\x1a&\xfe\xe0@\x0e\x12\x12\x0e@\x0e\x12\x12\xfe\xf2@\x0e\x12\x12\x0e@\x0e\x12\x12\xfe\xf2@\x0e\x12\x12\x0e@\x0e\x12\x12\xfe\xf2@\x0e\x12\x12\x0e@\x0e\x12\x12\xfe\xb2@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\xfb\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x02\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\xfc\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x00\x00\x00\x02\x00@\xff\x10\x04\xc0\x05`\x00\x1f\x00'\x00\x00\t\x01\x11\x14\x06\"&5\x11#\x11\x14\x06\"&5\x11\x01&4762\x1f\x01!762\x17\x16\x14$\x14\x06\"&462\x04\xa4\xfe\xdcB\\B@B\\B\xfe\xdc\x1c\x1c\x1dO\x1c\xe4\x01p\xe4\x1cP\x1c\x1c\xfe\xa0\x83\xba\x83\x83\xba\x03\xdc\xfe\xdc\xfc\xc8.BB.\x01\x80\xfe\x80.BB.\x038\x01$\x1cP\x1c\x1c\x1c\xe4\xe4\x1c\x1c\x1dO広\x83\xba\x83\x00\x05\x00\x00\xff\x80\x06\x80\x05\x80\x00\x0f\x00\x1d\x003\x00C\x00Q\x00\x00\x01\x14\x0e\x01#\".\x0154>\x0132\x1e\x01\x01\x14\x06#\".\x0154632\x1e\x01\x052\x04\x12\x15\x14\x0e\x02#\"&#\"\x06#\"54>\x02%\".\x0154>\x0132\x1e\x01\x15\x14\x0e\x01%2\x16\x15\x14\x0e\x01#\"&54>\x01\x03\f&X=L|<&X=M{<\xfe\xaaTML\x83FTML\x83F\x01\x8av\x01\x12\xb8\"?B+D\xef?B\xfdJ\xb7p\xa7\xd0\x01H=X&<{M=X&<|\x01dMTF\x83LMTF\x83\x04(\x012\x1e\x01\x02\xc0r_-\x02$\x1a\xc0\x1a$\x02-_rU\x96\xaa\x96U\x03\xf0\x91\xc5%\xfc\xcb\x1a&&\x1a\x035%ő\x80\xf3\x9d\x9d\xf3\x00\x00\x00\x00\x03\x00\x00\xff\x00\x06\x80\x05\x80\x00\x03\x00\a\x00\x1f\x00\x00\x05\x01\x11\x05'-\x01\r\x01\x11\x14\x06\a\x01\x06\"'\x01.\x015\x11467\x0162\x17\x01\x1e\x01\x03\x80\x02\x80\xfd\x80@\x02\xba\xfdF\xfdF\x05\xfa$\x1f\xfd@\x1cB\x1c\xfd@\x1f$.&\x02\xc0\x16,\x16\x02\xc0&.]\x01]\x02|\xe9q\xfe\xfe\xfe\x02\xfd\x00#<\x11\xfe\x80\x10\x10\x01\x80\x11<#\x03\x00(B\x0e\x01\x00\b\b\xff\x00\x0eB\x00\x00\x00\x00\a\x00\x00\xff\x00\b\x80\x06\x00\x00\x03\x00\a\x00\v\x00\x0f\x00\x13\x00\x17\x00B\x00\x00\x05%\x11\x05'-\x01\x05\x01%\x11\x05'-\x01\x05'%\x11\x05'-\x01\x05\x01\x11\x14\x06\a\x05\x06\"'%&'\x06\a\x05\x06\"'%.\x015\x11467%\x11467%62\x17\x05\x1e\x01\x15\x11\x05\x1e\x01\x02\x80\x01\x80\xfe\x80@\x01\x94\xfel\xfel\x05\xd4\x01\x80\xfe\x80@\x01\x94\xfel\xfel,\x01\x80\xfe\x80@\x01\xb9\xfeG\xfeG\x05\xf9&!\xfe@\x19@\x19\xfe@\x04\x03\x02\x05\xfe@\x19@\x19\xfe@!&+#\x01\xb2+#\x01\xc0\x176\x17\x01\xc0#+\x01\xb2$*`\xc0\x01:\xa4p\xad\xad\xad\xfd\x8d\xc0\x01:\xa4p\xad\xad\xadx\xa5\x01\n\xa4p\xbd\xbd\xbd\xfd=\xfe`$>\x10\xe0\x0e\x0e\xe0\x02\x02\x02\x02\xe0\x0e\x0e\xe0\x10>$\x01\xa0&@\x10\xba\x01\x90&@\x10\xc0\n\n\xc0\x10@&\xfep\xba\x10@\x00\x00\x06\x00\x00\xff\xfe\b\x00\x05\x02\x00\x03\x00\t\x00\x1f\x00&\x00.\x00A\x00\x00\x01!\x15!\x03\"\x06\a!&\x032673\x02!\"\x0254\x0032\x1e\x01\x15\x14\a!\x14\x16%!254#!5!2654#!%!2\x1e\x02\x15\x14\a\x1e\x01\x15\x14\x0e\x03#!\a8\xfe\x01\x01\xff\xfcZp\x06\x01\x98\x12\xa6?v\x11\xddd\xfe\xb9\xd6\xfd\x01\x05Ί\xcde\x02\xfdns\xfb6\x01(\xcd\xc7\xfe\xd2\x01\x19N[\xbe\xfe\xfc\xfe\xeb\x02RW\x88u?\xacrt1Sr\x80F\xfd\x9d\x04\xad|\xfe\xd2iZ\xc3\xfd\xb7@7\xfe\xcd\x01\b\xd7\xd0\x01\x13\x88މ\x11\x1eoy2\xa7\xb4\xbeIM\x90\xd7\x1cC~[\xb5R \xa6yK{T:\x1a\x00\x00\x00\a\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x1e\x00%\x00,\x00A\x00G\x00K\x00\x00\x012\x16\x15\x11\x14\x06#!\"&5\x11463\x13!\x11!2654'654.\x02\x03#532\x15\x14\x03#532\x15\x14\x05\"&5!654&#\"\x06\x15\x14\x16327#\x0e\x01\x032\x17#>\x01\x03!\x15!\x04\xe0w\xa9\xa9w\xfc@w\xa9\xa9w\xd3\xfe\x8d\x01~u\xa0\x8fk'JTM\xb0\xa3wa\xb9\xbd|\x02\nDH\x01\x9b\x01\x95\x81\x80\xa4\x9e\x86\xcd>\x8a\vI1q\v\xfe\x04Fj\x01?\xfe\xc1\x05\x80\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\xfe\x91\xfc\xedsq\x9e*4p9O*\x11\xfe¸Z^\xfe\xb1\xd9qh LE\n\x14\x84\xb1\xac\x82\x87\xa4\xbf\"(\x01nz8B\x01\nM\x00\x00\x00\x04\x00\x00\xff\x80\a\x00\x05\x80\x00\a\x00\x1b\x00'\x00?\x00\x00\x00\x14\x06\"&462\x004&#\"\a\x17\x1e\x01\a\x0e\x01'.\x01'\x1e\x0132\x014&#\"\x06\x15\x14\x163267\x14\x00#\x01\x0e\x01#\"&/\x01\x11\x05632\x17\x016\x0032\x00\x06.\x8fʏ\x8f\xca\xfd\x8d\x92h\x1b\x1bhMA\x1f\x1f\x98L\x15R\x14 vGh\x03г~\u007f\xb3\xb3\u007f~\xb3\x96\xfe\xf5\xbc\xfeK\f\u0084y\xba\x19\xe6\x01\x85O^\r\x16\x01\x1c\x02\x01\v\xbb\xbc\x01\v\x04\x1fʏ\x8fʏ\xfb\xbeВ\x06*\x1f\x97LM@\x1f\b!\b\xfeשw\x03\xc0w\xa9\xf7\x8eȍ\x8dde\x8d\x03)\xa0qrOPq\xfeȦs:0\x14\x14\x183=\x027\x16\x1b\x01'\x0e\x03\x0f\x01\x03.\x01?\x0167'\x01\x03\x0e\x01\x0f\x01\x06\a\x17\x03\x13\x17\x1667\x01\x06\x03%'\x13>\x01\x17\x1e\x05\x01\x13\x16\x06\a\x0e\x05\a&\x03%'7\x03%7.\x03/\x01\x056\x16\x1f\x01\x16\x03D\x0f\x02\xfe\\$>\x10\v\a\x0f\t\"\x02N,\xb4\x93?a0\x1f\x03\x04\xbe\x11\x02\a\b#O\x8c\x06\x80\xbc\f1\x13\x12G\x94\b\xe6\xd3\a\xaa\xe29\xfd'/\xda\xfe\xc3\x13\xe1\x14P(\x181#0\x180\x02\x97\xd4\x12\v\x16\r($=!F\v\"\xe7\x019|\x8e\xdc\xfe]\x97\"RE<\x11\x11\x01\x95\x1f6\f\v'\x01o\xfe\x90\x16\x1d\x039%\x1b8J$\\\a\f\x02:\xfe\x85\\H\x91iT\x15\x15\x01e\x1a<\x11\x12?}V\xfd\xea\xfe\x99\x1d#\x03\x04\a\x05\xa4\x01o\x01j\xad\x10\x16\x16\x03\xb2?\xfe\x8c\xbb\f\x01d\x1f\x1c\x04\x02\x14\x16,\x196\xfe\xc5\xfe\x95%N#\x14\"\x16\x16\n\x12\x03H\x01l\xc3\xedS\xfe\x8b\x14VY\x9a]C\r\r\x01\x03\x1b\x0f\x0f=\x00\x00\x04\x00\x00\xff@\b\x00\x05\x80\x00\a\x00\x11\x00\x19\x00C\x00\x00\x004&\"\x06\x14\x162\x13!\x03.\x01#!\"\x06\a\x004&\"\x06\x14\x162\x13\x11\x14\x06+\x01\x15\x14\x06\"&=\x01!\x15\x14\x06\"&=\x01#\"&5\x1146;\x01\x13>\x013!2\x16\x17\x1332\x16\x01\xe0^\x84^^\x84\x82\x03\xf8Y\x02\x18\t\xfd\x00\t\x18\x02\x05\x03^\x84^^\x84\xfe\x12\x0e`p\xa0p\xfc\x00p\xa0p`\x0e\x12\x83]\x1ci\x17\xa2b\x03\x00b\xa2\x17i\x1c]\x83\x01~\x84^^\x84^\x01\xe0\x01e\b\x13\x13\b\xfd\x19\x84^^\x84^\x01\x00\xfe\x80\x0e\x12\x80PppP\x80\x80PppP\x80\x12\x0e\x01\x80]\x83\x01\xa3^\u007f\u007f^\xfe]\x83\x00\x04\x00\x00\xff\x00\b\x00\x06\x00\x003\x00;\x00E\x00M\x00\x00\x012\x16\x15\x11\x14\x06+\x01\x15\x14\x06\"&=\x01!\x15\x14\x06\"&=\x01#\"&5\x1146;\x01\x13>\x01;\x015463!2\x16\x1d\x0132\x16\x17\x13\x00264&\"\x06\x14\x01!\x03.\x01#!\"\x06\a\x00264&\"\x06\x14\a ]\x83\x12\x0e`p\xa0p\xfc\x00p\xa0p`\x0e\x12\x83]\x1ci\x17\xa2b\x80\x12\x0e\x01\xc0\x0e\x12\x80b\xa2\x17i\xf9\xfa\x84^^\x84^\x01d\x03\xf8Y\x02\x18\t\xfd\x00\t\x18\x02\x04!\x84^^\x84^\x02\x80\x83]\xfe\x80\x0e\x12@PppP@@PppP@\x12\x0e\x01\x80]\x83\x01\xa3^\u007f\xe0\x0e\x12\x12\x0e\xe0\u007f^\xfe]\xfe ^\x84^^\x84\x01\x82\x01e\b\x13\x13\b\xfc\xbb^\x84^^\x84\x00\x01\x00 \xff\x00\x05\xe0\x06\x00\x003\x00\x00$\x14\x06#!\x1e\x01\x15\x14\x06#!\"&5467!\"&47\x01#\"&47\x01#\"&47\x0162\x17\x01\x16\x14\x06+\x01\x01\x16\x14\x06+\x01\x01\x05\xe0&\x1a\xfe2\x01\n$\x19\xfe\xc0\x19$\n\x01\xfe2\x1a&\x13\x01\x92\xe5\x1a&\x13\x01\x92\xc5\x1a&\x13\x01\x80\x134\x13\x01\x80\x13&\x1a\xc5\x01\x92\x13&\x1a\xe5\x01\x92Z4&\x11\x8d&\x19##\x19&\x8d\x11&4\x13\x01\x93&4\x13\x01\x93&4\x13\x01\x80\x13\x13\xfe\x80\x134&\xfem\x134&\xfem\x00\x04\x00\x00\xff\x80\x06\x00\x05\x80\x00\x15\x00+\x00D\x00P\x00\x00\x014'&#\"\a\x06\x15\x14\x16327632\x17\x1632674'&!\"\a\x06\x15\x14\x1632763 \x17\x16326\x134'&$#\"\a\x0e\x01\x15\x14\x16327632\x04\x17\x1632>\x01\x10\x02\x04 $\x02\x10\x12$ \x04\x04g\x1e\xc1\xfe\x85\x9a*\x1b\x16\x05 \x84o\xe2\xab\x13\x0e\x13\x1c`#\xed\xfeə\x960#\x19\a\x1ez\x81\x01\x17\xd1\x18\x0e\x19#l(~\xfe\xb2\xb0̠\x17\x1f)\x1f\v\x1d\x85\xae\x9f\x01-g\x15\x13\x1d+\xcd\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01F \x13s\"\t+\x14\x1d\b\x1bg\v\x1b\xec(\x15\x8d*\r3\x19#\b!|\r#\x01\x11/\x17IK/\a%\x1e\x1f*\b%D=\f)[\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x01\x00\x00\xff\x80\x04\x00\x06\x00\x00\x13\x00\x00\t\x01\x17!\x11!\a\x03\a!\x11\x01'!\x11!7\x137!\x04\x00\xfe\xd1\x18\x01\x17\xfe\x05,\x8e\x1e\xfe\xd3\x01/\x18\xfe\xe9\x01\xfb,\x8e\x1e\x01-\x04\xd1\xfd\xba\x1f\xfea\x1e\xfe\xef\x1e\x01/\x02G\x1e\x01\x9f\x1e\x01\x11\x1e\x00\x00\x00\x11\x00\x00\x00\x8c\t\x00\x04t\x00\x0e\x00%\x00/\x00;\x00<\x00H\x00T\x00b\x00c\x00q\x00\u007f\x00\x8d\x00\x90\x00\x9e\x00\xac\x00\xc0\x00\xd4\x00\x00%7\x03.\x01#\"\x06\x15\x03\x17\x1e\x0132%7\x034'&\"\a\x06\x15\a\x03\x14\x17\x15\x14\x17\x1632765\x01\x17\a\x06\"/\x017627\x17\a\x06#\"5'7432\x01\x03\x17\a\x14#\"/\x017632\x1f\x01\a\x06#\"5'7432\x1f\x01\a\x06#\"&5'74632\t\x01\x13\a\x14\x06#\"/\x01\x13632\x167\x13\a\x14\x06#\"/\x01\x13632\x167\x13\a\x06#\"/\x01\x134632\x16\x019\x01\x03\x13\a\x14\x06\"&/\x01\x13462\x16\x17\x13\a\x14\x06\"&/\x01\x13>\x012\x16\x13\a1\x14\x06\"&/\x02\x13567632\x17\x16\x17\x01\x14\x06#!.\x015\x1147632\x00\x17632\x16\x03\x10\x10\x10\x01\r\n\t\x0e\x0e\x0e\x01\r\t\x16\x01*\v\f\r\b\x10\b\r\x01\n\v\x06\t\x0e\v\t\t\xfb\xec\x14\x14\x02\x0e\x02\x11\x11\x02\x0eX\x1a\x1a\x02\b\t\x17\x17\t\b\x01\x1a\xbc\x19\x19\v\n\x02\x15\x15\x02\n\v^\x17\x17\x02\f\r\x15\x15\r\f`\x15\x15\x02\x0e\x06\t\x14\x14\t\x06\x0e\x01\x81\xfe\xdf\x15\x15\n\a\x10\x02\x12\x12\x02\x10\a\n^\x13\x13\v\b\x12\x02\x10\x10\x02\x12\b\vb\x12\x12\x02\x14\x13\x02\x10\x10\r\b\t\f\x01\x89\xc6\x0f\x0f\x0f\x14\x0e\x01\x0e\x0e\x0f\x14\x0fc\x0e\x0e\x10\x16\x10\x01\f\f\x01\x10\x16\x0f\xd5\x0e\x12\x1a\x12\x01\x06\x06\f\x02\n\t\v\b\a\x0e\x02\x04f\xa6u\xfc\xee\r\x12\x1cU`\xc3\x01\x1e\x1159u\xa6\xa4\xf1\x02\v\n\x0e\x0e\n\xfd\xf5\xf1\n\r4\xd3\x02J\x10\b\x05\x05\b\x10\x06\xfd\xbd\x01\xeb\x01\n\a\v\t\a\r\x01l\x80~\t\t~\x80\tF\xcf\xcb\t\n\xca\xcf\t\xfe2\x01\xeb\xf5\xed\v\v\xed\xf5\f\x05\xfc\xf4\r\r\xf4\xfc\r\x1f\xea\xf6\x10\t\a\xf6\xea\x06\t\xfe\x16\x02m\xfe\x84\xf6\a\v\x12\xf6\x01|\x12\vO\xfe,\xf4\b\v\x13\xf4\x01\xd4\x13\v \xfe\x06\xf2\x15\x15\xf2\x01\xfa\t\r\r\xfd\x11\x02\xea\xfe\x02\xef\n\x0f\x0e\v\xef\x01\xfe\v\x0e\x0e\x1e\xfe\x14\xec\v\x10\x10\v\xec\x01\xec\f\x10\x10\xfe\b\xe7\r\x12\x12\rru\x02|\x03\x0f\t\a\x05\b\x12\xfd\x94u\xa5\x02\x12\r\x03\x83\x17\n\"\xfe\xf9\xc0\x16\xa6\x00\x00\x00\x04\x00\x00\xff\x00\x06\x00\x06\x00\x00\r\x00\x1b\x00)\x009\x00\x00\x00 $7\x15\x14\x06\x04 $&=\x01\x16\x00 $7\x15\x14\x06\x04 $&=\x01\x16\x00 $7\x15\x14\x06\x04 $&=\x01\x16\x00 \x04\x16\x1d\x01\x14\x06\x04 $&=\x0146\x02\x13\x01\xda\x01\x9cw\xce\xfe\x9e\xfe`\xfe\x9e\xcew\x01\x9c\x01\xda\x01\x9cw\xce\xfe\x9e\xfe`\xfe\x9e\xcew\x01\x9c\x01\xda\x01\x9cw\xce\xfe\x9e\xfe`\xfe\x9e\xcew\x01\xb9\x01\xa0\x01b\xce\xce\xfe\x9e\xfe`\xfe\x9e\xce\xce\x03\x00VT\xaaEvEEvE\xaaT\xfc\xaaVT\xaaEvEEvE\xaaT\x01*VT\xaaEvEEvE\xaaT\x04*EvE\x80EvEEvE\x80Ev\x00\b\x00\x00\xff\x00\x06\x00\x06\x00\x00\x13\x00\x1a\x00#\x00^\x00c\x00t\x00\u007f\x00\x87\x00\x00\x01\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x17\a\x11!&'\x01&\x01\x11!\"&5\x11!\x11\x01\x16\x17632\x17\x16\a\x14\x06\a\x15\x06#\"&'\x06\a\x02#\"/\x01&'&7>\x0176\x17\x16\x156767.\x0176;\x022\x17\x16\a\x06\a\x16\x1d\x01\x06\a\x16\x0167\x0e\x01\x01\x06\x17674767&5&5&'\x14\a\x0367.\x01'&'\x06\a\x06\x05&#\x163274\x05\xbc\x1c(8(\xfa\xc0(88(\x03\x80(`\x1c\x84\x01x\n\f\xfe\xc7\f\x01c\xfe`(8\xfd\x00\x02\xfe!3;:\x93\x1e\x10\x0e\x02\x01\x06A0\x86?ݫ\x99Y\x0f\r\x18\x01\x05\n\x04\t^U\x0e\t\x0247D$\x18\r\r\v\x1f\x15\x01\x17\f\x12\t\x02\x02\x01\x02\f7\xfe\x1b4U3I\x01\x81\x0f\r\x01\x06\a\x01\x03\x01\x01\x01\f\x01|\x87\x95\x02\x16\x05L3\x1b8\x1e\x02w\x18tL0\x0e\x04\x04\x84\x1c`(\xfb\x80(88(\x06@(8(\x1cD\xfe\x88\x1d\f\x019\f\xfa\x12\x04\x008(\x01\xa0\xfa\x00\x02Q\x1a\x1e\a1\x16\x1e\x01\x02\x01\x01&(!\x18;\xfe\xfa\a\f\x01\x04\n\x1a(g-\t\x0f\x02\x02Up\x88~R\x9b2(\x0f\x15/\x06\x02\x03\x05\x1e{E\xa4\xfe\x1b\x18\x86(X\x03z*Z\a%\x03(\x04\x04\x01\x01\x02\x01\x16\x0e\x01\x01\xfdi6\x1b\x01\x11\x05CmVo8\v\x18\x1c\x01\x01\x00\x00\x00\x00\x04\x00\x00\xff\x00\x06\x00\x06\x00\x00\x13\x00\x1a\x00#\x00T\x00\x00\x01\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x17\a\x11!&'\x01&\x01\x11!\"&5\x11!\x11\x13\x153\x133\x1367653\x17\x1e\x01\x17\x133\x1335!\x153\x03\x06\x0f\x01#4.\x015.\x01'\x03#\x03\x0e\x01\x0f\x01#'&'\x0335\x05\xbc\x1c(8(\xfa\xc0(88(\x03\x80(`\x1c\x84\x01x\n\f\xfe\xc7\f\x01c\xfe`(8\xfd\x00iF\xa4\x9f\x80\a\x03\x02\x04\x03\x01\x05\x03\x80\x9f\xa4F\xfe\xd4Zc\x05\x02\x02\x04\x01\x02\x01\x06\x02\x90r\x90\x02\x05\x01\x04\x04\x02\x02\x05cZ\x04\x84\x1c`(\xfb\x80(88(\x06@(8(\x1cD\xfe\x88\x1d\f\x019\f\xfa\x12\x04\x008(\x01\xa0\xfa\x00\x03\x80k\xfdk\x01\xe5\x14\x1a\x10\b\x18\x03\"\t\xfe\x1b\x02\x95kk\xfeJ\x14\x1a\x15\x03\a\t\x02\x05 \t\x02!\xfd\xdf\t\x1f\x06\x15\x15\x1a\x14\x01\xb6k\x00\x00\x04\x00\x00\xff\x00\x06\x00\x06\x00\x00\x13\x00\x1a\x00#\x00S\x00\x00\x01\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x17\a\x11!&'\x01&\x01\x11!\"&5\x11!\x11%\x15!5#7>\x02;\x01\x16\x17\x1e\x02\x1f\x01#\x15!5#\x03\x1335!\x153\a\x0e\x01\x0f\x01#&'&/\x0135!\x153\x13\x03\x05\xbc\x1c(8(\xfa\xc0(88(\x03\x80(`\x1c\x84\x01x\n\f\xfe\xc7\f\x01c\xfe`(8\xfd\x00\x01-\x01\x19Kg\x05\n\x05\x01\x02\x01\x04\x02\x05\a\x03kL\x01#D\xc0\xc3C\xfe\xe9Jg\x04\f\x03\x02\x02\x01\x04\x06\vjL\xfe\xdeD\xbd\xc2\x04\x84\x1c`(\xfb\x80(88(\x06@(8(\x1cD\xfe\x88\x1d\f\x019\f\xfa\x12\x04\x008(\x01\xa0\xfa\x00\xeajj\xa1\a\x13\b\x04\x06\x04\a\t\x04\xa1jj\x01\x11\x01\x1akk\x9f\a\x13\x04\x03\x04\x06\v\f\x9fkk\xfe\xf0\xfe\xe5\x00\x00\x00\x00\x05\x00\x00\xff\x00\x06\x00\x06\x00\x00\x13\x00\x1a\x00#\x008\x00C\x00\x00\x01\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x17\a\x11!&'\x01&\x01\x11!\"&5\x11!\x11%\x15!5#5327>\x0154&'&#!\x153\x11\x01#\x1132\x17\x16\x15\x14\a\x06\x05\xbc\x1c(8(\xfa\xc0(88(\x03\x80(`\x1c\x84\x01x\n\f\xfe\xc7\f\x01c\xfe`(8\xfd\x00\x01 \x01G]\x89L*COJ?0R\xfe\x90\\\x01\x05wx4\x1f8>\x1f\x04\x84\x1c`(\xfb\x80(88(\x06@(8(\x1cD\xfe\x88\x1d\f\x019\f\xfa\x12\x04\x008(\x01\xa0\xfa\x00\xeajj\xa7\x0f\x17\x80RQx\x1b\x13k\xfd\xd5\x01\x18\x01\f\x12!RY\x1f\x0f\x00\x00\x00\x00\x05\x00\x00\xff\x00\x06\x00\x06\x00\x00\x13\x00\x1a\x00#\x00*\x002\x00\x00\x01\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x17\a\x11!&'\x01&\x01\x11!\"&5\x11!\x11\x01\x11!57\x17\x01\x04\"&462\x16\x14\x05\xbc\x1c(8(\xfa\xc0(88(\x03\x80(`\x1c\x84\x01x\n\f\xfe\xc7\f\x01c\xfe`(8\xfd\x00\x04\x80\xfc\x00\xc0\x80\x01\x80\xfeP\xa0pp\xa0p\x04\x84\x1c`(\xfb\x80(88(\x06@(8(\x1cD\xfe\x88\x1d\f\x019\f\xfa\x12\x04\x008(\x01\xa0\xfa\x00\x01\xc0\xfe\xc0\xc0\xc0\x80\x01\x80\x80p\xa0pp\xa0\x00\x00\t\x00\x00\xff\x00\x06\x00\x06\x00\x00\x03\x00\a\x00\v\x00\x0f\x00#\x00*\x007\x00J\x00R\x00\x00\x015#\x15\x055#\x1d\x015#\x15\x055#\x15\x01\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x17\a\x11!&'\x01&\x01\x11!\"&5\x11#\x15#5!\x11\x01\x13\x16\x15\x14\x06\"&5476\x1353\x1532\x16\x02264&\"\x06\x14\x02\x80\x80\x01\x00\x80\x80\x01\x00\x80\x03<\x1c(8(\xfa\xc0(88(\x03\x80(`\x1c\x84\x01x\n\f\xfe\xc7\f\x01c\xfe`(8\x80\x80\xfe\x00\x02\x8dk\b\x91ޑ\b\x15c\x80O\x16\"\xbcjKKjK\x04\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01\x84\x1c`(\xfb\x80(88(\x06@(8(\x1cD\xfe\x88\x1d\f\x019\f\xfa\x12\x04\x008(\x01\xa0\x80\x80\xfa\x00\x02\xd1\xfe\xa3\x1b\x19SmmS\x19\x1b?\x01M\x80\x80\x1a\xfe\x1a&4&&4\x00\x00\x00\x00\x06\x00\x00\xff\x00\x06\x00\x06\x00\x00\x13\x00\x1a\x00#\x009\x00L\x00^\x00\x00\x01\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x17\a\x11!&'\x01&\x01\x11!\"&5\x11!\x11\x01\x16\x15\x11\x14\a\x06#\"/\x01#\"&=\x0146;\x0176\x01276\x10'.\x01\a\x0e\x01\x17\x16\x10\a\x06\x16\x17\x16'2764'.\x01\x0e\x01\x17\x16\x14\a\x06\x16\x17\x16\x05\xbc\x1c(8(\xfa\xc0(88(\x03\x80(`\x1c\x84\x01x\n\f\xfe\xc7\f\x01c\xfe`(8\xfd\x00\x01\xec\x14\x14\b\x04\f\v\xa6\x83\x0e\x12\x12\x0e\x83\xa6\x10\x01\xb4\x1f\x13\x81\x81\x106\x14\x15\x05\x11dd\x11\x05\x15\x12\xbd\x1b\x14WW\x126&\x02\x1344\x13\x02\x13\x14\x04\x84\x1c`(\xfb\x80(88(\x06@(8(\x1cD\xfe\x88\x1d\f\x019\f\xfa\x12\x04\x008(\x01\xa0\xfa\x00\x03.\b\x16\xfd\xe0\x16\b\x02\t\xa7\x12\x0e\xc0\x0e\x12\xa7\x0f\xfdG\x18\x9f\x01\x98\x9f\x15\x06\x11\x115\x15{\xfe\xc2{\x155\x10\x0f\x94\x14]\xfc]\x13\x02$5\x149\x949\x145\x12\x11\x00\x00\x00\x05\x00\x00\xff\x00\x06\x00\x06\x00\x00\x13\x00\x1a\x00#\x003\x00C\x00\x00\x01\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x17\a\x11!&'\x01&\x01\x11!\"&5\x11!\x11\x012\x16\x15\x11\x14\x06#!\"&5\x11463\x05\x16\x15\x11\x14\a\x06#\"'\x015\x01632\x05\xbc\x1c(8(\xfa\xc0(88(\x03\x80(`\x1c\x84\x01x\n\f\xfe\xc7\f\x01c\xfe`(8\xfd\x00\x02\x804LL4\xfe\x804LL4\x03l\x14\x14\b\x04\x0e\t\xfe\xf7\x01\t\t\x0e\x04\x04\x84\x1c`(\xfb\x80(88(\x06@(8(\x1cD\xfe\x88\x1d\f\x019\f\xfa\x12\x04\x008(\x01\xa0\xfa\x00\x03\x80L4\xfe\x804LL4\x01\x804L\x02\b\x16\xfd\xc0\x16\b\x02\t\x01\nZ\x01\n\t\x00\x00\x00\x06\x00\x00\xff\x00\x06\x00\x06\x00\x00\x13\x00\x1a\x00#\x007\x00K\x00[\x00\x00\x01\x1e\x01\x15\x11\x14\x06#!\"&5\x11463!2\x16\x17\a\x11!&'\x01&\x01\x11!\"&5\x11!\x11\x01>\x01\x1f\x01\x1e\x01\x0f\x01\x17\x16\x06\x0f\x01\x06&'\x03&7!\x16\a\x03\x0e\x01/\x01.\x01?\x01'&6?\x016\x16\x17\x01.\x017\x13>\x01\x1f\x01\x1e\x01\a\x03\x0e\x01'\x05\xbc\x1c(8(\xfa\xc0(88(\x03\x80(`\x1c\x84\x01x\n\f\xfe\xc7\f\x01c\xfe`(8\xfd\x00\x01`\b\x1a\v3\v\x03\b\xb6\xb6\b\x03\v3\v\x1a\b\xe2\x0e\x0e\x04\x04\x0e\x0e\xe2\b\x1a\v3\v\x03\b\xb6\xb6\b\x03\v3\v\x1a\b\xfev\r\x0f\x02\x8a\x02\x16\r?\r\x0f\x02\x8a\x02\x16\r\x04\x84\x1c`(\xfb\x80(88(\x06@(8(\x1cD\xfe\x88\x1d\f\x019\f\xfa\x12\x04\x008(\x01\xa0\xfa\x00\x03\x80\v\x03\b&\b\x1a\v\xf3\xf3\v\x1a\b&\b\x03\v\x01-\x13\x13\x13\x13\xfe\xd3\v\x03\b&\b\x1a\v\xf3\xf3\v\x1a\b&\b\x03\v\xfd\x06\x02\x16\r\x03?\r\x0f\x02\n\x02\x16\r\xfc\xc1\r\x0f\x02\x00\x01\x00'\xff\x97\x05\xd9\x06\x00\x006\x00\x00\x01\x15\x06#\x06\x02\x06\a\x06'.\x04\n\x01'!\x16\x1a\x01\x16\x1767&\x0254632\x16\x15\x14\a\x0e\x01\".\x01'654&#\"\x06\x15\x14\x1632\x05\xd9eaAɢ/PR\x1cAids`W\x1b\x01\x1b\x1aXyzO\xa9v\x8e\xa2д\xb2\xbe:\a\x19C;A\x12\x1f:25@Ң>\x02\xc5\xc6\x17\x88\xfe\xf2\xa1\x1a-0\x115r\x8f\xe1\x01\a\x01n\xcf\xda\xfe\x97\xfe\xef\xc6`\xa9\xedH\x01(\xb9\xc0\xf5\xd3\xc0\x9f\u007f\x01\x04\f' gQWZc[\xba\xd7\x00\x00\b\x00\x00\xff\x00\a\x00\x06\x00\x00\x03\x00\x06\x00\n\x00\x0e\x00\x12\x00\x15\x00\x19\x00-\x00\x00\x13\x01\x11%\x057'\t\x01%\x05'-\x01\x05'%\x11\t\x01\x17\x11\x05%\x01\x11\x05\x11\x14\a\x01\x06\"'\x01&5\x1147\x0162\x17\x01\x16\xd8\x02[\xfe\xb2\xfe\xb5\xc1\xc1\x033\x02[\xfe\xf3\xfe\xb2M\x01\x10\xfe\xf0\xfe\xf0\x8b\x01N\xfd\xa5\x04\xcd\xc1\xfe\xb5\x01\r\xfd\xa5\x033\"\xfc\xcd\x15,\x15\xfc\xcd\"\"\x033\x15,\x15\x033\"\x01o\xfen\x01g\xdf$\x81\x81\xfc\xdc\x01\x92\xb4߆\xb6\xb6\xb6]\xdf\x01g\xfen\xfe\xef\x81\x01\x02$\xb4\x01\x92\xfe\x99+\xfd\xde)\x17\xfd\xde\r\r\x02\"\x17)\x02\")\x17\x02\"\r\r\xfd\xde\x17\x00\x00\x00\x00\x02\x00\x00\x00\x00\b\x00\x05x\x00#\x00W\x00\x00\x01\x1e\x01\x15\x14\x06#\"&#!+\x02.\x015467&54632\x176$32\x04\x12\x15\x14\x06\x01\x14\x16327.\x01'\x06#\"&54632\x1e\x0532654&#\"\a\x17632\x16\x15\x14\x06#\".\x05#\"\x06\a\bo\x89\xec\xa7\x04\x0f\x03\xfbG\x01\x02\x05\xaa\xecn\\\f\xa4u_MK\x01'\xb3\xa6\x01\x18\xa3\x01\xfą|\x89g\x10?\fCM7MM5,QAAIQqAy\xa7\xa8{\x8fb]BL4PJ9+OABIRo?z\xaa\x02\xfc.\xc7z\xa4\xe9\x01\n\xe7\xa5n\xba6'+s\xa2:\x9a\xbc\xa1\xfe\xec\xa3\x06\x18\xfe\xf0z\x8ec\x14I\x0eAC65D*DRRD*\x8fwy\x8eal@B39E*DRRD*\x8d\x00\x00\x00\x00\x06\x00\x00\xff\x00\a\x00\x06\x00\x00\x0f\x00\x17\x00\x1f\x00'\x00/\x007\x00\x00\x00 \x04\x16\x12\x10\x02\x06\x04 $&\x02\x10\x126$ \a\x1762\x177\x017&47'\x06\x10\x00 7'\x06\"'\a\x12 6\x10& \x06\x10\x05\x176\x10'\a\x16\x14\x02\xca\x01l\x01L\xf0\x8e\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x02\xc0\xfe\x84\xab\xc2R\xaaR\xc2\xfb\xf1\xc2\x1c\x1c\xc2Z\x02B\x01|\xab\xc2R\xaaR\xc2\xca\x01>\xe1\xe1\xfe\xc2\xe1\x03d\xc2ZZ\xc2\x1c\x06\x00\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x0eZ\xc2\x1c\x1c\xc2\xfb\xf1\xc2R\xaaR«\xfe\x84\xfd\xbeZ\xc2\x1c\x1c\xc2\x01&\xe1\x01>\xe1\xe1\xfe\xc2\b«\x01|\xab\xc2R\xaa\x00\x01\x00 \xff \x06\xe0\x05\xd7\x00!\x00\x00\x01\x14\x02\x06\x04 $&\x0254\x12$7\x15\x06\x00\x15\x14\x1e\x02 >\x0254\x00'5\x16\x04\x12\x06\xe0\x89\xe7\xfe\xc0\xfe\xa0\xfe\xc0\xe7\x89\xc2\x01P\xce\xdd\xfe\xddf\xab\xed\x01\x04\xed\xabf\xfe\xdd\xdd\xce\x01P\xc2\x02\x80\xb0\xfe\xc0牉\xe7\x01@\xb0\xd5\x01s\xf0\x1f\xe4-\xfe\xa0\xe6\x82\xed\xabff\xab\xed\x82\xe6\x01`-\xe4\x1f\xf0\xfe\x8d\x00\x00\x01\x00\x13\xff\x00\x06\xee\x06\x00\x00c\x00\x00\x136\x12721\x14\a\x0e\x04\x1e\x01\x17\x1e\x01>\x01?\x01>\x01.\x01/\x01.\x03/\x017\x1e\x01\x1f\x016&/\x017\x17\x0e\x01\x0f\x01>\x01?\x01\x17\x0e\x01\x0f\x01\x0e\x01\x16\x17\x1e\x01>\x01?\x01>\x02.\x04/\x01&3\x161\x1e\b\x17\x12\x02\x04#\"$&\x02\x13\b\xd8\xc5\x05\x01\b(@8!\x05IH2hM>\x10\x10'\x1c\x0f\x1b\r\x0e\n)-*\x0e\rh'N\x14\x13\x01'\x15\x14\xa1\xa0!'\x03\x04\x16O\x1c\x1cg,R\x13\x13\x1f\"\x14/!YQG\x16\x15\x0154'6\x133&5\x1147#\x16\x15\x11\x14\x055\x06#\"=\x0132\x1635#47#\x16\x1d\x01#\x15632\x163\x15#\x15\x14\x1e\x0332\x014&\"\x06\x15\x14\x1626%\x11\x14\x06#!\"&5\x11463!2\x16\x02F]kbf$JMM$&\xa6N92Z2\x1d\b\x02\a\x18\x06\x15&`\x06\xe3\x06\xab\x0f9\x0eUW=\xfd\xf0N9:PO;:\x16dhe\x03\\=R\x91\x87\x01\xcd\xca\f\n+)\u007f\xb3\x17\b&'\x1f)\x17\x15\x1e-S9\xfe\xd0\x199kJ\xa5<\x04)Um\x1c\x04\x18\xa9Q\x8b\xb9/\xfc\xbe-Y\x02a^\"![\xfd\x9bY\xb1\xc4'(<`X;\x01_\x04\x02\x06\xbeL6#)|\xbe\x04\xfe\x93\x83\x04\x0etWW:;X\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\v\x00\x1b\x00\x00\t\x01#\x03\x06\a'\x03#\x01\x113\x01\x11\x14\x06#!\"&5\x11463!2\x16\x03)\x01\np\x9d\x18\x14*\x9bx\x01\ae\x02שw\xfc@w\xa9\xa9w\x03\xc0w\xa9\x02\x14\x01\xf3\xfe\xc80,\\\x018\xfe\x13\xfe\xbc\x03\x8a\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x02\x009\xff\x00\x04\xc7\x06\x00\x00\x1d\x00I\x00\x00\x00\x14\x06#\"'\x06\a\x02\x13\x16\x06\a#\"&'&>\x03767&5462\x04\x10\x02\x04#\"'.\x017>\x01\x17\x1632>\x024.\x02\"\x0e\x02\x15\x14\x17\x16\x0e\x01&'&54>\x0232\x04\x03JrO<3>5\xf7-\x01\x1b\x15\x05\x14\x1e\x02\x0e\x15&FD(=G\x10q\xa0\x01\xee\x9c\xfe\xf3\x9e@C\x15\x17\x05\x05$\x1539a\xb2\x80LL\x80\xb2²\x80L4\n\r&)\n@]\x9c\xd8v\x9e\x01\r\x04\x14\xa0q#CO\xfe\x8d\xfe\x18\x16!\x02\x1b\x14~\U000ffd42\x0172765'.\x01/\x01\"\a\x0e\x01\a#\"&'&5\x10\x01\x0e\b\x16\r\x01\x11\x0e\xb9}\x8b\xb9\x85\x851R<2\"\x1f\x14\f\x017\x12\x03\x04MW'$\t\x15\x11\x15\v\x10\x01\x01\x02\x05;I\x14S7\b\x02\x04\x05@\xee5sQ@\x0f\b\x0e@\b)\xadR#DvTA\x14\x1f\v;\x14\x04\n\x02\x020x\r\x05\x04\b\x12I)\x01\x04\x04\x03\x17\x02\xda\x13!\x14:\x10\x16>\f\x8b\x01+\x03\x14)C\x04\t\x016.\x01\x13\x00\x00\x00\x00\x06\x00\x00\xff>\b\x00\x05\xc2\x00\n\x00\x16\x00!\x00-\x00I\x00[\x00\x00\x004&#\"\x06\x15\x14\x1632\x014&#\"\x06\x15\x14\x16326\x024&#\"\x06\x15\x14\x1632\x014&#\"\x06\x15\x14\x16326\x01&#\"\x04\x02\x15\x14\x17\x06#\".\x03'\a7$\x114\x12$32\x04\x16\x01\x14\x06\a\x17'\x06#\"$&\x106$32\x04\x16\x02D2)+BB+)\x03\x193(\x1b--\x1b(3\xec1)+BB+)\x02\xac4'\x1b--\x1b'4\xfe\xf6\x1f'\xa9\xfe\xe4\xa3\x17#!\x1a0>\x1bR\t\xfdH\xfe\xde\xc3\x01MŰ\x019\xd3\x02o\x89u7ǖD\xa9\xfe䣣\x01\x1c\xa9\xa1\x01\x1c\xab\x04\nR23('3\xfe_\x1c,-\x1b\x1c-,\x01\xefR23('3\xfe_\x1c,-\x1b\x1c-,\x01\xaa\x04\x9a\xfe\xf9\x9cNJ\x03\x03\n\x04\x11\x02\u007f\xda\xcb\x01\x1f\xa9\x01\x1c\xa3\x84\xe9\xfd?u\xd5W\xb5m%\x8d\xf2\x01\x1e\xf2\x8d\x8d\xf3\x00\x01\x00\x00\xff\x00\x06\xff\x06\x00\x00\x1e\x00\x00\x01\x16\a\x01\x06\a\x06#\"'%\x03\x06#\"'.\x015\x11\t\x01%&'&7\x01632\x06\xe4!\x06\xff\x00\x05\x1b\x0e\x11\v\r\xfe;\xf2\x12\x1f\r\t\x13\x17\x03`\xfb\xd3\xfeu%\x03\x02\"\x06\x80\x0f\x11\x14\x05\xf5\x18(\xfa\x00\x1d\x10\b\x05\xb9\xfe\xd9\x17\x04\a!\x14\x01]\x04#\xfcc\xa2\x0e)(\x13\x03\xc0\t\x00\x00\x00\x00\x02\x00\x00\xff\x00\x06\xff\x05\xf7\x00\x1a\x00 \x00\x00\x01\x16\a\x01\x06\a\x06#\"'%\x01\x06#\"'.\x015\x11%&'&7\x016\x01\x13\x01\x05\t\x01\x06\xe4!\x06\xff\x00\x05\x1b\x0e\x11\v\r\xfd\xf1\xfe\xd6\x12\x1d\x0e\t\x13\x16\xfe(%\x03\x03#\x06\x80#\xfe\xcb\xdd\xfaf\x01P\x03_\xfe\"\x05\xf5\x18(\xfa\x00\x1d\x10\b\x05\xd7\xfe\xb9\x15\x04\a!\x14\x01\xc4\xc1\x0e)'\x14\x03\xc0\x15\xfa\x0e\x05+\xfcʼn\x02\u007f\xfc\xe3\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x004\x00I\x00\x00\x00\x10\x02\x06\x04#\"$'&6?\x0163\x16\x17\x1e\x0132>\x024.\x02#\"\x06\a\x17\x16\a\x06#!\"&5\x11476\x1f\x016$32\x04\x16\x05\x11\x14\x06#!\"&=\x0146;\x01\x1146;\x012\x16\x06\x00z\xce\xfe䜬\xfe\xcam\a\x01\b\x89\n\x0f\x10\aI\xd4wh\xbd\x8aQQ\x8a\xbdhb\xb4F\x89\x1f\x11\x11*\xfe@\x1a&('\x1e\x82k\x01\x13\x93\x9c\x01\x1c\xce\xfd\xfa\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\xe0\x12\x0e@\x0e\x12\x03\x1c\xfe\xc8\xfe\xe4\xcez\x91\x84\n\x19\b\x8a\t\x02\n_hQ\x8a\xbdн\x8aQGB\x8a\x1e'(&\x1a\x01\xc0*\x11\x11\x1f\x81eozΘ\xfe@\x0e\x12\x12\x0e@\x0e\x12\x01`\x0e\x12\x12\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x1b\x00\x00\x00 \x0e\x02\x10\x1e\x02 >\x02\x10.\x01\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x03\x82\xfe\xfc\xed\xabff\xab\xed\x01\x04\xed\xabff\xab\x01\x91\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x05\x00f\xab\xed\xfe\xfc\xed\xabff\xab\xed\x01\x04\xed\xab\xfe\xb7\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x01\x00>\xff\x80\x06\xc2\x05\x80\x00\x85\x00\x00\x05\"&#\"\x06#\"&54>\x02765\x034'&#!\"\a\x06\x15\x03\x14\x17\x1e\x03\x15\x14\x06#\"&#\"\x06#\"&54>\x02765'\x1146.\x04'.\x01\"&54632\x1632632\x16\x15\x14\x0e\x02\a\x06\x15\x13\x14\x17\x163!2765\x134'.\x0254632\x1632632\x16\x15\x14\x0e\x02\a\x06\x15\x13\x14\x17\x1e\x03\x15\x14\x06\x06\x92,\xb1-,\xb0,\x18\x1a\",:\x10!\x01\x01\r%\xfd]&\r\x01\x01%\x10@2(\x19\x18/\xb9.+\xaa*\x17\x19\x1f)6\x0f!\x01\x01\x01\x02\x05\b\x0e\t\x0f<.$\x18\x18.\xb9.*\xa9*\x19\x19\"+8\x0f#\x01\x01\r\x1a\x02\xbb\x19\r\x01\x01#\x12Q3\x19\x19,\xb0,+\xac+\x19\x19#-:\x0f#\x01\"\x10\x19$$\x19\x01\xf0\f/:yu\x8e\xa6xv)%$\x00\t\x00\x00\xff\x80\x06\x00\x05\x00\x00\x03\x00\x13\x00\x17\x00\x1b\x00\x1f\x00/\x00?\x00C\x00G\x00\x00%\x15!5%2\x16\x15\x11\x14\x06#!\"&5\x11463\x01\x15!5\x13\x15#5\x01\x15!5\x032\x16\x15\x11\x14\x06#!\"&5\x11463\x012\x16\x15\x11\x14\x06#!\"&5\x11463\x05\x15#5\x13\x15!5\x01`\xfe\xa0\x02\xc0\x1a&&\x1a\xff\x00\x1a&&\x1a\x01\xa0\xfc\xa0\xe0\xe0\x06\x00\xfd \xe0\x1a&&\x1a\xff\x00\x1a&&\x1a\x03\x80\x1a&&\x1a\xff\x00\x1a&&\x1a\x02@\xe0\xe0\xfc\xa0\x80\x80\x80\x80&\x1a\xff\x00\x1a&&\x1a\x01\x00\x1a&\x01\x80\x80\x80\x02\x00\x80\x80\xfc\x00\x80\x80\x04\x80&\x1a\xff\x00\x1a&&\x1a\x01\x00\x1a&\xfe\x00&\x1a\xff\x00\x1a&&\x1a\x01\x00\x1a&\x80\x80\x80\x02\x00\x80\x80\x00\x01\x00\x00\xff\x80\x06\x00\x05\x80\x00%\x00\x00\x012\x16\x10\x06 &547%\x06#\"&\x10632\x17%&546 \x16\x10\x06#\"'\x05\x16\x14\a\x056\x04\xc0\x85\xbb\xbb\xfe\xf6\xbb\x02\xfe\x98\\~\x85\xbb\xbb\x85~\\\x01h\x02\xbb\x01\n\xbb\xbb\x85~\\\xfe\x98\x02\x02\x01h\\\x02\x00\xbb\xfe\xf6\xbb\xbb\x85\f\x16\xb4V\xbb\x01\n\xbbV\xb4\x16\f\x85\xbb\xbb\xfe\xf6\xbbV\xb4\x16\x18\x16\xb4V\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00%\x005\x00\x00$4&#\"\a'64'7\x163264&\"\x06\x15\x14\x17\a&#\"\x06\x14\x16327\x17\x06\x15\x14\x162\x01\x11\x14\x06#!\"&5\x11463!2\x16\x05\x00}XT=\xf1\x02\x02\xf1=TX}}\xb0~\x02\xf1>SX}}XS>\xf1\x02~\xb0\x01}\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\xfd\xb0~:x\x10\x0e\x10x:~\xb0}}X\a\x10x9}\xb0}9x\x10\aX}\x03\xe0\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\a\x00\x00\xff\x00\a\x00\x06\x00\x00\x11\x00/\x00>\x00L\x00X\x00d\x00s\x00\x00\x00.\x01\a\x0e\x01\a\x06\x16\x17\x16327>\x0176\x01\x17\a\x17\x16\x14\x0f\x01\x16\x15\x14\x02\x06\x04 $&\x02\x10\x126$32\x17762\x1f\x01\x13\x06#\"/\x01&4762\x1f\x01\x16\x14\x17\x06\"/\x01&4762\x1f\x01\x16\x146\x14\x06+\x01\"&46;\x012'\x15\x14\x06\"&=\x01462\x16\x17\a\x06#\"'&4?\x0162\x17\x16\x14\x02E\x140\x19l\xa6,\n\x14\x19\r\v*\x12\"\x81T\x19\x03\xb8.\xf4D\x13\x13@Yo\xbd\xfe\xfb\xfe\xe2\xfe\xfb\xbdoo\xbd\x01\x05\x8f\xb6\xa1@\x135\x13D\xfb\n\f\r\n[\t\t\n\x1a\nZ\n\xdc\v\x18\vZ\n\n\t\x1b\t[\t \x12\x0e`\x0e\x12\x12\x0e`\x0e\xae\x12\x1c\x12\x12\x1c\x12\x97[\n\f\r\n\n\nZ\n\x1a\n\t\x03\x9a2\x14\n,\xa6l\x190\n\x05(T\x81\"\v\x01\xad.\xf3D\x135\x13@\xa1\xb6\x8f\xfe\xfb\xbdoo\xbd\x01\x05\x01\x1e\x01\x05\xbdoY@\x13\x13D\x01,\n\nZ\n\x1a\n\t\t[\t\x1b\xef\t\t[\t\x1b\t\n\nZ\n\x1a\xbb\x1c\x12\x12\x1c\x12\xa0`\x0e\x12\x12\x0e`\x0e\x12\x12EZ\n\n\t\x1b\t[\t\t\n\x1a\x00\x03\x00\x00\xff\x00\a\x00\x06\x00\x00\x04\x00\x14\x005\x00\x00\x01%\x05\x03!\x02 \x04\x16\x12\x10\x02\x06\x04 $&\x02\x10\x126\x016=\x01\a'\x13\x17&'\x17\x05%7\x06\a7\x13\a'\x15\x14\x177\x05\x13\a\x1627'\x13%\x02a\x01\x1f\x01\x1fm\xfe\x9d\x05\x01l\x01L\xf0\x8e\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x04m\x95f\xf0?\x86\x96\xef5\xfe\xe1\xfe\xe15\uf587>\xf0f\x95\x1e\x01F\x8btu\xf6ut\x8b\x01F\x02\xd0\xd0\xd0\xfe\xb0\x04\x80\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\xfbH\xcb\xfb\x03Y\xe0\x01C\f\xceL|\x9f\x9f|L\xce\f\xfe\xbd\xe0Y\x03\xfb˄(\xfe\xd6E''E\x01*(\x00\x00\x00\f\x00\x00\x00\x00\a\x00\x05\x80\x00\x0f\x00\x1f\x00/\x00?\x00I\x00Y\x00i\x00y\x00\x89\x00\xa2\x00\xb2\x00\xbc\x00\x00%\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x03\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x03\x15\x14\x06+\x01\"&=\x0146;\x012\x16%\"&=\x01!\x15\x14\x06#\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x03\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x03\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x15!54\x05\x04\x1d\x01!54>\x04$ \x04\x1e\x04\x11\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x11\x15\x14\x06#!\"&=\x01\x01\xc0\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\xc0\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x02@\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\xc0\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\xfd\xc2\x1c&\x02\x02&\x1b\x02\xff\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\xc0\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x02@\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\xc0\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x01\x80\xfd\xfe\xfe\x82\xfe\x82\xfd\xfe\x113P\x8d\xb3\x01\r\x01>\x01\f\xb4\x8dP3\x11\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12&\x1b\xfe\x80\x1b&\xe0\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x01r\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\xfer\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x01r\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x92&\x1b\x81\x81\x1b&\xfd\xe0\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x01r\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\xfer\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x01r\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x01\x8a\r\nh\x02\x01e\n\r\x114LKM:%%:MKL4\xfeW\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x01T\x81\x1b&&\x1b\x81\x00\x00\x00\x00\x05\x00\x00\xff\x00\a\x00\x06\x00\x00\x10\x00\x14\x00%\x00/\x009\x00\x00\x01\x11\x14\x06#\x11\x14\x06#!\"&5\x11\x1363!\x11!\x11\x01\x11\x14\x06#!\"&5\x11\"&5\x11!2\x17\x01\x15!5463!2\x16\x05\x15!5463!2\x16\x02\xc0&\x1a&\x1a\xfe\x00\x1a&\xf9\a\x18\x02\xe8\xff\x00\x04\x00&\x1a\xfe\x00\x1a&\x1a&\x01\xa8\x18\a\xfc\xd9\xfe\xa0\x12\x0e\x01 \x0e\x12\x02\xa0\xfe\xa0\x12\x0e\x01 \x0e\x12\x04\xc0\xfd\x00\x1a&\xfd\xc0\x1a&&\x1a\x02\x00\x03i\x17\xfd@\x02\xc0\xfc\x80\xfe\x00\x1a&&\x1a\x02@&\x1a\x03\x00\x17\x017\xe0\xe0\x0e\x12\x12\x0e\xe0\xe0\x0e\x12\x12\x00\x01\x00\x00\xff\x00\a\x00\x06\x00\x00\x1d\x00\x00\x01\x16\x14\a\x01\x17\a\x06\x04'\x01#5\x01&\x12?\x01\x17\x0162\x16\x14\a\x01\x17\x0162\x06\xdb%%\xfeo\x96\xa0\xa3\xfe;\xb9\xfe\x96\xb5\x01j|/\xa3\xa0\x96\x01\x90&jJ%\xfep\xea\x01\x91&j\x04;&i&\xfep\x96\xa0\xa3/|\xfe\x96\xb5\x01j\xb9\x01ţ\xa0\x96\x01\x91%Jk%\xfeo\xea\x01\x90%\x00\x00\x00\x04\x00\x19\xff\f\x06\xe7\x06\x00\x00\t\x00\x15\x00:\x00g\x00\x00\x01\x14\x06\"&5462\x16\x05\x14\x06#\"&54632\x16\x13\x114&#!\"\x06\x15\x11\x1e\x052636\x17\x16\x17\x16\x176\x172\x1e\x02>\x057\x06\a\x12\a\x06\a\x06'&7\x035.\x01'\x03\x16\a\x06'&'&\x13&'&6\x17\x1e\x01\x17\x11463!2\x16\x15\x1176\x16\x03i\u007f\xb2\u007f\u007f\xb2\u007f\x01\xf6~ZY\u007f\u007fYZ~\xe1@O\xfb\xa8S;+[G[3Y\x1cU\x02D\x1b\x06\x04\x1a#\ao\x05?\x17D&G3I=J\xc6y\xfbTkBuhNV\x04\x01\b!\a\x01\x04WOhuAiS\xfby\x19*'\x04\x0f\x03^C\x04\xe9C^\x15'*\x03\x1cSwwSTvvTSwwSTvv\xfe\xf8\x02\x9bWID\\\xfd_\x17\"\x16\x0f\a\x01\x04\x01\x1c\x06\x03\x19\x1a[\x04\x03\x01\x01\x03\x06\v\x10\x17\x1f\x18\x95g\xfe\xe3\xb4q# /3q\x01F\x01\x02\b\x01\xfe\xaer2/ $r\xb4\x01\x1bg\x95%4\x1b\x02\n\x03\x02\xb6HffH\xfdJ\x0f\x1b4\x00\x00\x04\x00d\xff\x80\x06\x9c\x06\x00\x00\x03\x00\a\x00\x0f\x00\x19\x00\x00\x01\x11#\x11!\x11#\x11\x137\x11!\x11!\x157\x01\x11\x01!\a#5!\x11\x13\x03\x80\x91\x02\x1f\x91\x91\xfd\xfbV\x01F\xd9\x03\x1c\xfeN\xfe\xba\xd9\xd9\xferm\x04N\xfeN\x01\xb2\xfeN\x01\xb2\xfd\b\xfe\x03\x1b\xfb\xe7\xd9\xd9\x04\xaa\xfc\v\xfeN\xd9\xd9\x04\x86\x01!\x00\x00\x00\x00\x05\x00Y\xff\x01\x05\xaa\x05\xfd\x00\x16\x00+\x00?\x00N\x00e\x00\x00%\x15\x02\a\x06\a\x06&'&'&7>\x01727>\x01\x17\x1e\x01'\x06\x0f\x01\x04#&'&'&>\x01\x172\x17\x16\x1f\x01\x1e\x01\x01\x0e\x01\a\x06'&\x03'&676\x17\x16\x17\x1e\x01\x17\x16\x01\x16\a\x06'\x01&76$\x17\x16\x17\x16\x12\x05\x16\a\x06\x05\x06\a7\x06&'&767>\x0176\x17\x1e\x01\x17\x03\x05\x01\x05\f'6\xff#\r\x04\x01\x05\x04<\x97\x01;\x0f1\x19\x18\x1b\x96\x031x\xfe\xed\x11#\x13\f\x05\b\x12*#\r\xbdG,T\x17\x19\x039\a\xa93%\x1a\x0e\xaa/\x0e\x05\x11#0\x01v\xcbN\b\x1c\xfdZ\x05;:8\xfe\x86\b\x1b)\x01M:(\t\x03&\x02\x9b\x03\x1d\x0f\xfe\xc6C\x18\x01\x17.\x0e\x1e\x1e\x01J}2\t\x1c%0\x96\x06\xd9\u007f\xfe\xdc\r \b\t^*\x0f\x15\f\x0e\nJ\xb3F\x13\v\t\n&\xe47\x0f'X\x02\"\x192L\xb5D\x02M\x1d\x12\"\t+\xfe\xbc6\xd6\x14\x0e\x15\n\x01\x15M\x152\x15+\x11\x01'B\x1b\a\x16\x02Qf\x14\x11X\x02V#\x1b+]\x0f\n#\x12\xfd\xc1\xc8'\x14\nL\x0f\b\x02\x06\x14\x16/(\x01e\xabB\x06\x13\x11\x17\xdd9\x00\x00\x00\n\x00\x00\x00\x00\b\x00\x05\x80\x00\x03\x00\a\x00\v\x00\x0f\x00\x13\x00\x17\x00\x1b\x00#\x00,\x008\x00\x00\x01!\x11!\x13\x15!5\x01\x11!\x11\x01\x15!5\x01\x15!5\x01\x15!5\x01\x15!5\x01\x11#\x11\x14\x1626%\x11!\x11\x14\a!26\x13\x11\x14\x06#!\"&5\x11!5\x04\x00\xfe\x80\x01\x80\x80\xfd\x80\x02\x80\xfd\x80\x05\x00\xfe\x00\x02\x00\xfe\x00\x02\x00\xfe\x00\x02\x00\xfe\x00\xfc\x00\x80&4&\x06\x80\xfa\x00\v\x05\xcb\x1a&\x80pP\xf9\x80Pp\x01\x00\x04\x00\xfe\x80\xff\x00\x80\x80\x03\x00\xfd\x80\x02\x80\xfd\x00\x80\x80\x01\x00\x80\x80\x01\x00\x80\x80\x01\x00\x80\x80\xfc@\x03\xc0\xfc@\x1a&&\x1a\x04@\xfb\xc0!\x1f&\x04\xda\xfb@PppP\x04@\x80\x00\x04\x00*\x00\r\a\xd6\x05\x80\x00\t\x00\x1f\x009\x00Q\x00\x00$\"&5462\x16\x15\x147\".\x01\"\x0e\x01#\"&547>\x012\x16\x17\x16\x15\x14\x06\x01\"'.\x01#\"\x0e\x03#\"&5476$ \x04\x17\x16\x15\x14\x06\x13\"'&$ \x04\a\x06#\"&5476$ \x04\x17\x16\x15\x14\x06\x04\x14(\x92}R}h\x02L\u007f\x82\u007fK\x03\x12\x97\nN\xec\xe6\xecN\n\x97\x00\xff\v\f\x88\xe8\x98U\xab\u007fd:\x02\x11\x96\n\x84\x01x\x01\x80\x01x\x84\n\x96\xfe\v\v\xb3\xfe\u007f\xfe8\xfe\u007f\xb3\v\v\x11\x97\n\xbb\x02\x04\x02\x1a\x02\x04\xbb\n\x97\r\x93\x14 ,, \x14|2222\x96\x12\r\nMXXM\n\r\x12\x96\x01\x10\bic,>>,\x96\x12\f\n\x84\x92\x92\x84\n\f\x12\x96\x01\x0f\t\x9d\x9f\x9f\x9d\t\x96\x12\r\n\xba\xcc̺\n\r\x12\x96\x00\x00\r\x00\x00\xff\x00\x06\x80\x06\x00\x00\a\x00\x0f\x00\x17\x00\x1f\x00'\x00/\x007\x00?\x00K\x00S\x00c\x00k\x00{\x00\x00\x044&\"\x06\x14\x162$4&\"\x06\x14\x162\x004&\"\x06\x14\x162\x004&\"\x06\x14\x162\x004&\"\x06\x14\x162\x004&\"\x06\x14\x162\x004&\"\x06\x14\x162\x004&\"\x06\x14\x162\x01\x114&\"\x06\x15\x11\x14\x1626\x004&\"\x06\x14\x162\x01\x114&#!\"\x06\x15\x11\x14\x163!26\x104&\"\x06\x14\x162\x13\x11\x14\x06#!\"&5\x11463!2\x16\x01\x80KjKKj\x01\xcbKjKKj\xfe\xcbKjKKj\x03KKjKKj\xfe\xcbKjKKj\xfe\xcbKjKKj\x03KKjKKj\xfe\xcbKjKKj\x03KLhLLhL\xfe\x80KjKKj\x01\xcb&\x1a\xfb\x00\x1a&&\x1a\x05\x00\x1a&KjKKj\xcbL4\xfa\x804LL4\x05\x804L5jKKjKKjKKjK\x01\xcbjKKjK\xfe\xcbjKKjK\x01\xcbjKKjK\x01\xcbjKKjK\xfe\xcbjKKjK\x01\xcbjKKjK\xfd\x80\x01\x804LL4\xfe\x804LL\x02\xffjKKjK\x01\xc0\x01\x00\x1a&&\x1a\xff\x00\x1a&&\xfe\xa5jKKjK\x03\x00\xfa\x004LL4\x06\x004LL\x00\x02\x00\t\xff\x00\x05\xef\x06\x00\x00'\x00E\x00\x00\x01\x16\a\x02!#\"\x06\x0f\x01\x03\a\x0e\x01+\x01\"&7>\x0376;\x01\x167676767>\x01\x16\x17\x16'\x14\a\x06\a\x06\a\x14#'\"\a\x06\x03\x06#!\"&7\x13>\x013!2\x16\x17\x1e\x01\x05\xef\x12\x16W\xfe\",\x19&\x05\x047\x02\x05'\x19\xfb\x15\x18\x03\t#\x12$\t\x05&\x83\x85g\xafpf5\x18\v\x01\x03\x04\x04O\x99.P\xdeq\x8bZZd\x12\x02S\x01\v\xfe\xd9\x16\x1d\x03\xe8\x05-\x1d\x02V\"\u007f0kq\x03zTx\xfeD!\x1a\x13\xfe\xa6\x0f\x1a!\x1e\x158\xe0p\xdf8%\x02\x17'i_\x97F?\x06\x03\x01\x03;\xb3k\x81\xe9R(\x02\x01\x01`\b\xfd\xf6\n!\x16\x05\xbf\x1d&\x1a\x13)\xa4\x00\x00\x04\x00'\xff\x00\a\x00\x06\x00\x00\n\x00\x12\x00\x19\x00(\x00\x00\x012\x17\x00\x13!\x02\x03&63\x01\x06\a\x02\x0367\x12\x13\x12\x00\x13!\x02\t\x01\x10\x03\x02\x01\x02\x03&63!2\x16\x17\x12\x01\xb9!\x13\x01\n`\xfeB\u007f\xf0\f\x12\x14\x03\xa41LO\xb1(\x04\xd3\xe1\xeb\x01+#\xfe=)\xfe\x00\x04heC\xfe\xdc\x19Q\x04\x13\x10\x01g\x15#\x05s\x03`\x1a\xfe\x94\xfef\x01\xb9\x014\x10#\xfe\x9b\xc7\xc2\x016\x01\x1c\xdd\xe4\xfe\xac\x01\x8f\xfe\xbc\xfd\x13\xfeq\x02\x99\x03'\xfd\xc0\xfeX\xfe|\x020\x02\v\x01-\x01\x1b\x10\x19\x1a\x14\xfeg\x00\a\x00\x00\xff\x80\t\x00\x05\x80\x00\b\x00\x0f\x00\x18\x00\x1c\x00>\x00I\x00Y\x00\x00\x01#6?\x01>\x017\x17\x05\x03&#!\a\x04%\x03'.\x01'\x133\x01\x033\x13#\x05&#\"\x06\a\x06\x17\x1e\x01\x15\x14\x06#\"/\x01\a\x163\x16674'.\x0154636\x1f\x01%#\"\a\x03373\x16\x173\x13\x11\x14\x06#!\"&5\x11463!2\x16\a\xb7\x8a\x0e4\x03\x04\f\x03\f\xfa\x82:\v@\xfe\xf4\x02\x017\x01\x0f\xa2\x11\x1avH\x87\xaf\x01\x05%\xa6h\xa6\x02\x98EP{\x9c\x01\x01\x920&<'VF\x16\x17Jo\x82\x9d\x02\x8c1,1.F6\x0f\x01\xc0\x80A\x16\xf6\xae#\xd4\x05\x0f\x9a\x80L4\xf8\x004LL4\b\x004L\x02\"%\x8e\t\n \n7x\x01'6\rO\\\xfeJYFw\x1d\xfe\x02\x02\x81\xfd~\x02\x82\x10\x1bv^fH\x17$\x15\x1e !\v\x90\"\x01xdjD\x19\"\x15\x16!\x01\x19\b\x9b6\xfd\xb4`\x16J\x03\xc2\xfb\x004LL4\x05\x004LL\x00\x18\x00\x00\xff\x80\t\x00\x05\x80\x00\x11\x00\x19\x00+\x003\x00@\x00G\x00X\x00c\x00g\x00q\x00z\x00\x9c\x00\xb8\x00\xc7\x00\xe5\x00\xf9\x01\v\x01\x19\x01-\x01<\x01J\x01X\x01{\x01\x8b\x00\x00\x01&#\"\x0e\x02\x15\x14\x1e\x02327&\x02\x127\x06\x02\x12\x176\x12\x02'\x16\x12\x02\a\x1632>\x0254.\x02#\"\x0135#\x153\x15;\x025#\a'#\x1535\x1737\x03\x15+\x015;\x01\x153'23764/\x01\"+\x01\x15353$4632\x16\x15\x14\x06#\"$2\x17#\x04462\x16\x15\x14\x06#\"6462\x16\x15\x14\x06\"\x17\"'\"&5&547476125632\x17\x161\x17\x15\x16\x15\a\x1c\x01#\a\x06#\x06%354&'\"\a&#\"\a5#\x1535432\x1d\x0135432\x15\x173=\x01#\x15&#\"\x06\x14\x1632?\x014/\x01&5432\x177&#\"\x06\x15\x14\x1f\x01\x16\x15\x14#\"'\a\x16326\x17'\x06#\"=\x0135#5#\x15#\x153\x15\x14327\"\x06\x15\x14\x16327'\x06#\"'354&3\"\a5#\x1535432\x177&\x16\x14\x16327'\x06'\"&4632\x177&#\"\x173=\x01#\x15&#\"\x06\x14\x1632?\x01\"\a5#\x1535432\x177&\x173=\x01#\x15&\"\x06\x14\x1632?\x01\a\"#\x06\a\x06\x15\x06\x15\x14\x17\x14\x17\x1e\x013274?\x0167654'&'4/\x01\"&\x01\x11\x14\x06#!\"&5\x11463!2\x16\x04_\x80\x99g\xbd\x88QQ\x88\xbch\x99\x80\x83^_\xa3~\\[\u007f\u007f[\\]\x82_^\x83\x80\x99h\xbc\x88QQ\x88\xbdg\x99\x02e\a\x11\a\x03\x1d\x04\x05\x06\x06\x05\x03\x06\x04\x05\b\x02\x03\x03\x02\x03\x04\x01\x01\x01\x01\x01\x01\x02\x01\x06\x03\x01\xfb\x16\x16\x13\x12\x16\x16\x12\x13\x01\xa5<\x05F\x01\x87\x16$\x17\x16\x13\x12\xfa\x17$\x17\x17$\x87\x02\x02\x01\x04\x01\x01\x02\x01\x02\x02\x02\x03\x01\x04\x02\x01\x01\x01\x01\x02\x02\x01\xfa\xbc\x1e\x1d\x19 \x0f\x0e\x1f\x18\x0f\x1e\x1e!\x1e\x1d!\x1e\xa6\x1d\x1d\x11\x1a\x1d&&\x1d\x1c\x0f\xb2/\x0e\x17\x19\x17\x14\f\x16!\x1a\x1e/\r\x18\x1f\x19\x14\r\x19!\x1d!\x82\b\r\r\x1300\x1e\x1c\x1c/\x15e\x1d&'\x1e!\x16\x0e\x12\x15\"\ae$\x83\x17\f\x1e\x1e\x1d\n\b\t\t\x12'!\x1d\x13\x0e\x12\x11\x12\x17\x17\x12\x13\x10\x0e\x14\x1c!\xce\x1e\x1e\x0f\x1b\x1d''\x1d\x1c\x0e\x85\x17\f\x1d\x1d\x1d\n\b\t\b\u007f\x1d\x1d\x0f8''\x1c\x1d\x0eN\x02\x02\x01\x02\x02\x03\x01\x01\x03\x02\x04\x03\x04\x02\x02\x02\x01\x02\x01\x01\x01\x02\x02\x02\x01\x04\x01gL4\xf8\x004LL4\b\x004L\x04\xabUQ\x88\xbcgh\xbc\x88QUk\x01=\x01(\x14\x18\"\x06\x02\x04\n\x0f\v\x18\x0e\x18\x14!\x06\x02\x04\n\x11\x0e\x17\x11\x18\x0e\x19\a\x16=\x1b))\x1b=2\x8e(\x1f '\x13\x16\x0f!\f '\x14\x10\x87L#\x04\x1c\x04(>(\x10\x18\r\x01\x18&\x18\f\x18\x10\x8bDC\x10\x14(>(\x14z\x14\x10\x87L#\x04\x1c\x04\x8bDzG\x14)<)\x14\x03\x01\x01\x02\x01\x03\x02\x04\x03\x02\x02\x02\x02\x02\x01\x01\x01\x01\x01\x03\x02\x03\x04\x02\x01\x03\x01\x01\x01\x01\x04\xe5\xfb\x004LL4\x05\x004LL\x00\x00\f\x00\x00\xff\x80\t\x00\x05\x80\x00\n\x00\x11\x00\x1b\x00\x1f\x00B\x00W\x00b\x00j\x00q\x00}\x00\x8a\x00\x9a\x00\x00\x01\x14\a\x06+\x01532\x17\x16%\x14+\x01532\x054&+\x01\x113276\x173\x11#\x054&'.\x0154632\x177&#\"\x06\x15\x14\x16\x17\x16\x17\x16\x15\x14\x06#\"'\a\x16326\x055\x06#\"&54632\x175&#\"\x06\x14\x1632\x01\x11\x0e\x01\f\x02\x05!26\x004&\"\x06\x14\x162%\x13#\a'#\x13735#535#535#\x013'654&+\x01\x11353\x01\x11\x14\x06#!\"&5\x11463!2\x16\x019$\x1d<\x11\x11=\x1c$\x06\xf0@\x13\x14?\xf9SdO__J-<\x1eAA\x01@)7\x1d\x15\x1b\x15\x1d\x18\")9,<$.%\b\x13\x1c\x160\x17*,G3@\x01\x16%)1??.+&((JgfJ*\x04\xf7A\x9f\xfe\xc4\xfe\xa9\xfe\x14\xfe\xfe\x06!\x1a&\xfc\xadj\x96jj\x96\x01\x02\x90GZYG\x8eиwssw\xb8\x01\x87PiL>8aA\t\x01!M7\xf8\b7MM7\a\xf87M\x02\xf73!\x1a\xdc\x1b\x1f\r4erJ]\xfe\xb3&3Y\x01M\xe8(,\x14\n\x12\x0e\x10\x15\x1b,%7(#)\x10\r\x06\f\x16\x14\x1b,(@=)M%A20C&M\x14e\x92e\xfd\xb7\x02\x0f(X\x92\x81\x8c0&\x02Ėjj\x96j\b\x01V\xe0\xe0\xfe\xaa\t8Z8J9\xfe\xb3\x8c\x10N/4\xfe\xb3\x85\x02$\xfb\f8NN8\x04\xf48NN\x00\x00\x00\x00\x12\x00\x00\xff\x80\t\x00\x05\x80\x00\x02\x00\v\x00\x0e\x00\x15\x00\x1c\x00#\x00&\x00:\x00O\x00[\x00\xce\x00\xe2\x00\xf9\x01\x05\x01\t\x01$\x01?\x01b\x00\x00\x133'\x017'#\x153\x15#\x15%\x175\x174+\x01\x1532%4+\x01\x1532\x014+\x01\x1532\x053'%\x11#5\a#'\x15#'#\a#\x133\x13\x113\x177\x01\x14\x0e\x04\"&#\x15#'\a!\x11!\x17732%\x15#\x113\x15#\x153\x15#\x15\x01\x15\x14\x06#!\"&5\x11373\x1735\x1737\x15!572\x1d\x01!5\x1e\x026373\x1735\x173\x11#\x15'#\x15'#\"\a5#\x15&#!\a'#\x15'#\a\x11463!2\x16\x15\x11#\"\a5#\"\a5!\x15&+\x01\x15&+\x01\a'!\x11!7\x1735327\x153532\x16\x1d\x01!27\x1532%\x14\x06\a\x1e\x01\x1d\x01#54&+\x01\x15#\x1132\x16\x01\x14\x06\a\x1e\x01\x1d\x01#46.\x03+\x01\x15#\x11\x172\x16\x01\x15#\x113\x15#\x153\x15#\x15\x01\x11#\x11\x01\x14+\x0153254&\".\x01546;\x01\x15#\"\x15\x14\x166\x1e\x017\x15\x06+\x0153254&\x06.\x02546;\x01\x15#\"\x15\x14\x1e\x01\x03\x11#'\x15#'#\a#\"54;\x01\x15\"&\x0e\x04\x15\x14\x16;\x0173\x13\x113\x175wY-\x02AJF\xa3\x8e\x8e\x01=c\xbd(TS)\x01!*RQ+\xfe\xea*RQ+\x01\xcbY,\xfc\x16B^9^\x84\x19\x87\x19Ft`njUM\x02\x98\v\x11\x1c\x18'\x18)\t~PS\xff\x00\x01\x04PR\xcfm\xfe\xdd\xd9٘\x94\x94\x05\xd4M7\xf8\b7Mo\x197\x19\xda\x13q\x14\x02\x1d\n\n\x01\x17\x17@)U\t\x198\x19\xe3\"\xb6\xb4\x19\xb9\x17\xf9E(\xac\x181\xfd\x8c++\xc6\x16\xa9NM7\a\xf87Mx3\x1e\xb17\x17\xfe\xc4\x1f8\xd1\x17D\xea62\xfe\xa3\x01W74\xd3\x15;\x1f\xae\b\b\x04\x02\x119\x1f\xa8<\xfd-\x18\x16\x19\x12A\x18\"EA\x9a0:\xfe\xeb\x19\x15\x1a\x11A\x01\x01\x05\f\x17\x12F@\x991:\x02\x11\xd8ؗ\x94\x94\xfe\xedB\x02\xf7f~~\"\"12\"4(\x82w$#11#\xef\x18@}}!\x19%+%\x195(\x81v$:O\x94\\z\x84\x1a\x86\x19K\x81\x85?\a*\x0f\x1f\f\x11\x06\x1b$\x1d\\amcr\x03Vl\xfd\x86OO176Nn\xd9\x022\x16326\x05\x136&+\x01\"\a&#\"\x06\x15\x14\x163267\x06\x15\x14;\x012\x004&+\x01\"\x0f\x01'&+\x01\"\x06\x15\x14\x1e\x01\x17\x06\x15\x14;\x0127\x01%4&+\x01\"\a\x03\x06\x16;\x012?\x01>\x022\x16326\x05\x136&+\x01\"\a&#\"\x06\x15\x14\x163267\x14\x06\x15\x14;\x012\x1354+\x01\"\a\x03\a\x14\x16;\x0127\x01\x0e\x01#\a76;\x012\x16\x01\x11\x14\x06#!\"&5\x11463!2\x16\x02\xe93%\x1d#2%\x1c%\x03\x11,, \x11\x02\v\x12\x16\x1a\x18\x01_3$\x1d$2%\x1c%\xfa\xa8M>\xa0\x13\x02A\x01\b\x06L\x14\x02\x12\x01\f\x12\x10\x16\x03Vb\x015)\x01\b\x06L\x0e\x03\x1bDHeE:\x1c<\x12\x04\rE\x13\x01\xc2\b\x05M\v\aj,\x05\x11K\x05\b'-\x01R\rM\v\a\x00\xff\x01~M>\x9f\x14\x02A\x01\b\x06R\f\x04\x12\x01\f\x12\x10\x16\x03Vb\x015)\x01\b\x06L\x0e\x03\x1aEHeE:\x1d<\x11\x04\rE\x13\xdd\rJ\v\x02A\x01\b\x06B\x13\x02\xf9I\x05*'!\x11\x02\v\x13($\arL4\xf8\x004LL4\b\x004L\x02v%1 \x1c%3!x*\x1e\x01k\v\x04\x15\xa9$2 \x1c%3!\x8e;5\x13\xfeh\x06\n\x13n\b\n\x03\x02a\xe2\x01\x05\x06\n!(lI;F\x18\x14\f\t\x10\x01\x15\n\t\n\x9c\x96\x10\t\x05\x02r\x84\x04p\b\r\n\x01p8;5\x13\xfeh\x06\n\rt\b\n\x03\x02a\xe2\x01\x05\x06\n!(lI;F\x18\x14\x01\x10\x04\x10\x01\xac\x01\x0e\v\xfe`\x02\x05\t\x13\x01\x13#\x16\x01k\v\x17\x01\xdf\xfb\x004LL4\x05\x004LL\x00\x00\x00\n\x00\x00\xff\x80\t\x00\x05\x80\x00\n\x00\x0f\x002\x00H\x00W\x00[\x00l\x00t\x00\x8b\x00\x9b\x00\x00\x01\x14\a\x06#\"'5632\x05#632\x054&'.\x015432\x177&#\"\a\x06\x15\x14\x16\x17\x1e\x01\x15\x14#\"&'\a\x163276\x017#5\x0f\x033\x15\x14\x17\x163275\x06#\"=\x01\x055&#\"\x06\a'#\x113\x11632\x133\x11#\x054'&#\"\a'#\x1175\x163276\x004&\"\x06\x14\x162\x014'&#\"\x06\x15\x14\x17\x16327'\x06#\"'&'36\x13\x11\x14\x06#!\"&5\x11463!2\x16\x06=\x15\x13!\x17\x12\x1d\x1c9\x01\xb6n\x0623\xf9\xecBD$ &:B\x12CRM.0AC'\x1f0\x1dR\x1f\x12H`Q03\x01'\x13`\x81\x12.\x11>,&I / \f*\x01\x89\x0f\r /\n\n\x83\x96\x1a8\x10/\x96\x96\x02n-(G@5\b\x84\x96$ S3=\xfe,.B..B\x03\xb002^`o?7je;\x109G+\x14\x17\x05\xf8\x02\x80L4\xf8\x004LL4\b\x004L\x02yE%#\t\xe0\x1eVb\xe9;A\x19\r\x16\x0e\x1a!p &'F:A\x18\x0e\x17\x10\x1f\x19\x12q)%)\x01#o\x87\x15r\bg\xdbT$\x1e\vv\a2\xc5\x19\x8b\x03 \x1e8\xfe)\x012\x1f\xfe\xaf\x01\xd7\xdez948/\xfd{\x19\x97\v8A\x01\xc4B..B/\xfe\xebq?@\x84r\x80<7(g\x1f\x13\x13/\x0e\x02\xb1\xfb\x004LL4\x05\x004LL\x00\x00\x03\x00\x0e\xff\x00\a\xf2\x06\x00\x00\v\x00\x17\x00?\x00\x00\x01\x12\x17\x14\x06#!\x14\x06\"&'\x0524#\"&54\"\x15\x14\x16\x01\x16\x06\a\x01\x06&/\x01&6?\x01&5>\x0454\x127&5462\x16\x15\x14\a\x1e\x01\x17\x016\x16\x17\x06\x16=\xedL4\xfe@\x96ԕ\x01\x01\x00\x10\x10;U g\x043\b\x01\n\xf8\xb0\n\x1b\bT\b\x01\n\xba\x132RX='\xea\xbe\b8P8\b|\xbe5\x01\xa2\n\x1b\b\x02\xac\xfe\x9c\xc84Lj\x96\x95j\xaf U;\x10\x10Ig\x06@\n\x1b\t\xf9\xaa\b\x02\n`\n\x1b\b\xa1 \"*\\\x93\xaa\xf2\x8b\x98\x01\x05\x1c\x13\x14(88(\x14\x13\x12\x81]\x01k\b\x02\n\x00\x00\x00\x00\x04\x00\x0e\xff\x00\a\xf2\x06\x00\x00\v\x00\x16\x00&\x00N\x00\x00\x044#\"&54\"\x15\x14\x163\t\x01.\x01#\"\x0e\x02\x15\x10\x01\x14\x06#!\x14\x06\"&'7!&\x037\x12\x01\x17\x16\x06\a\x01\x06&/\x01&6?\x01&5>\x0454\x127&5462\x16\x15\x14\a\x1e\x01\x17\x016\x16\x04\x10\x10;U gI\xfd\xf7\x03m*\xb5\x85]\x99Z0\x04\xc0L4\xfe@\x96ԕ\x01\x95\x02\xf5\xa6=o=\x01CT\b\x01\n\xf8\xb0\n\x1b\bT\b\x01\n\xba\x132RX='\xea\xbe\b8P8\b|\xbe5\x01\xa2\n\x1b\xb0 U;\x10\x10Ig\x01\xeb\x02\xf8Xu?bl3\xfe\x80\xfe@4Lj\x96\x95j\x81\xbb\x01\x10a\xfe\x9c\x04\xa8`\n\x1b\t\xf9\xaa\b\x02\n`\n\x1b\b\xa1 \"*\\\x93\xaa\xf2\x8b\x98\x01\x05\x1c\x13\x14(88(\x14\x13\x12\x81]\x01k\b\x02\x00\x00\x00\x00\x05\x00\x00\xff\x80\x05\x80\x05\x80\x00\x0f\x00\x1f\x00/\x007\x00[\x00\x00%\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126%\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126%\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126\x01!'&'!\x06\a\x05\x15\x14\x06+\x01\x11\x14\x06#!\"&5\x11#\"&=\x01463!7>\x013!2\x16\x1f\x01!2\x16\x02\x00\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x01\x00\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x01\x00\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\xfd\xe0\x01\xc00\a\n\xfe\xc3\n\a\x03o\x12\x0e`^B\xfc\xc0B^`\x0e\x12\x12\x0e\x015F\x0fN(\x01@(N\x0fF\x015\x0e\x12\xa0\x02\xc0\x0e\x12\x12\x0e\xfd@\x0e\x12\x12\x0e\x02\xc0\x0e\x12\x12\x0e\xfd@\x0e\x12\x12\x0e\x02\xc0\x0e\x12\x12\x0e\xfd@\x0e\x12\x12\x03\xeeu\t\x02\x02\t\x95@\x0e\x12\xfcLSyuS\x03\xb8\x12\x0e@\x0e\x12\xa7%44%\xa7\x12\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00,\x00<\x00H\x00\x00\x01\x15\x14\x0e\x02#\"\x0054\x0032\x1e\x03\x1d\x01\x14+\x01\"=\x014&#\"\x06\x15\x14\x16326=\x0146;\x012\x16\x02 \x0e\x02\x10\x1e\x02 >\x02\x10.\x01\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04~Isy9\xcd\xfe\xed\x01\x10\xcb\"SgR8\x10v\x10\x83H\x8c\xb1\xb7\x8eD\x8c\t\x06w\x06\n\xfc\xfe\xfc\xed\xabff\xab\xed\x01\x04\xed\xabff\xab\x01\x91\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01\xcem2N+\x16\x01\x16\xcf\xcb\x01\x10\t\x1b)H-m\x10\x10F+1\xb7\x92\x97\xc50*F\a\t\t\x03+f\xab\xed\xfe\xfc\xed\xabff\xab\xed\x01\x04\xed\xab\xfe\xb7\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0e\x00b\x00\x00\x014&#\"\x0e\x02\x15\x14\x1632>\x01\x05\x14\x0e\x02\a\"\x06#\"'&'\x0e\x01#\"&54\x12632\x16\x17?\x01>\x01;\x012\x17\x16\a\x03\x06\x15\x14\x163>\x045\x10\x00!\"\x0e\x02\x10\x1e\x023276\x16\x1f\x01\x16\a\x06\a\x0e\x01#\"$&\x02\x10\x126$3 \x00\x03\xcck^?zb=ka`\xa0U\x024J{\x8cK\x06\x13\a_/\x1c\x054\x9f^\xa1\xb1\x84\xe2\x85W\x88&\x02\v\x01\t\x05v\x05\b\x05\x02x\x05\x19 \x1c:XB0\xfe\xa4\xfe܂\xed\xabff\xab\xed\x82\xe4\xb1\v\x1a\b)\b\x01\x02\nf\xfb\x85\x9c\xfe\xe4\xcezz\xce\x01\x1c\x9c\x01X\x01\xa8\x02\xf9lz=l\xa6apz\x85\xc7\x11o\xacb3\x02\x015!2BX\xbf\xae\x9d\x01\n\x9bG@\x138\x06\f\v\x05\v\xfd\x9a\x18\x18'\x1a\x01\t'=vN\x01$\x01\\f\xab\xed\xfe\xfc\xed\xabf\x90\t\x02\v1\f\f\r\tSZz\xce\x01\x1c\x018\x01\x1c\xcez\xfeX\x00\x00\x00\x00\x02\x00\x00\xff\x00\a\x00\x06\x00\x00#\x00(\x00\x00\x00\x16\x10\x0f\x01\x17\x16\x14\x0f\x01\x06\"/\x01\x01\x06+\x01\x05'\x13547\x01'&4?\x0162\x1f\x0176\t\x01'\x01\x15\x06D\xbc^\xe1h\n\n\xd2\n\x1a\ni\xfd\xa5%5\xcb\xff\x00@\x80%\x02[i\n\n\xd2\n\x1a\nh\xdf]\xfc\xc5\x02@\xc0\xfd\xc0\x06\x00\xbc\xfe\xf7]\xdfh\n\x1a\n\xd2\n\ni\xfd\xa5%\x80@\x01\x00\xcb5%\x02[i\n\x1a\n\xd2\n\nh\xe1^\xfa@\x02@\xc0\xfd\xc0\xc0\x00\x02\x00\x00\xff\x00\x06\xfe\x06\x00\x00\x10\x00)\x00\x00\x012\x16\x15\x14\a\x00\a\x06#\"&547\x016\x01\x1e\x01\x1f\x01\x16\x00#\".\x025\x1e\x03327>\x04\x06OFi-\xfe\xb4\x85ay~\xb5\\\x02~;\xfc\xba'\x87S\x01\x04\xfe\xf5\xd7{\xbes:\aD8>\x0f)\x0e\x19AJfh\x06\x00]F?X\xfd\x8b{[\xb9\u007f\x80T\x02C6\xfb\xf6Ll\x16G\xd5\xfe\xf4]\xa2\xccv\x052'\"%B];$\x0f\x00\x00\x00\x05\x00\x00\xff\x00\a\x00\x06\x00\x00-\x00o\x00\u007f\x00\x8f\x00\x9f\x00\x00%\x11!\x112>\x017>\x0132\x1e\x01\x17\x1e\x0232>\x017>\x0232\x16\x17\x1e\x022>\x017>\x0132\x16\x17\x1e\x02\x13\x15\".\x01'.\x02#\"\x0e\x01\a\x0e\x02#\"&'.\x02#\"\x0e\x01\a\x0e\x02#\"&'.\x02#\"\x0e\x01\a\x0e\x01#546;\x01\x11!\x11!\x11!\x11!\x11!\x1132\x16\x01\x14\x06#\"&54>\x0452\x16\x05\x14\x06#\"&54>\x0452\x16\x05\x14\x06#\"&54>\x0452\x16\a\x00\xf9\x00-P&\x1c\x1e+#\x18(\x16\x16\x1d$P.-P$\x1e\x15\x17'\x18#+\x1e\x1c&PZP&\x1c\x1e+#\"+\x1e\x1c&P-\x18(\x16\x16\x1d$P-.P$\x1d\x16\x16(\x18#+\x1e\x1d$P.-P$\x1e\x15\x17'\x18#+\x1e\x1c&P-.P$\x1d\x1e+#pP@\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00@Pp\xfb\x00H85K\x13\x1c\"\x1c\x13&Z\x02\x00H85K\x13\x1c\"\x1c\x13&Z\x02\x00H85K\x13\x1c\"\x1c\x13&Z\x80\xfe\x80\x01\x80\x1c\x1b\x18\x1b\x16\x0e\x10\x13\x19\x1a\x1c\x1d\x19\x19\x13\x10\x0e\x16\x1b\x18\x1b\x1c\x1c\x1b\x18\x1b\x16\x16\x1b\x18\x1b\x1c\x01@\xc0\x0e\x10\x13\x19\x1a\x1c\x1c\x1a\x19\x13\x10\x0e\x16\x1b\x19\x1a\x1c\x1d\x19\x19\x13\x10\x0e\x16\x1b\x18\x1b\x1c\x1c\x1a\x19\x1b\x16\xc0Pp\x01\xc0\xfe@\x01\xc0\xfe@\x01\xc0\xfe@p\x03\x10MSK5\x1d,\x18 \x1f:&\x94LMSK5\x1d,\x18 \x1f:&\x94LMSK5\x1d,\x18 \x1f:&\x94\x00\x02\x00\x00\xff\x80\b\x00\x05\x80\x00\x05\x00\v\x00\x00!\x15!\x113\x11\t\x01!\x11\t\x01\b\x00\xf8\x00\x80\x06\x00\x01\x00\xf9\x80\x01\xc0\x02@\x80\x06\x00\xfa\x80\x04\x00\xfc\x80\x02@\x02@\xfd\xc0\x00\x00\x00\x03\x00\x00\xff\x80\x06\xc0\x06\x00\x00\v\x00\x10\x00\x16\x00\x00\t\x01\x06\x04#\"$\x02\x10\x12$3\x13!\x14\x02\a\x13!\x112\x04\x12\x03\x00\x02\"j\xfe\xe5\x9d\xd1\xfe\x9f\xce\xce\x01aѻ\x03\x05xl\xa4\xfd\x00\xd1\x01a\xce\x02\x86\xfd\xdelx\xce\x01a\x01\xa2\x01a\xce\xfd\x00\x9d\xfe\xe5j\x02\xa2\x03\x00\xce\xfe\x9f\x00\x02\x00\x00\xff\x80\b\x00\x05\x80\x00\x05\x00\x1f\x00\x00!\x15!\x113\x11\x01\x11\x14\x06/\x01\x01\x06\"/\x01\x01'\x0162\x1f\x01\x01'&63!2\x16\b\x00\xf8\x00\x80\a\x00'\x10y\xfd\x87\n\x1a\n\xe9\xfe`\xc0\x02I\n\x1a\n\xe9\x01\xd0y\x10\x11\x15\x01\xb3\x0e\x12\x80\x06\x00\xfa\x80\x04\xe0\xfeM\x15\x11\x10y\xfd\x87\n\n\xe9\xfe`\xc0\x02I\n\n\xe9\x01\xd0y\x10'\x12\x00\x00\x01\x00\x00\x00\x00\a\x00\x04W\x00`\x00\x00\x01\x14\x17\x1e\x03\x17\x04\x15\x14\x06#\".\x06'.\x03#\"\x0e\x01\x15\x14\x1632767\x17\x06\a\x17\x06!\"&\x0254>\x0232\x1e\x06\x17\x1632654.\x06'&546\x17\x1e\x01\x17#\x1e\x02\x17\a&'5&#\"\x06\x05\f\n\n\x1e4$%\x01Eӕ;iNL29\x1e1\v ;XxR`\xaef՝\xb1Q8\x1bT\x0f\x1d\x01\x83\xfe\xff\x93\xf5\x88W\x91\xc7iW\x90gW:;*:\x1a`\x89Qs&?RWXJ8\v\x03\xafoNU0\x01\f\x16\x1e\x04\x81\x1a\x1c\x17J1F\x03@\x06#\x1d)\x1b\r\n[\xf1\x92\xc1%6_P\u007fO\x86\x1cQiX(o\xb2`\xa0\xef_?5\x98\"$\x01\x98\x9e\x01\x01\x92iʗ\\&>bd\x86s\x926\xc8aP*< \x1f\x17-;iF\x10\x11n\xa4\x04\x03\x17*\v\x1b-\x05c1\x15\x01\x15B\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00W\x00g\x00\x00\x014'.\x02'4.\x0154632\x17#\x16\x177&'.\x01#\"\x06\x15\x14\x17\x1e\x01\x17\x1e\x03\x1d\x01\x16\x06#\"'.\x05#\"\x0e\x01\x17\x15\x1e\x0232767'\x0e\x01#\"&54632\x16\x17\x1e\a326\x13\x11\x14\x06#!\"&5\x11463!2\x16\x05\x98\xea#$(\t\x04\x021$6\x11\x01\x14\x13]'\n!E3P|\x02\x10ad\x1d(2\x1b\x01S;aF\x179'EO\x80Se\xb6j\x03\x04]\xaem\xba]\x14\v<*rYs\x98\xa4hpt.\b#\x16)$78L*k\x98h\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x01\xe4\xadB\n\r%\x1c\x02\r\v\x02$/\x0f\x0f$G6\n\x1d\x14sP\a\x10`X\x1d\b\x0f\x1c)\x1a\x05:F\x90/\x95fwH1p\xb8d\x01l\xb6qn\x1b\x18mPH\xaeui\xa8kw\x15_:[9D'\x1b\x8b\x02\xe5\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x03\x00\x00\x00\x00\b\x00\x05\x00\x00\x0f\x00\x1f\x003\x00\x00\x004.\x02\"\x0e\x02\x14\x1e\x022>\x01$4.\x02#!\x16\x12\x10\x02\a!2>\x01\x12\x10\x0e\x02#!\".\x02\x10>\x023!2\x1e\x01\x04\x80Q\x8a\xbdн\x8aQQ\x8a\xbdн\x8a\x03QQ\x8a\xbdh\xfe~w\x8b\x8bw\x01\x82h\xbd\x8a\xd1f\xab\xed\x82\xfd\x00\x82\xed\xabff\xab\xed\x82\x03\x00\x82\xed\xab\x02\x18н\x8aQQ\x8a\xbdн\x8aQQ\x8a\xbdн\x8aQZ\xfe\xf4\xfe\xcc\xfe\xf4ZQ\x8a\x01\xa7\xfe\xfc\xed\xabff\xab\xed\x01\x04\xed\xabff\xab\x00\x00\x00\x02\x00\x00\x00\x00\b\x00\x05\x00\x00\x13\x00#\x00\x00\x18\x01>\x023!2\x1e\x02\x10\x0e\x02#!\".\x01\x042>\x024.\x02\"\x0e\x02\x14\x1e\x01f\xab\xed\x82\x03\x00\x82\xed\xabff\xab\xed\x82\xfd\x00\x82\xed\xab\x04\xb2н\x8aQQ\x8a\xbdн\x8aQQ\x8a\x01\xfe\x01\x04\xed\xabff\xab\xed\xfe\xfc\xed\xabff\xab\x91Q\x8a\xbdн\x8aQQ\x8a\xbdн\x8a\x00\x00\x05\x00\x00\x00\x00\t\x00\x05\x00\x00\x0e\x00\x12\x00\x18\x00,\x00\\\x00\x00\x01!\"&?\x01&#\"\x06\x10\x16326'3&'\x05\x01!\a\x16\x17\x04\x10&#\"\a\x13\x16\x06\a\x06#\"'\x03\x06\x15\x14\x16 \x00\x10\x00 \x005467'\x01\x06+\x01\x0e\x01#\"\x00\x10\x0032\x177#\"&463!\x15!'#\"&463!2\x17\x01632\x02\xfa\xfe\xc6(#\x18\xbcAH\x84\xbc\xbc\x84s\xb0\xa3\xba\x129\x01q\x01 \xfe ci\x15\x05\x05\xbc\x84<=\xae\x0f\n\x16\x0f\x15#\x12\xae]\xbc\x01\b\x01<\xfe\xf9\xfe\x8e\xfe\xf9OFA\xfe\x9f\x12!\xc5\x17\xfc\xa8\xb9\xfe\xf9\x01\a\xb9re\x89\xe0\x1a&&\x1a\x01\x80\x01\xb3U\xde\x1a&&\x1a\x01\x00!\x14\x01\v[e\xb9\x01\x80F \xfb\x1f\xbc\xfe\xf8\xbc\x91\xefU?\x94\x01\x80\x84g\x95\xc4\x01\b\xbc\x18\xfe\xfc\x174\x0e\v\x1d\x01\x04_\x82\x84\xbc\x01\xf9\xfe\x8e\xfe\xf9\x01\a\xb9a\xad?b\xfe+\x1a\xa4\xdc\x01\a\x01r\x01\a7\xb7&4&\x80\x80&4&\x1c\xfep,\x00\x00\x05\x00\x00\xff\x00\x06\x00\x06\x00\x00\a\x00\x0f\x00\x1f\x00+\x00K\x00\x00\x004&\"\x06\x14\x162$4&\"\x06\x14\x162\x13\x03.\x01#!\"\x06\a\x03\x06\x163!26\x024&#!\"\x06\x14\x163!2\x01\x11#\x15\x14\x06\"&=\x01!\x15\x14\x06\"&=\x01#\x1147\x13>\x01$ \x04\x16\x17\x13\x16\x01\x80KjKKj\x04KKjKKj\x1dH\x05#\x17\xfcj\x17#\x05H\x05&\x1e\x04&\x1e&\xe7\x1c\x14\xfd\x80\x14\x1c\x1c\x14\x02\x80\x14\x01\xac\x80KjK\xfd\x00KjK\x80\x19g\t\xb1\x01\x1b\x01V\x01\x1b\xb1\ti\x17\x01\vjKKjKKjKKjK\x02\f\x01\x80\x17\x1d\x1d\x17\xfe\x80\x1e..\x02n(\x1c\x1c(\x1c\xfd[\xfd\xa5\x805KK5\x80\x805KK5\x80\x02[po\x01\xc6Nv<\x02\x01\x14\x06+\x01\x16\x15\x14\x02\x06\x04#\"\x00'#\"&546;\x01&54\x126$32\x00\x1732\x16\x05\xb72$\xfdB$22$\x02\xbe$\x01\b\x17\xfc*$22$\x03\x8cX\xfeڭ\xb1\xfeӯ\x17\x03\xd6$22$\xfctX\x01'\xad\x84\xf2\xaeh\x01s2$\x83\x11\x83\xdc\xfeϧ\xf6\xfekc\xbd$22$\x84\x11\x83\xdc\x011\xa8\xf5\x01\x95c\xbc$2\x02\xe3F33F3VVT2#$2\x8f\xa8\xaf\xfeԱVT2#$2\x8f\xa8g\xaf\xf1\x01\x84#2UU\xa7\xfe\xcf݃\x01\n\xd92$#2UU\xa7\x011݃\xfe\xf6\xd92\x00\x00\x06\x00\v\xff\x00\x04\xf5\x06\x00\x00\a\x00\x0f\x00\x1b\x00,\x00u\x00\xa3\x00\x00\x01\x03\x17\x1254#\"\x01\x16\x1767.\x02\x01\x14\x13632\x17\x03&#\"\x06\x03\x14\x1e\x0132654'.\x03#\"\x06\x03\x14\x17\x1e\x013276\x114.\x01'&$#\"\a\x06\x15\x14\x1e\x047232\x17\x16\x17\x06\a\x06\a\x0e\x01\x15\x14\x16\x15\a\x06\x15&'\x06#\x16\x15\x14\x06#\"&547\x16\x17\x1632654&#\"\x06\a467&54632\x17\x0254632\x13\x16\x17>\x0532\x16\x15\x14\x03\x1e\x03\x15\x14\x02\x0e\x01#\"'&\x02\x03\xb9ru\xa5&9\xfe\x8c\x1e\x03%\"\f*#\xfe͟\x11 \x0fO%GR\x9f=O&\x0e^\xaa\xfc\x98op\x95\xda\x04\x86\xfe\xb8\x15\x01\xc3C8\xfcpP\b*\x19\x02\a\a\x03\x85b\xfeY\n\x05\x01_\xdc#\xfc\xf5$\xa6\x8c\x1a\x0e\x18N Pb@6\xfe\x9d)?\x91\xa4\xaa\xa9\x01\x02+0L\x1215\v\x05\x1e\"4\x1c\x13\x04\x04\x02\x13\x13$\x1c\x1a\x16\x18.\x88E\x1fs\x1e\f\f\x02\n\xce\x02\a\x0e5I\x9cQ\"!@\fh\x11\f\"\xdeY7e|\x1aJ\x1e>z\x0f\x01\xceiPe\xfd\xbb\x11\x06\x10\u007fn\x91eHbIl\xfeF\x0f>^]@\x96\xfe\xfc\xben*9\x01\r\x00\x00\x00\x00\x04\x00\x00\xff\x80\b\x00\x05\x80\x00\x1a\x006\x00[\x00_\x00\x00\x013\x0e\x01#\"&54632\x16\x17#.\x01#\"\x06\x15\x14\x1e\x0232%3\x0e\x01#\"&54632\x16\x17#.\x01#\"\x06\x15\x14\x1e\x02326%4&'.\x02'&! \a\x0e\x02\a\x0e\x01\x15\x14\x16\x17\x1e\x02\x17\x16\x04! 7>\x027>\x01\x13\x11!\x11\x03\x11\xcf\x0e\xa9\x82\xa2\xb9\xba\x8c\x94\xa8\r\xcb\x05=39?\n\x1a6'_\x02\xd6\xce\x0e\xa8\x82\xa2\xb9\xba\x8c\x94\xa8\r\xcc\x04>29?\n\x1a5'17\x01m\x1f-\x06\x0f\x1c\x02V\xfd\x9d\xfd\x8fU\x05\x19\x11\x06-\x1e\x1e-\x06\x12\x17\x06,\x01\x87\x01\x13\x02bW\x05\x18\x11\x05.\x1e\xc0\xf8\x00\x02\x10\x9e\xb5\xe8\xc8\xc2뮠@Fyu0HC$\x8b\x9e\xb5\xe8\xc8\xc2뮠@Fyu0HC$L\xb6\xcf\xc8=\b\f\x12\x02??\x04\x0f\r\b<\xc7\xd1\xd0\xc7=\b\x0e\x0e\x05! A\x04\x0e\x0e\t<\xc6\x03\xcb\xfa\x00\x06\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x05`\x05\x80\x00\x1d\x00;\x00\x00\x01\x11\x14\x06+\x01\"&5\x114&#!\x11\x14\x06+\x01\"&5\x11463!2\x1e\x01\x01\x11\x14\x0e\x01#!\"&5\x1146;\x012\x16\x15\x11!265\x1146;\x012\x16\x03\xe0\x12\x0e\xa0\x0e\x12\xa0p\xfe\xf0\x12\x0e\xa0\x0e\x12\x12\x0e\x01Ї\xe4\x85\x01\x80\x85\xe4\x87\xfe0\x0e\x12\x12\x0e\xa0\x0e\x12\x01\x10p\xa0\x12\x0e\xa0\x0e\x12\x03\x90\xfe\x10\x0e\x12\x12\x0e\x01\xf0p\xa0\xfb\x80\x0e\x12\x12\x0e\x05@\x0e\x12\x85\xe4\x01I\xfc\x90\x87\xe4\x85\x12\x0e\x03\xc0\x0e\x12\x12\x0e\xfd\x00\xa0p\x03p\x0e\x12\x12\x00\x00\x00\x04\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00>\x00S\x00c\x00\x00\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x0554&+\x01\"\a&+\x01\"\x06\x1d\x01\x14;\x012=\x0146;\x012\x16\x1d\x01\x14;\x012=\x0146;\x012\x16\x1d\x01\x14;\x012%54&#!\"\x06\x15\x11\x14;\x012=\x01\x16;\x0126\x13\x11\x14\x06#!\"&5\x11463!2\x16\x05\x1f\x1b\x18\xca\x18\x1c\x1c\x18\xca\x18\x1b\xfe\x16A5\x85D\x1c\x1cD\x825A\x157\x16\x1b\x19^\x18\x1c\x156\x16\x1c\x18a\x18\x1b\x167\x15\x02MB5\xfe\xf85B\x167\x15\x1f?\xbf5B~\x88`\xfb\xd0`\x88\x88`\x040`\x88\x02\xb6r\x18\x1c\x1c\x18r\x18\x1c\x1c\xfe\xfa5A44A5\xfa\x16\x16\xe6\x18\x1c\x1c\x18\xe6\x16\x16\xe6\x18\x1c\x1c\x18\xe6\x16v\x9a5AA5\xfef\x15\x15\xb4*A\x02\x9d\xfb\xd0`\x88\x88`\x040`\x88\x88\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x02\x00\t\x00\x19\x00\x00\x01!\x1b\x01!\x01!\x01!\t\x01\x11\x14\x06#!\"&5\x11463!2\x16\x03\x93\xfeړ\xe9\x017\xfe\xbc\xfeH\xfe\xbc\x017\x01\u007f\x02j\xaav\xfc@v\xaa\xaav\x03\xc0v\xaa\x01\xc2\x02'\xfc\x97\x04\x00\xfc\x00\x01:\x02\xa6\xfc@v\xaa\xaav\x03\xc0v\xaa\xaa\x00\x00\x00\x00\x17\x00\x00\xff\x00\b\x00\x06\x00\x00M\x00U\x00a\x00h\x00m\x00r\x00x\x00\u007f\x00\x84\x00\x89\x00\x91\x00\x96\x00\x9c\x00\xa0\x00\xa4\x00\xa7\x00\xaa\x00\xaf\x00\xb8\x00\xbb\x00\xbe\x00\xc1\x00\xcb\x00\x00\x01\x14\x06\a\x03\x16\x15\x14\x06\a\x03\x16\x15\x14\x06#\"'!\x06\"'!\x06#\"&547\x03.\x01547\x03.\x015467\x134&547\x13&54632\x17!62\x17!632\x16\x15\x14\a\x13\x1e\x01\x15\x14\a\x13\x1e\x01\x01!\x01#\x01!62\x01\x16\x15\x14\a\x13\x177\x11'\x06\a\x01!\x17%!\x06\"\x0167'\a#7\x03\x01\x17\x017\x13!\x016\x053\x01!\x11\x17\x16\x03!7\x01\x0f\x0135\a\x16\x11\x14\x16\x15\x14\a\x17\x117\x11\x17\x01/\x01\a\x117'\x06%#\x05\x17\x15\t\x02%'\x11\x05\a3\x01\x17\x13/\x02&=\x01\x03&'\t\x025\x03\x13#\x13\x01\a?\x01\x13&547\v\x01\x176\b\x00\x1a\x14\xcd\x03\x19\x14\xc1\x03!\x18\x19\x10\xfep\x114\x11\xfeq\x11\x1a\x17\"\x04\xc1\x14\x19\x03\xce\x14\x19\x1b\x14\xc7\x01\"\xd1\x04\"\x17\x1a\x12\x01\x8c\x106\x10\x01\x8e\x12\x1a\x17\"\x04\xcf\x17 \a\xbb\x13\x19\xfc'\x01\x85\xfe\xaa\x8f\xfe\xaa\x01h\x12*\xfc[\x01\x02\xd0\x0f\xbc\xbb\r\x10\x02\xa8\xfe|\xbe\x02*\xfe\xe8\x10,\x02\xaf\x01\x04@\x11\x1e\x16\xfc\xfe\xd8?\x01w\x10A\xfeU\x01M\b\xfcp\x05\x01V\xfe\x8b\x04\x0e\x12\x01\x92@\xfe˝\xc1\xa3\xa8\x04\x01\b\xab\x1e\x99\x01)\xdf\xdf\x04Ϳ\x06\x03w\x10\xfd\x93\xd5\xfe\xd7\x017\x01(\xfd{\x88\x01\xe6*U\x01%\xee\x84\x03\x01\x16\b\xd8\x05\b\xfeK\x016\xfc\xc0\xa3\xa3\xa3\xa3\x04=0\x82(\xcf\x02\x03\xab\x81M\x05\x02\x81\x15\x1f\x04\xfe\x9c\t\t\x14\x1f\x04\xfe\xaf\b\b\x17\"\x12\x14\x14\x14!\x18\b\f\x01O\x04\x1f\x14\t\t\x01d\x05\x1f\x14\x15\x1f\x04\x01X\x01\x04\x01$\x0f\x01k\n\b\x18!\x15\x15\x15\x15!\x18\x06\f\xfe\x9a\x01!\x16\r\x0e\xfe\xbc\x04\x1f\xfc\xcd\x01b\xfe\x9e\x10\x03\x1c\x04\t\n\x05\xfe\x98\x06\xc7\x01[\xc2\b\x02\x01\xc0\xc8\xc8\x10\xfbT\x06\x05DOi\x01\n\xfe\xcd@\xfe\x90\x1c\x016\xfe\xa9\x04\x0f\x01b\xfe\xb1\x06\x05\x01xB\x01A\xa6ݽ\xb1\b\x035\x01\x02\x01\x10\r\xb1\x01\r\v\xfeɝ\x01:\xec\xde\b\xfe\xf8J\xc9\x02\f\xe0\xe1+\xfe\xc5\xfe\xc1\x013\x0f\x8d\xfe\xe4\xdd,\x01\x88\xfb\x02p\x05\x01\x15\r\x10\x02\x01x\x01\x04\xfe1\xfe\xb9\x01\xf6\xdf\xfe\xe6\xfc\x89\xfe\xe5\x01\x1b\xe3\xe3F\x01i\n\x04\x01\x0f\x01(\xfd\x9cR\x03\x00\x02\x00\x00\xff\x00\x05\x80\x06\x00\x00\r\x00\x1b\x00\x00\x11463!\x01\x11\x14\x06#!\"&5%'\x114&#!\"\x06\x15\x11\x14\x163\xb7\x83\x02\xe6\x01`\xb7\x83\xfc\xf4\x83\xb7\x04а@.\xfe\x1c.@A-\x03X\x83\xbf\x01f\xfaB\x84\xbe\xbe\x84$\xb4\x01\xa9.BB.\xfe\x14.C\x00\x00\x04\x00\x00\xff\x83\x06\x00\x05}\x00\n\x00\x14\x00\x1e\x00)\x00\x00\x01\x04\x00\x03&54\x12$32\x05\x16\x17\x04\x00\x03&'\x12\x00\x01\x12\x00%\x16\x17\x04\x00\x03&\x05&'\x06\a6\x007\x06\a\x16\x03\xa6\xfe\xc3\xfe\"w\x14\xcd\x01`\xd0R\x01d]G\xfe{\xfd\xc5o]>p\x026\xfe\xa3s\x02\x11\x01c(\x0e\xfe\xdc\xfe@wg\x03\xcf\xc1\xae\x87\x9bm\x01J\xcc\x15PA\x05jy\xfe\x1d\xfe\xc1YW\xd0\x01a͊AZq\xfd\xc1\xfe{HZ\x01\x82\x02:\xfb<\x01d\x02\x14v\\gx\xfe>\xfe\xdb\x0e\x142AT\x17\xcd\x01Kn\x98\x84\xaf\x00\x00\x03\x00\x00\xff\x80\b\x00\x04\xf7\x00\x16\x00+\x00;\x00\x00\x01\x13\"'&#\"\a&#\"\a\x06+\x01\x136!2\x1763 \x012\x16\x17\x03&#\"\a&#\"\a\x03>\x0232\x1767\x03\x06\a&#\"\a\x03>\x0132\x176\x17\ae\x9b\x83~\xc8\xc1└\xe2\xc1Ȁ|\x05\x9b\xe0\x01\x02隚\xe9\x01\x02\xfe\xf1\x81Ν|\xab\xc5\xe0\x96\x96\xe0ū|iy\xb0Zʬ\xac\xf27Ӕ\x98ް\xa0r|\xd1uѥ\xac\xca\x04x\xfb\b9[\x94\x94[9\x04\xf8\u007fjj\xfb\xa69A\x03\xfdN\x8d\x8dN\xfc\x03+,#ll\"\x03\x8b\x04\x97\x9bB\xfcS32fk\x05\x00\x00\x05\x00\x00\xff\xa5\b\x00\x05[\x00\x0f\x00\x1f\x00/\x00?\x00\\\x00\x00%\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126%\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126%\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126%\x114&+\x01\"\x06\x15\x11\x14\x16;\x0126%\x14\x06#!\"&5467&54632\x176$32\x1e\x01\x15\x14\a\x1e\x01\x05\xdc\x1e\x14]\x14\x1e\x1e\x14]\x14\x1e\xfe\xe4\x1e\x14e\x14\x1e\x1e\x14e\x14\x1e\xfe\xdc\x1e\x14e\x14\x1e\x1e\x14e\x14\x1e\xfe\xdc\x1e\x14e\x14\x1e\x1e\x14e\x14\x1e\x05\x88\xec\xa6\xfb$\xa6\xec~i\n\xa1qfN-\x01*\xbd\x95\xfc\x93\x0e\x87\xac\xa5\x02\xdd\x15\x1e\x1e\x15\xfd#\x14\x1e\x1e\x14\x02\x13\x14\x1e\x1e\x14\xfd\xed\x14\x1e\x1e\x14\x01\xad\x14\x1e\x1e\x14\xfeS\x14\x1e\x1e\x14\x01j\x14\x1e\x1e\x14\xfe\x96\x14\x1e\x1e\xa6\xa6\xec\xec\xa6t\xc52\"'q\xa1C\xb7\xea\x93\xfc\x95B8!\xdb\x00\x00\x00'\x00\x00\xff>\x06\x00\x06\x00\x00\x04\x00\t\x00\r\x00\x11\x00\x15\x00\x19\x00\x1d\x00!\x00%\x00)\x00-\x001\x005\x009\x00=\x00A\x00E\x00I\x00M\x00Q\x00U\x00Y\x00]\x00a\x00g\x00k\x00o\x00s\x00w\x00{\x00\u007f\x00\x85\x00\x89\x00\x8d\x00\x91\x00\x95\x00\x99\x00\xa5\x00\xd5\x00\x00\x11!\x11\t\x01%\x11!\x11\t\x015!\x15\x13\x15#5\x17\x15#5\x17\x15#5\x17\x15#5\x17\x15#5\x177\x17\a\x177\x17\a\x177\x17\a\x177\x17\a?\x01\x17\a?\x01\x17\a?\x01\x17\a?\x01\x17\a\x01\x15#5!\x15#5!\x15#5!\x15#5!\x15#5!\x15#5!\x15#5!\x15#5\x01\x15#53\x157\x15#5!\x15#5!\x15#5!\x15#5!\x15#5!\x15#5\x175#53\x15\a53\x15\a53\x15\a53\x15\a53\x15\a53\x15%\"&54632\x16\x15\x14\x06\x01\x14\x1e\x026\x16\x15\x14#\"'#\a\x1632>\x0254.\x01\x06&54>\x0132\x16\x1737.\x06#\"\x0e\x02\x06\x00\xfc\xf8\xfd\b\x05\x9c\xfa\xc8\x02\x95\x02\xa3\xfa\xc8Q%%%%%%%%%?\x0fi\x0f\x1f\x0fi\x0f\x1e\x0fi\x0f\x1f\x0fh\x0fOi\x0fixi\x0fiyi\x0fixi\x0fi\xfcAr\x01\x14s\x01\x15s\x01\x14r\x01\x14r\x01\x14s\x01\x15s\x01\x14r\xfb\xb8%s\xa2s\x01\x15s\x01\x14r\x01\x14r\x01\x14s\x01\x15s\xf0Ns%%%%%%%%%%\xfd\x88\x81\xb8\xb8\x81\x82\xb7\xb7\xfe\xd9'\x0232\x16\x15\x14\a\x06\x04#\".\x0154\x0032\x1e\x0532654&#\"\x06#\"&54654&#\"\x0e\x02#\"&547>\x0132\x16\x15\x14\a6\x05\x96\x01\x04\x94\xd2ڞU\x9azrhgrx\x98S\x9a\xc3Пd\xd8U\x05 \x1c\b\x0e\x15\x017\x03#\"&463!2\x1e\x04\x17!2\x16\x04\xc0&\x1a\x80&4&\x80\x1a&&\x1a\x80&4&\x80\x1a\xfd\xe6KjKKj\x03\xcbKjKKj\xcb \x19\xfb\xec\x01\a\x05\x18\x03\x98\x1a&&\x1a\xfc\x00\x1a&\x16%\x02\xb1\xcc\x1a&&\x1a\x01\x00\x10\x19\x0f\v\x04\a\x01\x04\xb1\x1a&\x03&4&\x80\x1a&&\x1a\x80&4&\x80\x1a&&\x1a\x80\xfd5jKKjKKjKKjK\x03\xc0\xfe\x00\x18%\x03z\a\x1d\x18\n\x100&4&&\x1a\x0e3D\x04\x037&4&\r\x12\x1f\x16%\a&\x00\x00\x00\x00\x04\x00\x00\xff\x80\x06\x80\x05\x00\x00\x17\x00\x1f\x00'\x00S\x00\x00\x004&\"\x0f\x01\x114&\"\x06\x15\x11'&\"\x06\x14\x17\x01\x1627\x01\x00\x14\x06\"&462\x04\x14\x06\"&462\x13\x11\x14\x06\a\x05\x1e\x02\x15\x14\a!2\x16\x14\x06#!\"&54>\x017\x03#\"&463!2\x1e\x04\x17!2\x16\x05\x00&4\x13\x93&4&\x93\x134&\x13\x01\x00\x134\x13\x01\x00\xfd\x93KjKKj\x03\xcbKjKKj\xcb \x19\xfb\xec\x01\a\x05\x18\x03\x98\x1a&&\x1a\xfc\x00\x1a&\x16%\x02\xb1\xcc\x1a&&\x1a\x01\x00\x10\x19\x0f\v\x04\a\x01\x04\xb1\x1a&\x03&4&\x13\x92\x01%\x1a&&\x1a\xfeے\x13&4\x13\xff\x00\x13\x13\x01\x00\xfd\"jKKjKKjKKjK\x03\xc0\xfe\x00\x18%\x03z\a\x1d\x18\n\x100&4&&\x1a\x0e3D\x04\x037&4&\r\x12\x1f\x16%\a&\x00\x00\x00\x00\a\x00\x00\xff\x00\b\x00\x05\x80\x00\x02\x00\x05\x00\t\x00\f\x00\x10\x00\x14\x00&\x00\x00\x13\t\x03!'\x13!\t\x02!%!\x03!\x01!\x01!%\x01\x16\x06\a\x01\x06\"'\x01.\x017\x0163!2\xd4\x02o\xfe\xd4\x01\xe9\x01]\xfdF\x89\xcc\xfe\xfa\xfe\xe0\x03\xfd\x02o\xfe\xbd\xfc\xc2\x02\xaa\xcc\xfe\xee\x02o\x01Z\xfe\xe0\xfe\xfa\x01Y\x01\x80\x0e\x02\x10\xfc@\x12:\x12\xfc@\x10\x02\x0e\x01\x80\x12!\x04\x80!\x03\x00\xfdg\x02\x99\xfc\xfc\x03\x04\x80\x01\x80\xfe\x80\xfc\xe7\x02\x99\x80\x01\x80\xfe\x80\x01\x80f\xfe\x00\x12/\x11\xfc\x00\x14\x14\x04\x00\x11/\x12\x02\x00\x1a\x00\x03\x00\x13\xff\x00\a\xed\x06\x00\x00I\x00\x97\x00\xa0\x00\x00\x0562\x1f\x01\a'\a\x06\"/\x01\a\x06\"/\x01\a\x06\"/\x01\a\x06\"/\x01\a\x06\"/\x01\a\x06\"/\x01\a\x06\"/\x017\x17762\x1f\x01762\x1f\x01762\x1f\x01762\x1f\x01762\x1f\x01762\x1f\x01%\x06\"/\x017\x17762\x1f\x017\x11\x03&6?\x01\x1135!5!\x15!\x153\x11\x17\x1e\x01\a\x03\x11762\x1f\x01762\x1f\x01\a'\a\x06\"/\x01\a\x06\"/\x01\a\x06\"/\x01\a\x06\"/\x01\a\x06\"/\x01\a\x06\"/\x01\x01\x15%\x055#5!\x15\a\x13\x134\x13\x80ZSS\x126\x12SS\x134\x13SS\x134\x13SS\x134\x13SS\x134\x13SS\x134\x13SS\x134\x13\x80ZSS\x134\x13SS\x134\x13SS\x134\x13SS\x134\x13SS\x134\x13SS\x134\x13S\xfa-\x134\x13\x80ZSS\x134\x13S@\xd2\x11\x14\x1e\xb1\x80\x01\x00\x01\x00\x01\x00\x80\xb1\x1e\x14\x11\xd2\x13\x134\x13SS\x134\x13\x80ZSS\x126\x12SS\x134\x13SS\x134\x13SS\x134\x13SS\x134\x13SS\x134\x13S\x01@\x01\x80\x01\x80\x80\xfe\x00\x13\x13\x13\x80ZSS\x13\x13SS\x13\x13SS\x13\x13SS\x13\x13SS\x13\x13SS\x13\x13SS\x13\x13\x80ZSS\x13\x13SS\x13\x13SS\x13\x13SS\x13\x13SS\x13\x13SS\x13\x13Sy\x13\x13\x80ZRR\x13\x13R@\x01%\x01:\x1a=\n:\x01+\x80\x80\x80\x80\xfe\xd5:\n=\x1a\xfe\xc6\xfe\xdb\x12\x13\x13RR\x13\x13\x80ZSS\x13\x13SS\x13\x13SS\x13\x13SS\x13\x13SS\x13\x13SS\x13\x13S\x04\x1a\x80\x80\x80\x80\x80\x80\x00\x00\x00\x04\x00\x00\xff\x80\x05\x80\x06\x00\x00\x03\x00\a\x00C\x00v\x00\x00!\x13/\x01\x01\x13\x0f\x01\x01&'&#\"\a\x06\"'&#\"\a\x06\a\x16\x17\x1e\x01\x17\x1e\t32>\x03;\x012\x1e\x0332>\b7>\x0176\x01\x14\x06#!\"&54>\x037'3&547&547>\x017632\x162632\x17\x1e\x01\x17\x16\x15\x14\a\x16\a3\a\x1e\x03\x02@``\x80\x01\x80\x80\x80`\x01\x00\x02\x02\nVFa\a\x1c\aaFV\n\x02\x02\x02\x02\x02\v\x02\x02\v\x03\f\x05\r\v\x11\x12\x17\r$.\x13\n\r\v\f\v\r\n\x13.$\r\x17\x12\x11\v\r\x05\f\x03\v\x02\x02\v\x02\x02\x01\xa2\x92y\xfc\x96y\x92\t\x1d.Q5Z\xd6\x16\x02\xc2\xd2\x11E$ ,\x1el\x90*%>>%*\x90>*98(QO\xe1!\u007f\xa0\x8f\x00\x03\x00\x00\x00\x00\b\xfd\x05\x00\x00L\x00\\\x00p\x00\x00\x01\x16\x0e\x02'.\x01'&67'\x0e\x01\x15\x14\x06#!#\x0e\x01#\"\x00\x10\x0032\x177&+\x01\"&46;\x012\x1e\x02\x17!3'#\"&7>\x01;\x012\x1f\x0176;\x012\x16\x1d\x01\x14\x06+\x01\x176\x17\x1e\x01\x01267!\"'&7\x13&#\"\x06\x10\x16(\x016\x10&#\"\a\x13\x16\x06\a\x06#\"'\x03\x06\x15\x14\b\xfd\fD\x82\xbbg\xa1\xed\x10\fOOG`n%\x1b\xff\x00E\x17\xfc\xa8\xb9\xfe\xf9\x01\a\xb9LL\x18{\xb5@\x1a&&\x1a\x80N\x86c,\x1d\x02\x00sU\xde\x1e&\x05\x04&\x18\xfd!\x14Fr\x13\x1be\x1a&&\x1a\xb3s\x83\x90\x8f\xca\xf8\xd4s\xb0\x17\xfe\xc6#\x14\x12\x11\x93/,\x84\xbc\xbc\x05\x80\x01\b\xbc\xbc\x84<=\xae\x0f\n\x16\x0f\x15#\x12\xae]\x01\xf4g\xbf\x88L\a\v\xe4\xa0o\xc7GkP\xe4\x82\x1b'\xa4\xdc\x01\a\x01r\x01\a\x1b-n&4&\x1b2\x1d\x16\x80-\x1e\x17\x1e\x1cir\x13&\x1a\x80\x1a&\xac?\x1b\x1a\xd9\xfd\xfb\x91o\x1f \x1f\x01\x15\r\xbc\xfe\xf8\xbc\xbc\x01\b\xbc\x18\xfe\xfc\x174\x0e\v\x1d\x01\x04_\x82\x84\x00\x00\x03\x00\x00\xff\x00\x05\x80\x05\xe0\x005\x00O\x00W\x00\x00!\x14\x0e\x02 .\x0254>\x0276\x16\x17\x16\x06\a\x0e\x04\a\x1e\x042>\x037.\x04'.\x017>\x01\x17\x1e\x03\x01\x11\x14\x06+\x01\x11\x14\x06#!\"&5\x11#\"&5\x11463!2\x16\x02\x14\x06\"&462\x05\x80{\xcd\xf5\xfe\xfa\xf5\xcd{BtxG\x1a,\x04\x05\x1f\x1a:`9(\x0f\x01\x030b\x82\xbfԿ\x82b0\x03\x01\x0f(9`:\x1a\x1f\x05\x04,\x1aGxtB\xfe\x80&\x1a@&\x1a\xff\x00\x1a&@\x1a&K5\x01\x805K`\x83\xba\x83\x83\xba?e=\x1f\x1f=e?1O6#\f\x05\x1f\x1a\x1a,\x04\n\x1b\x18\x17\x10\x04\v\x1f#\x1e\x14\x14\x1e$\x1f\f\x04\x0e\x18\x17\x1b\n\x04,\x1a\x1a\x1f\x05\f#6O\x03O\xfe\x80\x1a&\xfe\x80\x1a&&\x1a\x01\x80&\x1a\x01\x805KK\x01\xa8\xba\x83\x83\xba\x83\x00\x02\x00\x00\xff\x80\a\x00\x05\x80\x00\x1b\x00?\x00\x00\x01!\x0e\x01\x0f\x01\x01\x06\"'\x01&'!267\x1b\x01\x1e\x013267\x13\x17\x16\x01\x14\a!'.\x01\a\x06\a\v\x01.\x01\"\x06\a\x03!&54632\x1e\x02\x17>\x0332\x16\x05\x00\x011\x05\n\x04\x03\xfd\x91\x124\x12\xfd\x90\x05\x10\x01q\x16#\x05F\xbe\x06\"\x16\x15\"\x06\x928\x12\x02'g\xfe\x8fo\b#\x13-\v\x81\xc4\x06#,\"\x05t\xfeYg\xfe\xe0>\x81oP$$Po\x81>\xe0\xfe\x02\x00\x06\t\x03\x04\xfd\xa8\x12\x12\x02Z\x02\x12\x1b\x15\x01\x19\xfde\x14\x1a\x1a\x14\x01\xe5p#\x01\xac\x91\x9b\xdd\x11\x14\x02\x05)\xfeR\x02\xae\x14\x1a\x1b\x15\xfe0\x9b\x91\xdc\xf8+I@$$@I+\xf8\x00\x00\x02\x00\x02\xff\x00\x04\x80\x05\xfc\x00+\x003\x00\x00\x01\x14\x00\a\x1132\x16\x1d\x01\x14\x06+\x01\x15\x14\x06+\x01\"&=\x01#\"&=\x0146;\x01\x11.\x01\x027>\x0276\x04\x12$\x10\x00 \x00\x10\x00 \x04\x80\xfe\xd9\xd9\xe0\x0e\x12\x12\x0e\xe0\x12\x0e@\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\x96\xf3\x81\f\v\x8bᅪ\x01*\xae\xfc\x00\x01\a\x01r\x01\a\xfe\xf9\xfe\x8e\x03\xc0\xdd\xfe\xb9\x18\xfe\xfc\x12\x0e@\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\x12\x0e@\x0e\x12\x01\x04\x10\xae\x01\x12\x9b\x86\xe6\x92\x0f\x13\x92\xfe\xea\x12\xfe\x8e\xfe\xf9\x01\a\x01r\x01\a\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00'\x00/\x00\x00\x012\x16\x15\x11\x14\x06+\x01\"&5\x11\x01\x16\x15\x14\x0e\x02\".\x024>\x0232\x17\x01!\"&=\x01463\x00 \x00\x10\x00 \x00\x10\x05\xc0\x1a&\x12\x0e@\x0e\x12\xfe\x82~[\x9b\xd5\xea՛[[\x9b\xd5u˜\x01~\xfe\xfb\x0e\x12\x12\x0e\xfdg\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\x05\x80&\x1a\xfe`\x0e\x12\x12\x0e\x01\x06\xfe\x81\x9c\xcbu՛[[\x9b\xd5\xea՛[~\x01~\x12\x0e@\x0e\x12\xfa\x80\x01\a\x01r\x01\a\xfe\xf9\xfe\x8e\x00\x00\x00\x00\x02\x00\x00\xff\x00\x04\x80\x06\x00\x00=\x00E\x00\x00\x01\x16\x12\x15\x14\x00\a\x1532\x16\x1d\x01\x14\x06+\x01\x15\x14\x06+\x01\"&=\x01#\"&=\x0146;\x015&\x0054\x127&'&6;\x012\x17\x1e\x012676;\x012\x16\a\x06\x00 \x00\x10\x00 \x00\x10\x03>\x91\xb1\xfe\xd9\xd9`\x0e\x12\x12\x0e`\x12\x0e@\x0e\x12`\x0e\x12\x12\x0e`\xd9\xfeٱ\x91\xa5?\x06\x13\x11E\x15\b,\xc0\xec\xc0,\b\x1d=\x11\x13\x06?\xfd\xa4\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\x04\xc4H\xfe\xeb\xa7\xdd\xfe\xb9\x18\x84\x12\x0e@\x0e\x12`\x0e\x12\x12\x0e`\x12\x0e@\x0e\x12\x84\x18\x01Gݧ\x01\x15H`\xb1\x10\x1b\x14j\x82\x82j\x14\x1b\x10\xb1\xfb\xdc\x01\a\x01r\x01\a\xfe\xf9\xfe\x8e\x00\x02\x00\x02\xff\x00\x05\x80\x06\x00\x00B\x00J\x00\x00\x01463!2\x16\x15\x11\x14\x06+\x01\"&=\x01\a\x16\x15\x14\x00\a\x1532\x16\x1d\x01\x14\x06+\x01\x15\x14\x06+\x01\"&=\x01#\"&=\x0146;\x015.\x01\x0276\x0076\x16\x17%#\"&5\x00 \x00\x10\x00 \x00\x10\x04\x00\x12\x0e\x01 \x1a&\x12\x0e@\x0e\x12\xfe~\xfe\xd9\xd9`\x0e\x12\x12\x0e`\x12\x0e@\x0e\x12`\x0e\x12\x12\x0e`\x95\xf3\x82\f\x10\x01 \xcbv\xdcX\x00\xff\x86\x0e\x12\xfd\x87\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\x05\xe0\x0e\x12&\x1a\xfe\xe0\x0e\x12\x12\x0e\x86\xff\x9e\xc9\xdd\xfe\xb9\x18\x84\x12\x0e@\x0e\x12`\x0e\x12\x12\x0e`\x12\x0e@\x0e\x12\x84\x10\xae\x01\x11\x9b\xcc\x01+\x17\x0eBF\xfe\x12\x0e\xfb`\x01\a\x01r\x01\a\xfe\xf9\xfe\x8e\x00\x00\x02\x00\x00\xff\x00\x06\x80\x06\x00\x00k\x00s\x00\x00\x01463!2\x16\x15\x11\x14\x06+\x01\"&=\x01\a\x16\x15\x14\x00\a\x1532\x16\x1d\x01\x14\x06+\x01\x15\x14\x06+\x01\"&=\x01#\"&=\x0146;\x015&\x00547'\a\x0e\x01/\x01.\x01?\x01'\x15\x14\x06+\x01\"&5\x11463!2\x16\x1d\x01\x14\x06+\x01\x177>\x01\x1f\x01\x1e\x01\x0f\x01\x176 \x17%#\"&5\x00 \x00\x10\x00 \x00\x10\x05\x00\x12\x0e\x01 \x1a&\x12\x0e@\x0e\x12\xfe~\xfe\xd9\xd9`\x0e\x12\x12\x0e`\x12\x0e@\x0e\x12`\x0e\x12\x12\x0e`\xd9\xfe\xd9~4e\t\x1a\n0\n\x01\tio\x12\x0e@\x0e\x12&\x1a\x01 \x0e\x12\x12\x0e\x85jV\t\x1a\n0\n\x01\tZ9\x9e\x01\x92\x9e\x00\xff\x86\x0e\x12\xfd\x87\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\x05\xe0\x0e\x12&\x1a\xfe\xe0\x0e\x12\x12\x0e\x86\xff\x9e\xc9\xdd\xfe\xb9\x18\x84\x12\x0e@\x0e\x12`\x0e\x12\x12\x0e`\x12\x0e@\x0e\x12\x84\x18\x01G\xddɞ5o\n\x01\b,\b\x1b\nsp\x86\x0e\x12\x12\x0e\x01 \x1a&\x12\x0e@\x0e\x12k^\n\x01\b,\b\x1b\nc8~~\xfe\x12\x0e\xfb`\x01\a\x01r\x01\a\xfe\xf9\xfe\x8e\x00\x00\x00\x00\x05\x00\x02\xff\x00\x06\xfe\x05\xfd\x008\x00>\x00K\x00R\x00_\x00\x00\x01\x16\x02\x06\a\x1132\x16\x1d\x01\x14\x06+\x01\x15\x14\x06+\x01\"&=\x01!\x15\x14\x06+\x01\"&=\x01#\"&=\x0146;\x01\x11.\x01\x0276\x0076\x176\x17\x16\x00\x016\x10'\x06\x10\x0327&547&#\"\x00\x10\x00\x01\x11&'\x06\a\x11\x012\x00\x10\x00#\"\a\x16\x15\x14\a\x16\x06\xfe\f\x81\xf3\x96\xe0\x0e\x12\x12\x0e\xe0\x12\x0e@\x0e\x12\xfe\x00\x12\x0e@\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\x96\xf3\x81\f\x11\x01'\xcdΫ\xab\xce\xcd\x01'\xfc\x93\x80\x80\x80\xc0sg\x9a\x9ags\xb9\xfe\xf9\x01\a\x02\xf9\x89ww\x89\x02@\xb9\x01\a\xfe\xf9\xb9sg\x9a\x9ag\x03\xef\x9b\xfe\xee\xae\x10\xfe\xfc\x12\x0e@\x0e\x12\xe0\x0e\x12\x12\x0e\xe0\xe0\x0e\x12\x12\x0e\xe0\x12\x0e@\x0e\x12\x01\x04\x10\xae\x01\x12\x9b\xce\x01-\x13\x15ss\x15\x13\xfe\xd3\xfdʃ\x01l\x83\x83\xfe\x94\xfe\xf69\xa5\xe2\xe0\xa79\xfe\xf9\xfe\x8e\xfe\xf9\xfe\x80\x01\x04\x0fOO\x0f\xfe\xfc\x01\x80\x01\a\x01r\x01\a9\xa7\xe0\xe2\xa59\x00\x00\x04\x00\x01\xff\x06\a\x80\x06\x00\x00F\x00P\x00^\x00l\x00\x00\x01463!2\x16\x15\x11\x14\x06+\x01\"&=\x01\a\x1e\x01\a\x06\x00\a\x06$'.\x037>\x0276\x16\x17%#\"&=\x01463!2\x16\x15\x11\x14\x06+\x01\"&=\x01\a\x16\x17\x16\x17%#\"&5\x014'\x0e\x01\x15\x14\x17>\x01%\x14\x16\x17&54\x007.\x01#\"\x00\x012\x0054&'\x16\x15\x14\x00\a\x1e\x01\x06\x00\x12\x0e\x01 \x1a&\x12\x0e@\x0e\x12\xfeL?\x16\x1f\xfe\xf2\xb7\xd2\xfe\xa3CuГP\b\t\x8a\xe2\x87v\xdbY\x00\xff\x86\x0e\x12\x12\x0e\x01 \x1a&\x12\x0e@\x0e\x12\xfe;\"\xb6\x92\x00\xff\x86\x0e\x12\xfe\x00\x04\xa2\xda\x04\xa2\xda\xfc\x80ޥ\x03\x01\x0e\xcb5݇\xb9\xfe\xf9\x03\xc0\xb9\x01\aޥ\x03\xfe\xf2\xcb5\xdd\x04`\x0e\x12&\x1a\xfe\xe0\x0e\x12\x12\x0e\x86\xff_\ue036\xfe\xfc\x1a\x1dڿ\x06g\xa3\xdew\x87\xea\x95\x0f\x0eBF\xfe\x12\x0e@\x0e\x12&\x1a\xfe\xe0\x0e\x12\x12\x0e\x86\xffJ_\ts\xfe\x12\x0e\xfe\xa0\x14&\x19\xfa\xa7\x14&\x19\xfa\xa7\xa8\xfc\x17\x1d\x1e\xd2\x01?%x\x92\xfe\xf9\xfc\a\x01\a\xb9\xa8\xfc\x17\x1c\x1f\xd2\xfe\xc1%x\x92\x00\x04\x00\x06\xff\x00\b\x00\x06\x00\x00J\x00P\x00\\\x00h\x00\x00\x01463!2\x16\x15\x11\x14\x06+\x01\"&=\x01\a\x1e\x01\a\x06\x00\a\x06'\x06\a\x1532\x16\x1d\x01\x14\x06+\x01\x15\x14\x06+\x01\"&=\x01#\"&=\x0146;\x015.\x01\x0276\x0076\x17632\x17%#\"&5\x016\x10'\x06\x10\x00\x10\x00327&\x107&#\"\x012\x00\x10\x00#\"\a\x16\x10\a\x16\x06\x80\x12\x0e\x01 \x1a&\x12\x0e@\x0e\x12\xfeL?\x16 \xfe\xf7\xb5ߺu\x8b`\x0e\x12\x12\x0e`\x12\x0e@\x0e\x12`\x0e\x12\x12\x0e`\x9b\xf9}\x17\x19\x01\r\xba\u0e92\xaeɞ\x00\xff\x86\x0e\x12\xfd\x00\x80\x80\x80\xfd\x80\x01\a\xb9ue\x9a\x9aeu\xb9\x039\xb9\x01\a\xfe\xf9\xb9ue\x9a\x9ae\x05\xe0\x0e\x12&\x1a\xfe\xe0\x0e\x12\x12\x0e\x86\xff_\ue034\xfe\xfc\x1b\"|N\x0f\x84\x12\x0e@\x0e\x12`\x0e\x12\x12\x0e`\x12\x0e@\x0e\x12\x84\x11\xb9\x01\"\xa2\xbb\x01\x0f\x1d\"|a~\xfe\x12\x0e\xfb\xe7\x83\x01l\x83\x83\xfe\x94\x01o\xfe\x8e\xfe\xf99\xa7\x01\xc0\xa79\xfc\x80\x01\a\x01r\x01\a9\xa7\xfe@\xa79\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00;\x00C\x00\x00\x012\x16\x15\x11\x14\x06+\x01\"&5\x11\a\x17\x16\x14\x0f\x01\x06\"/\x01\a\x16\x15\x14\x0e\x02\".\x024>\x0232\x177'&4?\x0162\x1f\x017!\"&=\x01463\x00 \x00\x10\x00 \x00\x10\x05\xc0\x1a&\x12\x0e@\x0e\x12Ռ\t\t.\t\x1a\n\x8cN~[\x9b\xd5\xea՛[[\x9b\xd5u˜N\xac\t\t.\t\x1a\n\xac\xd5\xfe\xfb\x0e\x12\x12\x0e\xfdg\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\x05\x80&\x1a\xfe`\x0e\x12\x12\x0e\x01\x06\u058c\n\x1a\t.\t\t\x8dO\x9c\xcbu՛[[\x9b\xd5\xea՛[~N\xac\n\x1a\t.\t\t\xac\xd5\x12\x0e@\x0e\x12\xfa\x80\x01\a\x01r\x01\a\xfe\xf9\xfe\x8e\x00\x00\x00\x00\x02\x00\x02\xff\x04\x04\x80\x06\x00\x009\x00A\x00\x00\x01\x16\x00\x15\x14\x02\x04'.\x02'&\x12675#\"&=\x0146;\x015\a\x06\"/\x01&4?\x0162\x1f\x01\x16\x14\x0f\x01\x06\"/\x01\x1532\x16\x1d\x01\x14\x06+\x01\x02 \x00\x10\x00 \x00\x10\x02\x80\xd9\x01'\xae\xfe֪\x85\xe1\x8b\v\f\x81\xf3\x96\xa0\x0e\x12\x12\x0e\xa0\\\n\x1a\t.\t\t\xca\x134\x13\xca\t\t.\t\x1a\n\\\xa0\x0e\x12\x12\x0e\xa0\xf9\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\x03|\x18\xfe\xb9ݧ\xfe\xea\x92\x13\x0f\x92憛\x01\x12\xae\x10\x84\x12\x0e@\x0e\x12\xa5\\\t\t.\t\x1a\n\xc9\x13\x13\xc9\n\x1a\t.\t\t\\\xa5\x12\x0e@\x0e\x12\xfb\x80\x01\a\x01r\x01\a\xfe\xf9\xfe\x8e\x00\x00\x02\x00\x04\x00\x00\a\x80\x04~\x009\x00A\x00\x00\x01\x16\x14\a\x01\x06\"/\x01&4?\x01!\x15\x14\x06+\x01\"&=\x01#\x06\x00#\"$\x027>\x0276\x04\x16\x173546;\x012\x16\x1d\x01!'&4?\x0162\x17\x00 \x00\x10\x00 \x00\x10\am\x13\x13\xfe\xda\t\x1b\t-\n\n\xb9\xfe\xda\x12\x0e@\x0e\x12\x84\x18\xfe\xb9ݧ\xfe\xea\x92\x13\x0f\x92憛\x01\x12\xae\x10\x84\x12\x0e@\x0e\x12\x01&\xb9\n\n-\t\x1b\t\xfb@\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\x02m\x134\x13\xfe\xda\n\n-\t\x1b\t\xb9\xe0\x0e\x12\x12\x0e\xe0\xd9\xfeٮ\x01*\xaa\x85\xe1\x8b\v\f\x81\xf3\x96\xe0\x0e\x12\x12\x0e\xe0\xb9\t\x1b\t-\n\n\xfc\xed\x01\a\x01r\x01\a\xfe\xf9\xfe\x8e\x00\x00\x02\x00\x00\xff\x00\x04\x80\x06\x00\x00\x17\x00\x1f\x00\x00\x01\x14\x00\a\x11\x14\x06+\x01\"&5\x11&\x0054>\x022\x1e\x02\x00 \x00\x10\x00 \x00\x10\x04\x80\xfe\xd9\xd9\x12\x0e@\x0e\x12\xd9\xfe\xd9[\x9b\xd5\xea՛[\xfd\a\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\x03\xc0\xdd\xfe\xb9\x18\xfd\x9c\x0e\x12\x12\x0e\x02d\x18\x01G\xddu՛[[\x9b\xd5\xfd\xcb\x01\a\x01r\x01\a\xfe\xf9\xfe\x8e\x00\x00\x02\x00\x00\x00\x00\x04\x80\x04\x80\x00\a\x00\x17\x00\x00\x00\x10\x00 \x00\x10\x00 \x00\x14\x0e\x02\".\x024>\x022\x1e\x01\x04\x00\xfe\xf9\xfe\x8e\xfe\xf9\x01\a\x01r\x01\x87[\x9b\xd5\xea՛[[\x9b\xd5\xea՛\x01\x87\x01r\x01\a\xfe\xf9\xfe\x8e\xfe\xf9\x025\xea՛[[\x9b\xd5\xea՛[[\x9b\x00\x00\x01\x00\x00\xff\x80\x06\x00\x05\x80\x00$\x00\x00\x012\x16\x15\x11\x14\x06#!\x1137#546375&#\"\x06\x1d\x01#\x153\x11!\"&5\x11463\x05\xab#22#\xfey\xc7\x1e\xe5/Dz?s\x88\xa3\xc8\xc8\xfd!#22#\x05\x802#\xfa\xaa#2\x02S\xe8\x9488\x01\xcf\t\xa0\x92\xab\xe8\xfd\xad2#\x05V#2\x00\x00\x00\x01\x00\x00\xff\x80\x05\x00\x06\x00\x00L\x00\x00\x114>\x0332\x04\x16\x15\x14\x0e\x03#\"&'\x0e\x06\x0f\x01'&546\x127&54632\x16\x15\x14\x06\x15\x14\x1632>\x0454&#\"\x00\x15\x14\x1e\x02\x15\x14\x06#\"'.\x03K\x84\xac\xc6g\x9e\x01\x10\xaa&Rv\xacgD\x86\x1d\n$\v\x1e\x16*2%\x0e\t\x0f+Z\a hP=DXZ@7^?1\x1b\r۰\xc8\xfe\xf4\x19\x1d\x19\x1e\x16\x02\x0f3O+\x16\x03\xabl\xbf\x8eh4\x85\xfe\xa0`\xb8\xaa\x81M@8'\x93+c+RI2\x05\n\x9d\x1f\\\xe5\x01Z\x1eAhS\x92Q>B\xfa>?S2Vhui/\xad\xc1\xfe\xfd\xc7,R0+\t\x1cZ\x03\x0fRkm\x00\x00\x00\x00\x03\x00\x00\xffz\x06\x00\x05\x86\x00+\x00>\x00Q\x00\x00\x002\x16\x17\x16\x15\x14\a\x0e\x01#\"'.\x01'&7567632\x1632\x16\x17\x1e\x01\x15\x14\x06\x15\x14\x17\x16\x17\x16\x17\x1632\x032>\x024.\x02\"\x0e\x02\x15\x14\x17\a7\x16\x12 \x04\x16\x12\x10\x02\x06\x04#\"'\x05\x13&54\x126\x03\xcc\x1a\xa9\x05\x02\x11\x10n/9\x85b\x90LH\x01\x03G\x18\x1c\x06\x18\a\x13\x0f\b\b2E\x05\"D8_\f\n\x0fp\u007f\xe9\xa8dd\xa8\xe9\xfe\xe9\xa8dxO\xf2\x9e\"\x012\x01\x17\xcaxx\xca\xfe\xe9\x99ê\xfe_\x88lx\xca\x022X\t\x05\n!+'5>-\x92pkW\b[C\x16\x03\r\x15\x14\x88\a\x15I\n\a\bI@50\a\xfeOd\xa8\xe9\xfe\xe9\xa8dd\xa8\xe9\u007f˥\xe9Mh\x05fx\xca\xfe\xe9\xfe\xce\xfe\xe9\xcax^\x86\x01\x95\xb2ә\x01\x17\xca\x00\x00\t\x00\x00\x00\x00\a\x00\x05\x80\x00\x03\x00\a\x00\x0f\x00\x13\x00\x1b\x00#\x00'\x00+\x00/\x00\x007!5!\x11!5!\x004&\"\x06\x14\x162\x01!5!\x004&\"\x06\x14\x162\x124&\"\x06\x14\x162\x13\x11!\x11\x01\x11!\x11\x01\x11!\x11\x80\x04\x00\xfc\x00\x04\x00\xfc\x00\x06 8P88P\xfa\x18\x04\x00\xfc\x00\x06 8P88P88P88P\x98\xf9\x00\a\x00\xf9\x00\a\x00\xf9\x00\x80\x80\x01\x80\x80\xfd\x98P88P8\x04 \x80\xfd\x98P88P8\x028P88P8\xfd \xfe\x80\x01\x80\x02\x00\xfe\x80\x01\x80\x02\x00\xfe\x80\x01\x80\x00\x00\x03\x00\x00\xff\x80\b\x00\x05\x80\x00\a\x00+\x00N\x00\x00\x00 &\x106 \x16\x10\x01!2\x16\x1d\x01\x14\x06#!\x11\x14\x06+\x01\"&5\x11!\"&=\x01463!\x1146;\x012\x16\x15\x01\x14\x163!\x15\x06#!\"&54>\x0532\x17\x1e\x01267632\x17#\"\x06\x15\x03_\xfe\xc2\xe1\xe1\x01>\xe1\x02@\x01`\r\x13\x13\r\xfe\xa0\x13\r\xc0\r\x13\xfe\xa0\r\x13\x13\r\x01`\x13\r\xc0\r\x13\xfd L4\x01\x00Dg\xfc\x96y\x92\a\x15 6Fe=\x13\x14O\x97\xb2\x97O\x14\x13\x84U\xdf4L\x02\x80\xe1\x01>\xe1\xe1\xfe\xc2\xfe\x9f\x13\r\xc0\r\x13\xfe\xa0\r\x13\x13\r\x01`\x13\r\xc0\r\x13\x01`\r\x13\x13\r\xfd\xc04L\xee2\x8ay5eud_C(\x11====\x11`L4\x00\x00\x00\x03\x00\x00\xff\x80\a\xf7\x05\x80\x00\a\x003\x00V\x00\x00\x00 &\x106 \x16\x10\x01\x17\x16\x15\x14\x0f\x01\x06#\"/\x01\a\x06#\"/\x01&54?\x01'&54?\x01632\x1f\x017632\x1f\x01\x16\x15\x14\a\x05\a\x06\x15\x14\x1f\x01\x06#!\"&54>\x0532\x17\x16 7632\x17\x0e\x01\x15\x14\x17\x03_\xfe\xc2\xe1\xe1\x01>\xe1\x02\xb5\xf9\t\t\x88\t\r\x0e\t\xf9\xf9\t\x0e\r\t\x88\t\t\xf9\xf9\t\t\x88\t\r\x0e\t\xf9\xf9\t\x0e\r\t\x88\t\t\xfd\x15\xb5%%S\x15\x17\xfc\x96y\x92\a\x15 6Fe=\x13\x14\x9a\x01J\x9a\x14\x13\x1c\x1d\x1c\x1a%\x02\x80\xe1\x01>\xe1\xe1\xfe\xc2\xfd\xdf\xf9\t\x0e\r\t\x88\t\t\xf9\xf9\t\t\x88\t\r\x0e\t\xf9\xf9\t\x0e\r\t\x88\t\t\xf9\xf9\t\t\x88\t\r\x0e\t\xf9\xb5%65%S\x03\x8ay5eud_C(\x11zz\x11\x06\x1b.!6%\x00\x03\x00\x00\x00\x00\b\x00\x05\x00\x00\x12\x00\x1a\x00$\x00\x00\x01!2\x16\x15\x11!\x11!\x11!\x1146;\x012\x16\x15\x004&\"\x06\x14\x162!54&#!\"\x06\x15\x11\x01\x00\x06\xc0\x1a&\xff\x00\xfa\x00\xff\x00&\x1a\x80\x1a&\x02@\x96Ԗ\x96\xd4\x05V\xe1\x9f\xfd@\x1a&\x02\x00&\x1a\xfe@\x01\x00\xff\x00\x04\xc0\x1a&&\x1a\xfe\x16Ԗ\x96Ԗ@\x9f\xe1&\x1a\xfe\x80\x00\x00\x00\x00\x02\x00\x00\xff\x00\x06\x00\x06\x00\x00\x16\x00\x19\x00\x00\x01\x033\x15!\a!\x15!\t\x01!5!'!53\x03!\x01!\t\x01\x13#\x06\x00\xc0\xc0\xfe\xee7\x01I\xfee\xfe\x9b\xfe\x9b\xfee\x01I7\xfe\xee\xc0\xc0\x01\x00\x01C\x01z\x01C\xfe\x00l\xd8\x06\x00\xfe@\xc0\x80\xc0\xfc\xc0\x03@\xc0\x80\xc0\x01\xc0\xfd\x00\x03\x00\xfb@\x01\x00\x00\x00\x00\x03\x00\x00\xff\x00\x06\x00\x06\x00\x00\x17\x00\x1f\x00#\x00\x00\x012\x04\x15\x11\x14\x06\a\x17\x16\x06#!\"&?\x01.\x015\x114$3\x12264&\"\x06\x14\x01\x11!\x11\x04@\xb9\x01\a\xfb\xb4\xd5\x10\x10\x16\xfb\xe0\x16\x10\x10մ\xfb\x01\a\xb9\xf0\xa0pp\xa0p\x03\x00\xfb\x80\x06\x00\xbb\x85\xfc\x80\x82\xb8\x05\xca\x0f((\x0f\xca\x05\xb8\x82\x03\x80\x85\xbb\xfa\xc0p\xa0pp\xa0\x01\xd0\x02\x00\xfe\x00\x00\x00\x00\x00\x05\x00\x00\xff\x00\x06\x00\x06\x00\x00\x17\x00\x1f\x00#\x00+\x00/\x00\x00\x012\x04\x15\x11\x14\x06\a\x17\x16\x06#!\"&?\x01.\x015\x114$3\x02264&\"\x06\x14\x01\x11!\x11\x00264&\"\x06\x14\x01\x11!\x11\x04@\xb9\x01\a\xfb\xb4\xd5\x10\x10\x16\xfb\xe0\x16\x10\x10մ\xfb\x01\a\xb9\xe2\x84^^\x84^\x02@\xfd\xe0\x03\xfe\x84^^\x84^\x01@\xfd\xc0\x06\x00\xbb\x85\xfc\x80\x82\xb8\x05\xca\x0f((\x0f\xca\x05\xb8\x82\x03\x80\x85\xbb\xfa\xe0^\x84^^\x84\x01\xc2\x02\x00\xfe\x00\xfd\xe0^\x84^^\x84\x01\xc2\x02\x00\xfe\x00\x00\x00\x00\x00\x04\x00\x00\xff\x8a\a\x00\x05v\x00\x12\x00\x15\x00\x1c\x00(\x00\x00\x01\x11\x14\x06#\"'%.\x015\x114632\x17\x01\x16\x17\t\x02\x11\x14\x06\"'%\x01\x14\x00\a\t\x01632\x17\x01\x16\x02U\x19\x18\x11\x10\xfe/\x15\x1d\x14\x13\x0e\x1e\x01\xff\x03@\x02\x16\xfd\xea\x04k\x1c0\x17\xfeG\x02\x19\xfd\xff,\xfez\x01D\x11#\x0e\f\x02\x1d\x04\x04[\xfbk\x19#\b\xe9\n/\x17\x04t\x14\x1c\x0f\xff\x00\x03g\xfc\x9e\x01\n\x02F\xfb\xe2\x19\x1f\r\xdc\x03\xe5\x03\xfc\xbfG\x02z\x02\x0f\x1c\x06\xfe\xf2\x02\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\v\x00\x0f\x00\x00\t\x01#\x03\x06\a'\x03#\x01\x113\x01\x11!\x11\x03)\x01\np\x9d\x18\x14*\x9bx\x01\ae\x02\xd7\xfa\x00\x02\x14\x01\xf3\xfe\xc80,\\\x018\xfe\x13\xfe\xbc\x04\xaa\xfa\x00\x06\x00\x00\x00\x18\x00T\xff\x06\b\xa4\x05\xff\x00\v\x00\x17\x00#\x00/\x00D\x00M\x00\xfc\x01\x06\x01\x12\x01\x1b\x01%\x012\x01<\x01G\x01Q\x01^\x01l\x01w\x01\xb3\x01\xc2\x01\xd9\x01\xe9\x01\xfe\x02\r\x00\x00\x05\x0e\x01\a\x06&'&676\x16\x05\x1e\x01\x17\x16676&'&\x067\x1e\x01\x17\x16654&'&\x06\x05\x0e\x01\a\x06&54676\x16\x013\"\a\x1e\x01\x15\x14\x06#\"'\x06\x15\x14\x163264&7.\x01\a>\x02\x1e\x01\x01\x16\a\x16\x15\x16\x0e\x01\a\x06&'\x04%\x0e\x01'.\x01767&76\x1767&76\x1767476\x176\x17\x16\x175\"'.\x01'&767>\x02\x16\x173\x16\x17\x16\x17>\x017&'&'47.\x01'.\x017676\x16\x17\x14\x1e\x03\x17\x16767&\a76767.\x04'$\x01\x16\x17\x1673>\x03?\x01>\x01\x17\x16\x17\x16\x06\a\x0e\x01\a\x15\x06\a\x06\a\x1e\x01\x1767673>\x01\x1e\x01\x17\x16\x17\x16\a\x0e\x01\a\x06#\x14\a676\x176\x17\x16\x15\x16\x176\x17\x16\a\x16\x176\x01\x14\a\x16\x176&'&\x06\a\x1e\x01\a6767.\x01'\x06\a\"'\x16\x17276&\x0567&54&\a\x0e\x01\x17\x16\x17&671&'\x0e\x01\a\x16\x1767\x06\x0f\x015\x06\x17\x16\x05\x1e\x01\x17\x1e\x017>\x017&\x00\"\x06\x15\x14\x162654\x03&\a5\x06\x16\x17\x1e\x017>\x01&\x05>\x01&'5\x06#\x0e\x01\x16\x17\x1e\x01%\x06\x16\x17\x1667>\x017\x06\a\x16\a\x16\x04\x176$7&74>\x01=\x01\x15.\x01'\x06\a\x06'&'&'\x0e\b#\x06'\x0e\x03\a\x06#\x06'\x06'&'&'&'\x06\a\x16\x0365.\x01'&\x0e\x01\x17\x1e\x01\x17\x1667\x16\x1767.\x01'\x06\a\x14\x06\x15\x16\a\x06\a\x06\a#\x06\x17\x16\x17\x04%&'\x06\a\x06'&'\x06\a#\x152%6767\a65&'&'&7&5&'\x06\a\x16\x056.\x01\a\x0e\x01\a\x14\x17\x1e\x017>\x01\x01\xde\b&\x12\x195\x02\x01R\x1b\x17\x16\x054\a&\x13\x195\x01\x02S\x1b\x16\x169\rW\"-J\x870(/\xfar\rV\"-J\x870(.\x02\xc9\x01)#\x1b\"6&4\x1c\x05pOPpp\xe0c\xf3|\x1bo}vQ\x02\xf2\b\x13\a\x01[\x8060X\x16\xfdQ\xfd\xc4\x17W1V\xbb\x01\x02\x05\x13\b\x06\x19\x0e\x1b\a\t\v\x1c\x1d\x1e\r\x17\x1c#\x1a\x12\x14\v\a5X\v\t\t\x0fN\x02\"&\x1c\x05\r.\x0e\x03\x02\n)\n\x0f\x0f\x17D\x01>q\x1c \x15\b\x10J\x17:\x03\x03\x02\x04\a\x05\x1b102(z/=f\x91\x89\x14*4!>\f\x02S\x015b!\x11%\n\x19\x12\x05\x12\x03\x04\x01\x05\x01\v\x06(\x03\x06\x04\x02!\x1f$p8~5\x10\x17\x1d\x01\x1a\x10\x18\x0e\x03\x0e\x02.\x1c\x04\x12.:5I\r\b\x0f\r\b\x0e\x03~\xfe\xf7T\x8a\n\x13\x03\x0e\x18\x0f\x0e\x0e\x1c\x18\x114~9p# !\x02\n\x02)\x05\f\x01\x05\x01\x05\x03\x12\x05\x12\x18\b&\x11 ?()5F\t\x021\x18\x0f\x04\a\x05\x1c\f\t\x1c\x10\x12\r\t\n\x1c\x1e\x15\b\x03\xaf\x1d\x19 d%{\x1d\x13\x04v*\x85:\r \x0e\x0e@e\x10\x0f\n\x01s|\x03D\x861d \x19\x1d\x12\x04\x13\x1d{\x8b\x1f\x0e:\x85*\x06\x0f\x10dA\x11A|o\x04\x0e\x13\x01Yk\x03'&\x8d\x13\x12\a\b\x14\x83<\x02\x02\x83\xa5tu\xa5\xa5ut\xfe&\x02\x02\x01\x1bv\a\x0e\x01\v\x03HC\xba\x04XX\x13\x01\x03\x14TR\x05\x0f\x02\xc8;w\x19\b\x06\x12\x10\x94\x1d\x02\x82\x17\r\x8d\xc671\u0099\r\x15\x02\x03\x03\x01\x01\x01\x02\a\x01Z*&'\x06\b\r1\x05\b\x06\x05\x03\x02\x02\x01\x01\t\x14\x11\x13\v\x03\x02\x01\x119?\t\b.\r\r\x1d$\x06\x04\x02\xfd\x84\x0e\x10Gv\v\f5k65P\x02\x02<\xdc?8q=4\x88a\x04\t\x01\x06\x02\x12\x13\x17\v\r\vSC\"\xcd\x15\x15\x931#\x16\x03\x03\x15\x1c<\x80\x01/6B&!\x01ML\b\x11\t\x18\x14\x12\x04\x05\x04\b\xbe^;\x8c6k5\f\vwF\x10\x0e1<\x02\x02P\x00\x00\x03\x00\x00\xffC\t\x01\x05\xbd\x00\a\x00\x0f\x00;\x00\x00$\x14\x06\"&462\x04\x14\x06\"&462\x01\x1e\x05\f\x0132\x1e\x04\x0e\x03\a\x06\a>\x05.\x03\a\x06$.\a\x05\xf4`\x88aa\x88\xfdsa\x88``\x88\xfdZ9k\x87\x89\xc3\xcd\x01'\x019؋ӗa-\x03*Gl|M\xb9e\x1d_]`F&\fO\x9a\xfe\xb1\xa8\xfe\xdcܽ\x82sDD!/+\x88``\x88aa\x88``\x88a\x051\x0154&'\"&#!\x11!26\x13\x11\x14\x06#!\"&5\x11463!2\x16\a\x9f\x1f\x17\b\n\x99\x99\n\b\x17\r\x1e\x17\x03\f\x8b\x8b\x03\v\x01\x17\xfbi\xe4LCly5\x88)*\x01H\x02\xcacelzzlec0h\x1c\x1c\u007f\xb7b,,b\xb7\u007fe\x03IVB9@RB\x03\x12\x05\xfe9\x01\xebJ_\x80L4\xf8\x004LL4\b\x004L\x0244%\x05\x02\x8c\x02\x05\xaf2\"\x04\x01\x81\x01\x04\xe0\x014\xfe\xcc:I;p\x0f\x10\x01\x01!q4\a\bb\xbab\b\a3p\f\x0f\x02\x02\x06(P`t`P(\x06\x04\x8e6E\x05\x03\bC.7B\x03\x01\xfe\x02I\x036\xfb\x004LL4\x05\x004LL\x00\x00\x05\x00\x00\xff\x80\t\x00\x05\x80\x00\x05\x00\v\x00\x1a\x00.\x00>\x00\x00\x01\x11\x0e\x01\x14\x16$4&'\x116\x00\x10\x02\x04#\".\x0254\x12$ \x04\x014.\x02#!\"\x04\x02\x15\x14\x12\x043!2>\x02\x01\x11\x14\x06#!\"&5\x11463!2\x16\x03Zj\x84\x84\x02b\x84jj\x01[\x9d\xfe\xf2\x9fwٝ]\x9d\x01\x0e\x01>\x01\x0e\x02\x1co\xb8\xf3\x83\xfeӰ\xfeٯ\xae\x01*\xae\x01-\x81\xf5\xb8o\x01XL4\xf8\x004LL4\b\x004L\x01'\x02\xb5)\xbd꽽\xea\xbd)\xfdJ)\x01\xd1\xfe\xc2\xfe\xf2\x9d]\x9d\xd9w\x9f\x01\x0e\x9d\x9d\xfeL\x8b\xf5\xa6`\xa2\xfeֺ\xab\xfe۪e\xa9\xec\x03\x06\xfb\x004LL4\x05\x004LL\x00\x00\x00\x03\x00\x00\xff\x00\a\x00\x06\x00\x00\x0f\x00\x1f\x00;\x00\x00\x05\x114&#!\"\x06\x15\x11\x14\x163!26\x13\x11\x14\x06#!\"&5\x11463!2\x16\x01\x15#54&#!\"\x06\x15\x11\x14\x16;\x01\x15#\"&5\x11463!2\x16\x06\x80\x13\r\xfb\xc0\r\x13\x13\r\x04@\r\x13\x80^B\xfb\xc0B^^B\x04@B^\xfe\x80\x80\x13\r\xfb\xc0\r\x13\x13\r\xa0\xa0B^^B\x04@B^`\x04@\r\x13\x13\r\xfb\xc0\r\x13\x13\x04M\xfb\xc0B^^B\x04@B^^\x01>\xa0\xa0\r\x13\x13\r\xfb\xc0\r\x13\x80^B\x04@B^^\x00\x00\x06\x00\x00\xff\x00\b\x80\x06\x00\x00\x02\x00\x05\x005\x00=\x00U\x00m\x00\x00\t\x01!\t\x01!\x01\x0e\x01\a\x11!2\x16\x1d\x01\x14\x06#!\"&=\x01463!\x11.\x01'!\"&=\x01463!>\x012\x16\x17!2\x16\x1d\x01\x14\x06#\x04264&\"\x06\x14\x01\x14\x0e\x02\".\x0254>\x03762\x17\x1e\x04\x05\x14\x0e\x02\".\x0254>\x03762\x17\x1e\x04\x06\xc0\xfe\x80\x03\x00\xf9\x80\xfe\x80\x03\x00\x01\xb5\x0e?(\x02`\x0e\x12\x12\x0e\xfa\xc0\x0e\x12\x12\x0e\x02`(?\x0e\xfe\x15\x0e\x12\x12\x0e\x01\xeb\x15b|b\x15\x01\xeb\x0e\x12\x12\x0e\xfd?B//B/\x04\x90]\x8e\x93\x84\x93\x8e]Frdh\x04\x12L\x12\x04hdrF\xfb\x00]\x8e\x93\x84\x93\x8e]Frdh\x04\x12L\x12\x04hdrF\x04@\xfd@\x02\xc0\xfd@\x03\x80(?\x0e\xfa\xf5\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x05\v\x0e?(\x12\x0e@\x0e\x129GG9\x12\x0e@\x0e\x12\x10/B//B\xfcaItB!!BtI\v\x8cѶ\xba\a!!\a\xba\xb6ь\vItB!!BtI\v\x8cѶ\xba\a!!\a\xba\xb6ь\x00\x00\x02\x00\x00\xff\x00\x06\x00\x06\x00\x00-\x00M\x00\x00\x01\x10\x02\a\x16\x12\x1132\x16\x1d\x01\x14\x06#!\"&=\x0146;\x01\x10\x127&\x02\x11#\"&=\x01463!2\x16\x1d\x01\x14\x06#\x01>\x035!\x14\x1e\x02\x17\x1e\x01\x14\x06\a\x0e\x03\x15!4.\x02'.\x0146\x05\x80\u0560\xa0\xd5`\x0e\x12\x12\x0e\xfa@\x0e\x12\x12\x0e`\u0560\xa0\xd5`\x0e\x12\x12\x0e\x05\xc0\x0e\x12\x12\x0e\xfd\x8aM\x90sF\xfc\x00Fs\x90M\x13\x17\x17\x13M\x90sF\x04\x00Fs\x90M\x13\x17\x17\x05\x80\xfe\xfb\xfeojj\xfeo\xfe\xfb\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x01\x05\x01\x91jj\x01\x91\x01\x05\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\xfd<\x1d\u007f\xb2\xf2\x84\x84\xf2\xb2\u007f\x1d\a!(!\a\x1d\u007f\xb2\xf2\x84\x84\xf2\xb2\u007f\x1d\a!(!\x00\x00\x03\x00\x00\xff\x00\x06\x00\x06\x00\x00-\x003\x00?\x00\x00\x01\x10\x02\a\x16\x12\x1132\x16\x1d\x01\x14\x06#!\"&=\x0146;\x01\x10\x127&\x02\x11#\"&=\x01463!2\x16\x1d\x01\x14\x06+\x01!\x14\x17!6\x114.\x02'#\x0e\x03\x15\x05\x80\u0560\xa0\xd5`\x0e\x12\x12\x0e\xfa@\x0e\x12\x12\x0e`\u0560\xa0\xd5`\x0e\x12\x12\x0e\x05\xc0\x0e\x12\x12\x0e\xe0\xfc\x00\t\x03\xee\tDq\x8cL\xe6L\x8cqD\x05\x80\xfe\xfb\xfeojj\xfeo\xfe\xfb\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x01\x05\x01\x91jj\x01\x91\x01\x05\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12B>=\xfaC\x82\xef\xb1\u007f\x1f\x1f\u007f\xb1\xef\x82\x00\x00\x00\x00\x03\x00\x00\xff\x00\x06\x00\x06\x00\x00-\x003\x00;\x00\x00\x01\x10\x02\a\x16\x12\x1132\x16\x1d\x01\x14\x06#!\"&=\x0146;\x01\x10\x127&\x02\x11#\"&=\x01463!2\x16\x1d\x01\x14\x06+\x01!\x14\x17!6\x03.\x01'#\x0e\x01\a\x05\x80\u0560\xa0\xd5`\x0e\x12\x12\x0e\xfa@\x0e\x12\x12\x0e`\u0560\xa0\xd5`\x0e\x12\x12\x0e\x05\xc0\x0e\x12\x12\x0e\xe0\xfc\x00U\x03VU96\xb7g\xe6g\xb76\x05\x80\xfe\xfb\xfeojj\xfeo\xfe\xfb\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x01\x05\x01\x91jj\x01\x91\x01\x05\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12β\xb2\xfc\x0e\x8d\xc9**ɍ\x00\x00\x02\x00\x00\xff\x00\x06\x00\x06\x00\x00-\x00G\x00\x00\x01\x10\x02\a\x16\x12\x1132\x16\x1d\x01\x14\x06#!\"&=\x0146;\x01\x10\x127&\x02\x11#\"&=\x01463!2\x16\x1d\x01\x14\x06#\x01>\x035!\x14\x1e\x02\x17\x1e\x01\x14\x06\a\x06\a!&'.\x0146\x05\x80\u0560\xa0\xd5`\x0e\x12\x12\x0e\xfa@\x0e\x12\x12\x0e`\u0560\xa0\xd5`\x0e\x12\x12\x0e\x05\xc0\x0e\x12\x12\x0e\xfd\x8aM\x90sF\xfc\x00Fs\x90M\x13\x17\x17\x13\x89k\x02\xbck\x89\x13\x17\x17\x05\x80\xfe\xfb\xfeojj\xfeo\xfe\xfb\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x01\x05\x01\x91jj\x01\x91\x01\x05\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\xfd<\x1d\u007f\xb2\xf2\x84\x84\xf2\xb2\u007f\x1d\a!(!\a3\x91\x913\a!(!\x00\x00\x00\x03\x00\x00\xff\x00\x06\x00\x06\x00\x00\x0f\x009\x00I\x00\x00\x052\x16\x1d\x01\x14\x06#!\"&=\x014637>\b7.\b'!\x0e\b\a\x1e\b\x17\x132\x16\x1d\x01\x14\x06#!\"&=\x01463\x05\xe0\x0e\x12\x12\x0e\xfa@\x0e\x12\x12\x0eb\x03\x1a\":1P4Y,++,Y4P1:\"\x1a\x03\x04\xfc\x03\x1a\":1P4Y,++,Y4P1:\"\x1a\x03b\x0e\x12\x12\x0e\xfa@\x0e\x12\x12\x0e@\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12@7hVX@K-A\x1e\x1c\x1c\x1eA-K@XVh77hVX@K-A\x1e\x1c\x1c\x1eA-K@XVh7\x06\x00\x12\x0e\x80\x0e\x12\x12\x0e\x80\x0e\x12\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x00\x00A\x00j\x00\x00\x01\"\x06\x1d\x01#54&#\"\x06\x15\x11'54&#\"\x06\x1d\x01\x14\x17\x01\x16\x15\x14\x163!26=\x0147\x136=\x014&#\"\x06\x1d\x01#54&'&#\"\x06\x1d\x01#54&'&'2\x17632\x16\x17632\x16\x1d\x01\x14\a\x03\x06\x15\x14\x06#!\"&5\x01&=\x014632\x17>\x0132\x176\x03\x005K @0.B @0.B#\x016'&\x1a\x02\x80\x1a&\nl\n@0.B 2'\x0e\t.B A2\x05\bTA9B;h\"\x1b d\x8c\rm\x06pP\xfd\x80Tl\xfe\xccL\x8dc\v\x05\x06\x8b_4.H\x04\x80K5\x80]0CB.\xfeS\x1e\xac0CB.\xe0/#\xfe\xd8'?\x1a&&\x1a\x19)$\x01\xb4$)\xf60CB. }(A\b\x02B.\x80z3M\x05\x01\x802\"61\a\x8fd\xf639\xfeL\x18/PpuT\x01(If\xe0c\x8d\x01_\x82\x15E\x00\x00\x00\x00\x02\x00\x00\xff\x00\x06`\x06\x00\x001\x00X\x00\x00\x00\"\x06\x15\x11#\x114&\"\x06\x15\x19\x01'&#\"\x06\x15\x14\x17\x01\x163!267\x1365\x114&\"\x06\x15\x11#\x114&\"\x06\x15\x11#\x114&2\x16\x17632\x16\x1d\x016\x16\x15\x11\x14\a\x03\x0e\x01#!\"&'\x01&54632\x17\x114632\x176\x03\x9e\\B B\\B\x9a&@5K\x1a\x01\x80&@\x02\xb0\"6\aL\x05B\\B B\\B \xb4\x88s\x1f\x13\x17c\x8di\x97\bL\x0e}Q\xfdP\x01\x03%&#\"\x06\x15\x14\x16\x17\x05\x15!\"\x06\x14\x163!754?\x01\x0327%>\x015\x114&#!\a\x06\x15\x11\x14\x1626=\x013\x15\x14\a\x1e\x01\x15\x14\x06\a\x05\x041\xb1\xa3?\x17>I\x05\xfe\xfbj\x96\x96jq,J[\x96j.-\x02t\x01\x91j\x96lV\xfe\xad\\\x8f\x9b\xa3\x1e$B.\x1a\x14\x01R1?\x01@B.\x1a\x14\xfe\xde\x1c\x12+\x10\x10?2\x14\x12\x01`\x1e$\xe8\xfdv\x18\x165K-%\x02\x0e\xfd\x805KK5\x02\x17\xe9.olRI\x01S+6K5\xfë$B\\B 94E.&\xfeʀ\x8d15\x05\x1euE&\n\x96Ԗ\x11\x1c\x83Pj\x96\x11\xef\x96j\xfddX\x8b\x15U\x17\x02\xc7GJ\x0e7!.B\n\x9a\nP2\xff\x00.B\n\x84\r\b\x1a\x15%\x162@\t\xa0\x0e7\x03\x11\xf8\bK5(B\x0e\xc8@KjKj\xc6?+f\xfc\x00\x13U\vE,\x02\x9c5K~!1\xfe\xd8.>F.\xd0\xd0F,\bQ5*H\x11\x8d\x00\x00\x00\x00\x02\x00\x00\xff\x00\b\x00\x06\x00\x00$\x00b\x00\x00\x012\x16\x17\x01\x16\x15\x11\x14\x06#!\"&=\x01%!\"&=\x01463!7!\"&'&=\x01463\x01\x114'\x01&#!\"\x06\x15\x14\x1e\x01\x17>\x013!\x15!\"\x06\x15\x14\x17\x1e\x013!32\x16\x15\x14\x0f\x01\x0e\x01#!\"\x06\x1d\x01\x14\x163!2\x17\x05\x1e\x01\x1d\x01\x14\x163!26\x04\u007f=n$\x02\x0132\x16\x17\x1b\x01>\x0132\x16\x17\x1e\x01\x15\x14\a\x03>\x0532\x16\x15\x14\x06\a\x01\x06#\x03\"\x06\a\x03#\x03.\x01#\"\x06\x15\x14\x17\x13#\x03.\x01#\"\x06\x15\x14\x17\x13\x1e\x01\x17\x13\x1e\x013!27\x01654&#\"\a\x0554\x1a\x017654&#\"\x06\a\x03#\x13654&\x01\xcbMy\x13e\r\x05t\a|]\x11\x83WS\x82\x14Sg\x14\x82SY\x85\x0e\\x\a{\n7\x160\"1\x19i\x9692\xfe\x05DU1&=\t\xa4\u007f\x91\t=&0@\x03\x84\x1ac\t>&/B\x03t\a\x04\bd\b4!\x02\xb6*\"\x01\xfb8K4+\"\xfe\xcd@H\x03\x04@/'=\tt\x1a\x96\x03?\xff\x00_K\x01\x9193-\x16\x01\xdd\x1b\x1e]\x88\nUlgQ\xfe\xa4\x01\xacQgsW\n\x8a]\x18#\xfe\x00\a+\x10\x1e\v\v\x94i>p&\xfe\x843\x06\x800&\xfdV\x02Z&0B/\x0f\r\xfd\xdd\x01\x98%3B.\x0e\f\xfe\"\x1ct\x1e\xfeo )\x1a\x01{+C4I\x1a\xe6\xe3\x04\x01\f\x01(\r\x12\v/D0&\xfe\x1e\x02p\x0e\x0e0D\x00\x05\x00\x00\xff\x00\x06\x80\x06\x00\x003\x00[\x00_\x00c\x00g\x00\x00\x01\"\x06\x15\x19\x01'&#\"\x06\x15\x14\x17\x01\x163!267\x136=\x014&\"\x06\x15#54&#\"\x06\x1d\x01#54&#\"\x06\x1d\x01#\x114&'2\x16\x1d\x01632\x17632\x17632\x16\x1d\x01\x14\a\x03\x0e\x01#!\"&'\x01&54632\x17\x1146\x13\x11#\x11!\x11#\x11!\x11#\x11\x02\x805K\x97)B4J\x1a\x01\x80&@\x02\xce\x16#\x05\\\x188P8 @0.B J65K J6k\x95\x16\ncJ/4qG\x1b\x1d^\x82\x1c\\\x10hB\xfd2.\xfe\xd81!~K5\x03y\x17?\xa3\xb1^\\\xfe\xadVl\x96j\x01\x91\x02t-.j\x96[J,qj\x96\x96j\xfe\xfb\x05I7$\x1e\xa3\x9b?1\x01R\x14\x1a.B\x87\x10\x10+\x12\x1c\xfe\xde\x14\x1a.B$\x1e\x01`\x12\x142?\x01g\x16\x18\xfdvEo.\xe9\x02\x175KK5\xfd\x80\x02\x0e%-K\xfa\xeb6+\x01SIR[\xfe\xca&.E49 B\\B$\x88\xfe\xcc5K\x00\x00\x00\x00\x02\x00\x00\x00\x00\a\xb4\x04\x00\x00\x19\x00G\x00\x00\x01\x15\x14\x06#!\x11\x14\x06+\x01\"&5\x11!\"&=\x01463!2\x16\x05\x13\x16\a\x06+\x01\"&'\v\x01\x06+\x01\"'\v\x01\x0e\x01+\x01\"'&5\x13>\x01;\x012\x17\x13\x16\x17>\x017\x136;\x012\x16\x03Y\x13\r\xfe\xd6\x12\r\x87\r\x13\xfe\xd7\r\x13\x12\x0e\x03\x19\r\x13\x04\x0eM\x01\t\n\r\x86\f\x12\x01.\xbd\b\x15x\x14\t\xbc-\x01\x12\f\x87\r\n\tN\x01\x12\f\x8e\x14\t\xdc\n\n\x03\r\x04\xdd\t\x14\x8d\r\x12\x03\xe0u\r\x12\xfc\xd4\r\x13\x12\x0e\x03,\x12\ru\x0e\x12\x13\n\xfc?\r\v\n\x11\f\x02L\xfeW\x13\x13\x01\xab\xfd\xb2\f\x11\n\n\x0e\x03\xc1\f\x11\x13\xfd\xf8\x18\x1b\a#\t\x02\b\x13\x11\x00\x00\x00\x00\x04\x00\x00\xff\x00\a\x00\x06\x00\x00\t\x00*\x00:\x00J\x00\x00\x014'&+\x01\x11326\x17\x13\x16\a\x06+\x01\"'\x03#\x11\x14\x06+\x01\"&5\x11463!2\x17\x1e\x01\x15\x14\x06\a\x16\x02 \x04\x06\x02\x10\x12\x16\x04 $6\x12\x10\x02&\x00\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x04\x12UbUI\x06-\xfe\xd4\xfe\xf0\xc5uu\xc5\x01\x10\x01,\x01\x10\xc5uu\xc5\x01ڎ\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x03AX!\x12\xfe\xe7J\xd9\xfe\x8b\x11\x0e\x10\x11\x01m\xfe\xa2\x0e\x12\x12\x0e\x03\xc0\x0e\x12\x18\x1f\x9cf\\\x93$\n\x036u\xc5\xfe\xf0\xfe\xd4\xfe\xf0\xc5uu\xc5\x01\x10\x01,\x01\x10\xc5\xfeK\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x8e\xf0\x00\x00\x04\x00\x00\xff\x00\a\x00\x06\x00\x00-\x00[\x00k\x00{\x00\x00\x01276/\x01&'&\x0f\x01\x0e\x05#\"&54632\x16\x1f\x01\x1676?\x016'.\x04#\"\x06\x15\x14\x16!276/\x01&'&\x0f\x01\x0e\x05#\"&54632\x16\x1f\x01\x1676?\x016'.\x04#\"\x06\x15\x14\x16\x02 \x04\x06\x02\x10\x12\x16\x04 $6\x12\x10\x02&\x00 \x04\x16\x12\x10\x02\x06\x04 $&\x02\x10\x126\x02]\x99h\x0e\v-\x06\x12\x10\v\x04\x04\x0f\x14\x1b\x1e%\x13Lb`J%E\x10\x10\v\x0f\x10\b5\r\x0f\x03\x10,5R-\x94\xc4\xc2\x03\f\x99h\x0e\n-\b\x11\x10\v\x04\x04\x0f\x14\x1b\x1e%\x13Lb`J%E\x10\x10\v\x0f\x10\b5\r\x0f\x03\x10,5R-\x93\xc5\xc2'\xfe\xd4\xfe\xf0\xc5uu\xc5\x01\x10\x01,\x01\x10\xc5uu\xc5\xfd\xa4\x01l\x01L\xf0\x8e\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01/h\x12\x12R\r\x04\x02\r\x03\x04\f\x0f\x0e\f\adMLc\x1c\x0e\x0e\v\x01\x02\fN\x14\x13\x04\x10\x1f\x19\x14\xc1\x90\x92\xbfh\x12\x12R\x0e\x03\x02\r\x03\x04\f\x0f\x0e\f\adMLc\x1c\x0e\x0e\v\x01\x02\fN\x14\x13\x04\x10\x1f\x19\x14\xc1\x90\x92\xbf\x041u\xc5\xfe\xf0\xfe\xd4\xfe\xf0\xc5uu\xc5\x01\x10\x01,\x01\x10\xc5\x01\x15\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x00\x00\x02\x00@\xff\xe0\a\xc0\x05 \x00\v\x00\x17\x00\x00\t\x04\x17\a'\t\x017\t\x03'7\x17\t\x01\a\x01\a\x01\x02\xe0\x01\x80\xfe\x80\xfd`\x02\xa0\xa8`H\xfe \x01\xe0\xc1\xfe\xdf\x02\xa0\x02\xa0\xfd`\xa8`H\x01\xe0\xfe \xc1\x01!`\xfe\x80\x02\xe0\xfe\x80\xfe\x80\x02\xa0\x02\xa0\xa8`H\xfe \xfe \xc1\x01\x1f\x02\xa0\xfd`\xfd`\xa8`H\x01\xe0\x01\xe0\xc1\xfe\xe1`\x01\x80\x00\x00\x00\x00\x03\x00\x00\xff\x00\a\x00\x06\x00\x00\v\x00\x17\x00'\x00\x00%\t\x01\a\x17\a\t\x01\x177'\t\x057'7\t\x01'\a\x00\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x02\xcd\x01\x0f\xfe\xe9X\xc0`\xfe\xe9\x01\x17(W\u007f\xfe:\x03,\x01\xc6\xfe:\xfe\xf1\x01\x17X\xc0`\x01\x17\xfe\xe9(W\x03L\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\xb6\x01\x0f\x01\x17X\xbf`\x01\x17\x01\x17(W\x80\xfe:\xfeB\x01\xc6\x01\xc6\xfe\xf1\xfe\xe9X\xbf`\xfe\xe9\xfe\xe9(X\x01\xf9\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x8e\xf0\x00\n\x00\x00\xff\xdc\t\x00\x05$\x00\v\x00\x13\x00\x1c\x00%\x00/\x009\x00E\x00S\x00[\x00\x80\x00\x00\x01\x14\x06#\"&54632\x16$\x14\x06\"&462\x054&\"\x06\x14\x1626$4&#\"\x06\x14\x162%\x14\x06#\"&462\x16$\x14\x06#\"&4632\x00\x10\x00#\"\x0e\x01\x14\x1e\x0132\x01&! \a2\x1e\x02\x154>\x02\x00\x10\x00 \x00\x10\x00 \x13!\x0e\x01\a\x16\x15\x14\x02\x04#\"&'\x06\a.\x01'\x0e\x01#\"$\x02547.\x01'!6$32\x04\x02\x8b7&'77'&7\x04\x827N77N\xfc'q\xa0qq\xa0q\x04\x81qPOrq\xa0\xfcE\xa3st\xa3\xa4\xe6\xa3\x04\x82\xa3ts\xa3\xa3st\xfc\xdf\xfe\xf1\xbf}\xd4||\xd4}\xbf\x03\xab\xfe\xfe\xd2\xfe\xc1\xfeuԙ[W\x95\xce\x02Q\xfe\xf2\xfe\x82\xfe\xf1\x01\x0f\x01~\x04\x01\u007f,>\tn\x9a\xfe\xf8\x9b\x85\xe8P/R\vU P酛\xfe\xf8\x9an\t>,\x01m\x95\x01\x9c\xe2\xe0\x01\x8a\x02\x1b'77'&77\x02N77N6^Orq\xa0qq\x01\xa0qq\xa0q\xc0t\xa3\xa4棣\x01棣\xe6\xa3\xfe(\x01~\x01\x0f|\xd5\xfa\xd5|\x04\von[\x9a\xd4usј^\xfd\a\x01~\x01\x0f\xfe\xf1\xfe\x82\xfe\xf1\x04\x043\u007f3\x97\xba\x9c\xfe\xf8\x99pc8{\x16y%cq\x99\x01\b\x9c\xba\x973\u007f3dqp\x00\x03\x00f\xff\x00\x04\x9a\x06\x00\x00\t\x00\x13\x00L\x00\x00\x00 \x0054\x00 \x00\x15\x14\x00\"\x06\x15\x14\x162654\x01\x1e\x01\x0e\x02\a\x06\a\x17\x01\x16\x14\x0f\x01\x06\"'&'\x01\x06\"/\x01&47\x017&'.\x0367>\x02\x16\x17\x1e\x04326?\x01>\x01\x1e\x01\x03<\xfe\x88\xfe\xf6\x01\n\x01x\x01\n\xfe\x96\xb8\x83\x83\xb8\x83\x01,\r\x04\r(-'s\xc8I\x01\v\x1e\x1e\f\x1fV\x1fC\xc8\xfe\xf5\x1fV\x1e\f\x1f\x1f\x01\vH\xcbr'-(\r\x04\r\n$0@!\x05\x14BHp9[\xa6%&!@0$\x02u\x01\n\xbb\xbc\x01\n\xfe\xf6\xbc\xbb\x01\x9b\x83]\\\x83\x83\\]\xfd\xa7\x1b-$)!\x19I\x15H\xfe\xf5\x1fV\x1e\r\x1e\x1eD\xc8\xfe\xf4\x1e\x1e\r\x1eV\x1f\x01\vH\x15I\x19!)$-\x1b\x14\x1e\x0e\x12\x1a\x04\x0e#\x1a\x163\x19\x19\x1a\x12\x0e\x1e\x00\x04\x00\x00\xff\x80\x06\x00\x05\x80\x00\a\x006\x00>\x00N\x00\x00\x00\x14\x06\"&462\x01.\x01\x06\a\x0e\x02\"&/\x01.\x01\x06\a\x06\x16\x17\x16\x17\a\x06\a\x06\x14\x1f\x01\x162?\x01\x16\x17\x162?\x0164/\x0267>\x01\x02\x10& \x06\x10\x16 \x01\x11\x14\x06#!\"&5\x11463!2\x16\x03\x9f]\x84]]\x84\x013\n$;\x1f\n&|\x82v\x1b\x1b\x1f;$\n\x16(CS\x8f3\x8e1\x16\x16\t\x16=\x16\xbfrM\x16=\x16\t\x16\x16\xbf4\x8dTC(G\xbe\xfe\xf4\xbe\xbe\x01\f\x02z\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x03\xfe\x84]]\x84]\xfd\xf6\x14\x18\x05\x19\b\x18($\x12\x12\x19\x05\x18\x14-;,5\x0e4\x8e0\x16=\x16\t\x16\x16\xbfsL\x16\x16\t\x16=\x16\xbe4\x0e5,;\x01\x12\x01\f\xbe\xbe\xfe\xf4\xbe\x01\xe8\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x02\x00\x00\xff\x80\x06\xb8\x05\x80\x00\x12\x00(\x00\x00\x012\x16\x15\x11\x14\x02\x06\x04#\"$&\x025\x11463\x0127\x01654&#\"\a\t\x01&#\"\x06\x15\x14\x17\x01\x16\x06\x1dAZ\x88\xe5\xfe\xc1\xaf\xb0\xfe\xc1\xe6\x88\\@\x02\xc1/#\x01\x94%E1/#\xfe\xbd\xfe\xbd#.1E$\x01\x95!\x05\x80[A\xfd\xf9\xb0\xfe\xc0懇\xe6\x01@\xb0\x02\a@\\\xfb\xd8!\x01\x84#21E!\xfe\xca\x016!E13\"\xfe|!\x00\x00\x00\x01\x00\x00\xff\x98\t\x00\x05g\x00L\x00\x00\x05\x01\x06\x00\a\x06&5&\x00'.\x02#4&5!\x15\x0e\x02\x17\x16\x00\x176\x127&\x02'&'5\x05\x15\x0e\x01\x17\x1e\x01\x17676&'6452>\x013\x15\x0e\x01\a\x03\x16\x12\x17\x01.\x02'5\x05\x17\a\x06\a\x00\a\x05\xd6\xfe\xd9\x19\xfe\xf5A\x015R\xfe\xa5V\x15[t,\x01\x02G'Q4\x10\x1a\x01}-\x1f\xda\x16\x13\xd6\x1d&\xa3\x02\x01r!\xd5\r\xe5\a\x01\xb9\x0eG;\x1a\x01\xcc\x01\x01\x8b>\xfd\xf2!g\x02\xb71\xfd\xff\x85\x01\x01\x01\xc1\x03\x14\xca2sV\x05&\b2\x02\x1c:#;\xfc\x90d=\x01\x9b*'\x01\xe45E\x022\x01/\x02..F\xefD֕71\x02\a$\x06\x01\x011\x02>2\xfeF!\xfd\xfe\x11\x03\xf9&1\x0e\x012\x04\x02,\x04\x8d\xfb@K\x00\x05\x00\x00\xff\x00\a\x00\x06\x00\x00\n\x00\x18\x00r\x00\x82\x00\x92\x00\x00\x01\x14\x06#\"&5462\x16\x17\x01\x0e\x04\a\x01>\x04%\x14\a.\x02#\"\x15\x14\x17\x0e\x01\a'&#\"\x06\x1f\x01\x06#\"'>\x0254#\"\x0e\x01\a.\x01'7654&\x0f\x01&547\x1e\x023254&/\x01>\x017\x17\x16326/\x01632\x17\x06\x15\x14327\x1e\x01\x17\a\x06\x15\x14\x16?\x01\x1e\x01\x10\x02&$ \x04\x06\x02\x10\x12\x16\x04 $6\x12\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x03\xb5!\x19\x1a&\"2&\x0f\x01^\tu\x86\x8b_\x03\xfe\xa3\ax\x84\x8c^\x02\x8ah\x03\x1c\x19\x04\r;J݃\x10\x01\x0e\x05\x06\x01\x10HJǭ\x01\x18\x13\r\x06\x16\x17\x02q\x9e\x1fE\n\v\x05D\x0em\x02!\x1b\x04\r\x19\x14\x14M\xe0\x84\x0f\x02\r\x05\x06\x01\x0fG?̯'\f\v%o\x99\x1f8\n\v\x049\x0eU\u007f\xd6\xfe\xd8\xfe\xba\xfe\xd8\xd6\u007f\u007f\xd6\x01(\x01F\x01(\xd6ߎ\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x02\x83\x1a&!\x19\x1a&!S\x02E\bm|\x82[\x06\xfd\xbc\an{\x83[<ɪ\x02\x12\x0f\r\n\"p\x9d C\n\v\x04D\x0fi\x02%\x1e\x04\r\x1d(\x03K\xe1\x84\x0f\x03\f\x05\x06\x01\x0fHCέ\x01\x16\x10\f\x06\x13\f\fp\x9a\x1eC\n\v\x05B\rm8\t\r@Kނ\f\x02\x0e\x05\x06\x01\rH\xe7\x01F\x01(\xd6\u007f\u007f\xd6\xfe\xd8\xfe\xba\xfe\xd8\xd6\u007f\u007f\xd6\x02\x81\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x8e\xf0\x00\x00\x04\x00\x00\xff\x01\a\x00\x06\x00\x00\v\x00\x16\x00\"\x00*\x00\x00\x016\x17\x16\x17%&\x04\a\x016$\t\x01\x16\x047\x03&$\x025\x10%\x16\x12\x02\x06\a\x06%\x016\x02'$2\x16\x14\x06\"&4\x03}\xf0\xd3\xe8x\xfd\x1a\xa0\xfe\xf43\xfe\xec\x80\x01n\xfd\xdd\x01QH\x01\x16\x9a\xe6\xd4\xfe\xa6\xc7\x06\xc4:\x03dΏ\xe6\xfe\xf4\x01\x95X\ve\xfe8\xfa\xb1\xb1\xfa\xb1\x06\x00\x02z\x86\xee'\t\xa7\x92\x01\xa8\x9f\xad\xfel\xfdi\x8f\x94\x1d\xfe=!\xf9\x01\u007f\xdc\x01\v7\x96\xfe\xbf\xfe\xdd\xfdS\x85\x0e\x02o\x83\x01?v\x06\xb1\xfa\xb1\xb1\xfa\x00\x00\x01\x00\x02\xff\x00\a\x00\x05\xc9\x00M\x00\x00\x01 \x00'&\x02\x1a\x017\x03>\x01\x17>\x017\x0e\x01\x17\x1e\x03\x17\x16\x06\a\x0e\x02\a\x17'\x06\x1e\x027>\x02\x17\x1e\x01\a\x0e\x04'\x0e\x01'\x1e\x01>\x0276.\x01'\x1e\x01\x176\x02'\x04\x00\x13\x16\x02\x0e\x01\x04\x03\x87\xfe\xe5\xfeEl:\x12F\x98g\v\vr\r*\xedt6\x83\a\x19K3U\b\x0f\v\x19\x05\x17Z8\x0f\x8b\x12\x153P)3^I%=9\t\x01\x03\x0e\x16)\x1a<\xa9}J\xb1\xa0\x95k\x1b+\bC-Wd\x1b\x0f\x91\x89\x01\t\x01&\x04\x02U\xa2\xd8\xfe\xe9\xff\x00\x01-\xf8\x83\x01T\x01E\x01+]\xfe\xe7\x0e\x03\x11Qr\x02-\xcf<\b\v\x04\x04\x01\x05Q#\a\x170\n\xbdC+M8\x1b\a\t3'\x02\x04:$\x02\a\x12\r\b\x03_Q\v=+\x1fIf5[ˮ&&SG\xaa\x01ZoM\xfek\xfe\xc5\u007f\xff\x00ܬc\x00\x00\x00\x02\x00\x00\xff\x00\a\x00\x06\x00\x00#\x007\x00\x00\x01&#\"\x04\a\x0e\x01\a\x15\x1e\x01\x17\x16\x04327\x06\x04#\"'&$&\x0254\x126$;\x01\x16\x04\x01\x14\x02\a\x06#\"'6\x1254\x02'632\x17\x16\x12\x05ե\u009b\xfe\xecfKY\x04\x04YKf\x01\x14\x9b¥y\xfeͩ\x1d\x0e\xaf\xfe\xc4䆎\xf0\x01L\xb6\x03\xa8\x011\x01\xa4\x9a\x88hv\x89v\x9a\xc7ƚw\x87wk\x87\x97\x05\x1cn\x92\u007f]\xfa\x8d*\x8d\xfa]\u007f\x92nlx\x01\b\x94\xee\x01D\xb1\xb6\x01L\xf0\x8e\x01w\xfc\xf8\xc0\xfe\xab~?T8\x01b\xe4\xe3\x01b9SA}\xfe\xac\x00\x00\x00\x04\x00\x00\xff\x10\a\x00\x05\xf0\x00+\x005\x00?\x00F\x00\x00\x01\x14\a!\x14\x163267!\x0e\x01\x04#\"'\x06#\"\x114767\x12%\x06\x03\x12\x00!2\x17$32\x1e\x02\x15\x14\a\x16\x034&#\"\a\x1e\x01\x176\x01\x14\x16327.\x01'\x06\x01!.\x01#\"\x06\a\x00\a\xfb\x81۔c\xad2\x01\xa78\xe5\xfeΨ\xbb\xa9\xe4\xa6\xed-\x11\\\xc7\x01\x14\xb8\xf3?\x01\xb9\x01\x19\x1e\x0f\x00\xff\xb2@hU0KeFjTl\x92y\xcbE3\xf9\xc6aVs\x97z\xb7.b\x01\xf8\x02\xd8\x05؏\x90\xd7\x02W80\x92\xc5]T\x9f\xf4\x85St\x01\as\xa0<\xa9\x01h\xf6O\xfe\xed\x01\x12\x01_\x01u\x1a7bBt\xaa\xb6\x01\xb0SbF/\xa9o\x87\xfb|V]SHކ\xcd\x02J\x8e\xbe\xbe\x00\x00\x00\x00\x02\x00\x00\xff\x80\a\x80\x05\x80\x00\x0f\x003\x00\x00\x01\x114&#!\"\x06\x15\x11\x14\x163!26\x13\x11\x14\x06#!\x15!2\x16\x1d\x01\x14\x06#!\"&=\x01463!5!\"&5\x11463!2\x16\a\x00\x13\r\xf9\xc0\r\x13\x13\r\x06@\r\x13\x80^B\xfd \x01`\x0e\x12\x12\x0e\xfc\xc0\x0e\x12\x12\x0e\x01`\xfd B^^B\x06@B^\x01 \x03\xc0\r\x13\x13\r\xfc@\r\x13\x13\x03\xcd\xfc@B^\x80\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x80^B\x03\xc0B^^\x00\x00\x00\x00\x02\x00\x16\xff\x80\x06\xea\x05\x80\x00\x17\x00>\x00\x00\x133\x06\a\x0e\x03\x1e\x01\x17\x16\x17\x16\x17\x16\x17!\"&5\x1146)\x012\x16\x15\x11\x14\x06+\x016\x03\x05\x0e\x03\a\x06'.\x02'.\x0167>\x0176\x1e\x03\x17%&\x8a\xc5F8$.\x0e\x03\x18\x12\x13\x04\x023\x1e9_\xfe\xf00DD\x04\xe8\x0140DD0\xb2\xd4\x10\xfe+\x02\x14*M7{L *=\"#\x15\n\x12\x14U<-M93#\x11\x01\xd4D\x05\x80@U8v\x85k\x9d_Y\x13\t\xee[\xabhD0\x05\x180DD0\xfa\xe80D\xd2\x01ce-JF1\f\x1aB\x1bD\xbe\xa3\xa3\xc8N&)@\r\f\v\x17/1 d\xaf\x00\x00\x00\x00\x04\x00\x0e\xff\x00\x05y\x06\x00\x00%\x00F\x00\xab\x00\xc5\x00\x00\x05\a\x06\a\x06#\"'&'&'&'&76\x17\x16\x15\x16\x17\x16\x17\x16\x17\x163276?\x016\x17\x16\x17\x16\x01\a\x17\x16\a\x06#\"/\x01\a\x06#\"/\x01&54?\x01'&7632\x1f\x0176\x17\x16\x05\x14\a\x06\a\x0e\x01\"&'&'&5#&76\x17\x16\x173\x11567632\x16\x15\x14\x06#\"'&76\x1f\x01\x1e\x0132654'&#\"\a\x06\x15\x11\x1632>\x0254'&#\"\a\x06\x0f\x01\x0e\x02'.\x015\x11463!2\x14#!\x113>\x017632\x16\x17\x16\x17\x16\x03\x16\x14\x06\a\x06#\"'&'&#\"\a\x06'&767632\x17\x16\x05y\x06q\x92\x9a\xa3\xa5\x98\x94oq>*\f\x0443\x05\x01\x12\x1c2fb\x80\x84\x90\x8f\x85\x80a\x06\n\x0f\f\x15$\xfe\x15B?\x15\x1c\x11\x0f\n\t>B\x05\n\x0f\x10\x02\x12\bBB\x10\x1e\x12\r\x06\aAA\x12\x1e\x1b\x01\xc7.-QP\xd6\xf2\xd6PR+\x0f\x01\t42\n%<\x01\x03ci\x94\x93\xd0ђ:6\x1c\x0f\x10\x1c\x0e\x0e&\vh\x90HGhkG@n\x84`\xb2\x86I\x8d\x8c\xc7Ȍ5\x18\x02\b\n!\x16\x15\x1f\x15\x11\x03m\x1e\x1e\xfc\xd5\x01(|.mzy\xd6PQ-.\x1f\t\v\v\x1a\r\t\aje\x80\x94\x85\x81\x1b\x12\t\x01\x03\r\x82\xa9\xa4\x98\x89\v\x06q>@@?pp\x92gV\x1c\b\b\x1c\x01\x03ZE|fb6887a\x06\n\x04\x03\x13%\x02RB?\x15\x1c\x11\n=B\x05\x10\x02\x0f\x0e\a\nAB\x10\x1d\x12\x05BA\x11\x1e\x1bJvniQP\\\\PRh!\a\x1b\x11\x10\x1ccD\x01S\x02\x88`gΒ\x93\xd0\x10\v23\b\x03\x03\x06\x8fgeFGPHX\xfecCI\x86\xb0_ƍ\x8c\x8c5\"\x02\v\t\n\b\x05\x17\x0f\x02\xa8\x0f\x17n\xfe\x1d*T\x13.\\PQip\x01\xd0\b\x14\x10\r\x1a\a[*81\n/\x19\r\x10\x049@:\x00\x00\x04\x00\x1d\xff\x00\x06\xe1\x06\x00\x00\x1b\x00>\x00t\x00\x82\x00\x00%6\x16\x14\a\x0e\x04#\".\x03'.\x01>\x01\x16\x17\x16\x17\x04%6%\x16\x06\a\x06\a\x06&7>\x01'.\x03\x0e\x02#\x0e\x03*\x02.\x01'&676\x16\x01\x14\x1e\x02\x1f\x01\a.\x01/\x01&'\x0e\x03.\x0254>\x05754'&#\"\x0e\x03\a%4>\x0332\x1e\x03\x15\x01\x14\x17\x167676=\x01\x0e\x03\x06\x0f\x0f\x16\x0f\r>\x81\x99\xdfvw\ued25d\"\b\x04\x06\n\r\x05\xc0l\x01\x85\x01\x9a\xbe\x01\x98\v\x11\x14\"3\x11\x12\t\x15/\x11\x05\x15!\x1a,\x13+\x01\x06\x0e\b\t\x05\x06\x03\x03\x01\x01\x06j2.|\xfe\x84\x1b%&\x0e\r\xe3(N\x13\x13\v\x0e&w\x88\x90\x83h>8X}x\x8cc2\x15\"W\x06\x15<4<\x12\xfe\xda,Z~\xb1fd\xa2aA\x19\xfd`FBIT\x1e\x0e;hmA<\x06\x06\x1d\x13\x107QC1>[u])\t\x0f\t\x05\x01\x04u1\xb0V(\xd2\x10k1S)\x0e\n\x13-\x99\x16\a\t\x03\x02\x02\x02\x04\x01\x01\x01\x01\x01\x02\x02\x100\x06\a\f\x01\xa9\x1fB2*\v\v\xe0%M\x14\x14\v\x16;W(\x060S\x8f[T\x8c]I)\x1c\t\x02\u007fA 5\x02\x16%R7\x1b&\x1a\x80\x1a&T\x01\xa8\x01,\xfe\xd4\xfeX\xfe\xd4\x02\x00\x0e\x12\x12\x0e\x92\xce\x12\x1c\x12\xa9\x01\xc0\x0f\xfdq\x1a&&\x1a\x02\x8f\x041\xfe\xd4\xfeX\xfe\xd4\x01,\x01\xa8L\x12\x1c\x12Β\x0e\x12\x12\x0ew\xa9\x00\x00\x00\x00\x03\x00%\xff\x00\x06\xdb\x06\x00\x00\x1b\x00%\x00;\x00\x00\x01\x16\x14\x0f\x01\x06#!\"&5\x11463!546;\x012\x16\x1d\x01!2\x17\x01!\x11\x14\x06+\x01\"&5\x012\x16\x15\x11\x14\x06#!\"/\x01&4?\x0163!5!\x15\x06\xd1\n\n\x8d\x1c(\xfa\xc0\x1a&&\x1a\x02@&\x1a\x80\x1a&\x02\x00(\x1c\xfc\xbc\x01\x00&\x1a\x80\x1a&\x03@\x1a&&\x1a\xfa\xc0(\x1c\x8d\n\n\x8d\x1c(\x02\x00\x01\x00\x04\xd7\n\x1a\n\x8d\x1c&\x1a\x01\x00\x1a&@\x1a&&\x1a@\x1c\xfb\xdc\xfe\x00\x1a&&\x1a\x03\xc0&\x1a\xff\x00\x1a&\x1c\x8d\n\x1a\n\x8d\x1c\xc0\xc0\x00\x04\x00\x00\xff\x00\b\x00\x05\xfb\x00\x1b\x00\x1f\x00#\x00'\x00\x00\x01\x16\x15\x11\x14\x06\a\x01\x06'%\x05\x06#\"'&5\x11467\x016\x17\x05%6\x05\x11\x05\x11%\x11%\x11\x01\x11\x05\x11\a\xe4\x1c\x16\x12\xfd\x80\x18\x18\xfd\x98\xfd\x98\n\x0e\x13\x11\x1c\x16\x12\x02\x80\x18\x18\x02h\x02h \xfb\x18\x02@\xfb`\x02 \x04\xe0\xfd\xe0\x05\xf5\x14!\xfa\x80\x14 \a\xff\x00\v\v\xf6\xf6\x05\v\x14!\x05\x80\x14 \a\x01\x00\v\v\xf6\xf6\r\x9a\xfb\n\xe6\x04\xf6\r\xfb\n\xd9\x04\xf6\xfa\xfd\x04\xf6\xd9\xfb\n\x00\x00\x03\x00\x00\xff\x00\a\x00\x06\x00\x00\x11\x00#\x005\x00\x00\x012\x16\x15\x11\x14\a\x01\x06#\"&5\x1147\x016!2\x16\x15\x11\x14\a\x01\x06#\"&5\x1147\x016!2\x17\x01\x16\x15\x11\x14\x06#\"'\x01&5\x1146\x02\x00\r\x13\x11\xfe \a\b\r\x13\x11\x01\xe0\a\x04\xe8\r\x13\x11\xfe \a\b\r\x13\x11\x01\xe0\a\xfb\xa8\b\x06\x02\x00\x12\x13\r\b\x06\xfe\x00\x12\x13\x06\x00\x13\r\xfa@\x14\b\xff\x00\x04\x13\r\x05\xc0\x14\b\x01\x00\x04\x13\r\xfa@\x14\b\xff\x00\x04\x13\r\x05\xc0\x14\b\x01\x00\x04\x03\xff\x00\n\x13\xfa@\r\x13\x03\x01\x00\n\x13\x05\xc0\r\x13\x00\x00\x00\x00\x04\x00\x00\xff \a\x00\x05\x00\x00\a\x00\x0f\x00\x17\x008\x00\x00\x004&\"\x06\x14\x162$4&\"\x06\x14\x162$4&\"\x06\x14\x162\x00\x10\x02\x04#\"'\x06\x05\x06\a\x06&'&7>\a7.\x0154\x12$ \x04\x02\x80KjKKj\x01\xcbKjKKj\x01\xcbKjKKj\x01\xcb\xf0\xfed\xf4ne\xad\xfe\xfa4\"\f\x14\x03\x04\x18\x05%\x0e!\x0f\x1a\x0e\x0f\x05\x92\xa7\xf0\x01\x9c\x01\xe8\x01\x9c\x02KjKKjKKjKKjKKjKKjK\x01.\xfe\xa4\xfe٫\x12\xad8\n\x03\x01\x0e\v\x0f\x16\x05!\x0e%\x1a00C'Z\xfd\x8f\xae\x01'\xab\xab\x00\x00\x00\x00\x05\x00\x00\xff\x00\a\x00\x05\x00\x00\a\x00\x0f\x00\x17\x00.\x00W\x00\x00\x00\x14\x06\"&462\x04\x14\x06\"&462\x04\x14\x06\"&462\x02 \x04\x06\x15\x14\x16\x1f\x01\a\x06\a6?\x01\x17\x1632$6\x10&\x01\x14\x02\x04#\"'\x06\x05\x06\a#\"&'5&6&>\x027>\x057&\x0254>\x01$ \x04\x1e\x01\x02\x80KjKKj\x01\xcbKjKKj\x01\xcbKjKKj\xe9\xfeh\xfe\x9dя\x82W\x1b\x18.\x98{+9E=\xcc\x01c\xd1\xd1\x01Q\xf0\xfed\xf4FK\xc6\xfe\xfa1A\x05\x0f\x18\x04\x03\x05\x01\n\x02\f\x02\a0\x15)\x18\x1e\v\x9d\xb5\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x02\xb5jKKjKKjKKjKKjKKjK\x01\x80\x8b\xec\x89p\xcbJ2`[Q?l&\x06\b\x8b\xec\x01\x12\xec\xfe\x8b\xae\xfe٫\b\xafC\x0e\b\x15\x11\x01\x04\x10\x04\x0f\x03\x0e\x02\b5\x178.H(Y\x01\x06\x96\x82\xed\xacee\xac\xed\x00\x04\x00\x00\xff\t\x04\x00\x05\xf7\x00\x03\x00\x06\x00\n\x00\r\x00\x00\t\x01\x11\t\x01\x11\x01\x19\x01\x01\x11\t\x01\x11\x02\x00\x02\x00\xfe\x00\xfe\x00\x02\x00\xfe\x00\x02\x00\x02\x00\x01Y\x01'\xfd\xb1\xfe\xd8\x03w\xfd\xb1\x01(\x04\x9e\xfd\xb1\xfe\xd8\x02O\xfe\xd9\x01'\xfd\xb1\x00\x00\x00\x01\x00R\xff\xc0\x06\xad\x05@\x00$\x00\x00\x01\x06\x01\x00#\"\x03&\x03\x02#\"\a'>\x017676\x16\x17\x12\x17\x16327676#\"\a\x12\x05\x16\x06\xad\n\xfe\xbe\xfe\xb3\xe5\x8eb,XHU\x12mM\x18\xa8.\x9cU_t\x17,\x167A3ge\b\rz9@x\x01S\xfb\x03\xfa\xec\xfea\xfeQ\x01\a\xa0\x01B\x01\x06Lb\x15\x97(\x8a\b\t\x81\x8b\xfe\xe1V\xf9\xa1\xa1U\x8b\x1a\x01\x89\v\b\x00\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x03\x00\n\x00\x00\x11!\x11!\x01\x03\x13!\x13\x03\x01\x06\x00\xfa\x00\x04=\xdd\xdd\xfd\x86\xdd\xdd\x01=\x05\x80\xfa\x00\x01\xa5\x02w\x01)\xfe\xd7\xfd\x89\xfe\xd0\x00\x00\x00\x00\x04\x00\x00\xff\x80\x06\x00\x05\x80\x00\x03\x00\x12\x00A\x00U\x00\x00\x11!\x11!\x01\a\x17\a\x177\x177'7'#'#\a\x052\x16\a74.\x02#\"\x06\x1d\x01#\x1532\x15\x11\x14\x06\x0f\x01\x15!5'.\x02>\x015\x1137#\"76=\x014>\x02\x015'.\x01465\x11!\a\x17\x16\x15\x11\x14\x06\x0f\x01\x15\x06\x00\xfa\x00\x03\x8c\fK\x1f\x19kk\x19\x1fK\f_5 5\xfe\x96 \x19\x01\xae#BH1\x85\x84`L\x14\n\rI\x01\xc0\x95\x06\x05\x02\x01\x01\xbf&\xe7\x06\x04\x04\x03\f\x1b\x02v6\a\x05\x02\xfe\xed\x17S\x17\f\x0eF\x05\x80\xfa\x00\x04\xc0!Sr\x1999\x19rS!``\xa3 /\x157K%\x0es}H\x80\b\xfe\x82\x0e\f\x01\aXV\x0e\x01\x01\x04\x04\n\x05\x01\x83\x80\x06\x06\x03P\x1b\x1b\x1d\v\xfc\xc3V\t\x01\x03\x03\f\x06\x02\be\x16\a\x14\xfe\x8e\x0e\t\x02\tV\x00\x00\x04\x00\x00\xffd\a\x00\x06\x00\x00/\x009\x00Q\x00[\x00\x00\x01\x14\x06\a\x16\x15\x14\x02\x04 $\x02547.\x0154632\x176%\x13>\x01\x17\x05>\x0132\x16\x14\x06\"&5%\x03\x04\x17632\x16\x01\x14\x16264&#\"\x06\x0164'&\"\a\x0e\x01\"&'&\"\a\x06\x14\x17\x1e\x022>\x01&2654&#\"\x06\x14\a\x00;2\f\xd5\xfe\x90\xfeP\xfe\x91\xd5\v3>tSU<\xda\x01)t\x03\x18\x0e\x01q\x12H+>XX|W\xfe\xb2h\x01,\xdb:USt\xfa\xa2W|XX>=X\x03*\v\v\n\x1e\v)\xa0\xa0\xa0)\v\x1e\n\v\v+\x97^X^\x97\x16|WX=>X\x02\xb2:_\x19.2\x9b\xfe\xf8\x99\x99\x01\b\x9b//\x19a:Ru?\x98\n\x02\t\r\x10\x03Q%-W|XW>J\xfe(\t\x97=u\xfe\xe7>XX|WX\xfe`\v\x1e\v\n\n*((*\n\n\n\x1f\v+2\t\t2\xf8X>=XW|\x00\x00\x00\x01\x00E\xff\x02\x06\xbb\x06\x00\x000\x00\x00\x133>\x03$32\x04\x17\x16\x1d\x01!\x1e\x03>\x017\x11\x06\f\x01'&\x02'&\x127\x0e\x01\a!6.\x04/\x01\x0e\x03E\x01\x10U\x91\xbe\x01\x01\x94\xe7\x01noh\xfb\x9b\x01i\xa8\xd3\xd7\xc9I\\\xfe\xed\xfe\xa2\x8d\xbd\xf5\x02\x03\xe4\xd30<\x10\x02{\b >ORD\x16\x16\x87\xf9ƚ\x02\xe5~\xe7˕V\xd3ƻ\xff\xbco\xa3R \x1aC3\xfe\x877J\x026I\x01`\xc4\xf2\x01Tb<\x83^M~M8\x1a\x0f\x01\x01\x05O\x82\x97\x00\x00\x00\x04\x00\x00\xff\x80\t\x00\x05\x80\x00\t\x00\r\x00\x11\x00\x1b\x00\x005\x11!\x11\x14\x06#!\"&\x01\x15!5!\x15!5\x012\x16\x1d\x01!5463\t\x00^B\xf8@B^\x02\x80\x01\x80\xfd\x00\x01\x00\x06`B^\xf7\x00^B \x02`\xfd\xa0B^^\x01\"\x80\x80\x80\x80\x04\x80^B\xe0\xe0B^\x00\x00\x00\x03\x00\x00\xff\x00\x06\xbb\x06\x00\x00\x1f\x000\x00;\x00\x00%'\x0e\x01#\".\x0154>\x0232\x16\x177&$#\"\x04\x06\x02\x10\x12\x16\x0432$\t\x01\x06\x00!\"$&\x02\x10\x126$3 \x00\x17\x03#\x15#\x1132\x1e\x01\x0e\x01\x060\xdaJ\xf5\x8d\x93\xf8\x90U\x91\xc7n\x83\xe9L\xd7n\xfe\x9fʡ\xfe\xda\xd4~~\xd4\x01&\xa1\xd5\x01q\xfe@\x02\xb5t\xfeK\xfe\xee\xb6\xfe\xb4\xf0\x8e\x8e\xf0\x01L\xb6\x01\x04\x01\xa5}\x9f'`\x88 -\f\n-\xf6ox\x8a\x90\xf8\x92nǑUyl}\xa9\xc0~\xd4\xfe\xda\xfe\xbe\xfe\xda\xd4~\xd6\x02F\xfe\xa0\xfd\xfeڎ\xf0\x01L\x01l\x01L\xf0\x8e\xfe\xf5\xe9\xfet\xa0\x01`(88(\x00\x04\x00 \xff\x00\x06\xe0\x06\x00\x00\x03\x00\a\x00\v\x00\x0f\x00\x00\t\x017!\x01'\x11\x01\x1f\x01\x11\t\x02!\x01\x05\x93\xfd\x9a\\\x03W\xfa\xb5\xb8\x04\x9f\x14\x93\xfd\xec\x01\\\xfe\f\xfc\xa9\x01d\x03;\x01\x82\x97\xfc\xdet\x03Z\xfd\x19`_\xfc\xa6\x01O\x02\u007f\xfc\xde\x02;\x00\x00\x03\x00\x00\xff\x00\x06\x80\x05\xf0\x00\v\x00\x17\x00}\x00\x00\x0154+\x01\"\x1d\x01\x14;\x012%54+\x01\"\x1d\x01\x14;\x012\x05\x11!\x114&\"\x06\x15\x11!\x114;\x012\x1d\x013\x114;\x012\x1d\x01354;\x012\x1d\x01354>\x02\x163\x11&5462\x16\x15\x14\a\x15632\x1632632\x1d\x01\x14\x06#\"&#\"\a\x1526\x1e\x02\x1d\x01354;\x012\x1d\x01354;\x012\x15\x11354;\x012\x02\x80\x10`\x10\x10`\x10\x02\x00\x10`\x10\x10`\x10\x02\x00\xfd\x80p\xa0p\xfd\x80\x10`\x10\x80\x10`\x10\x80\x10`\x10\x80\x05\f\a\x10\x01 !,! -&\x15M\x10\x11<\a\x10F\x1b\x12I\x13(2\x01\x10\a\f\x05\x80\x10`\x10\x80\x10`\x10\x80\x10`\x10\x02\x10\xe0\x10\x10\xe0\x10\x10\xe0\x10\x10\xe0\x10\x10\xfd\x10\x01@PppP\xfe\xc0\x02\xf0\x10\x10p\x02p\x10\x10pp\x10\x10pp\x06\a\x03\x01\x01\x01\x87\x0f#\x17 \x17#\x0f\x11\n\x0f\x0f\x10\xd2\x0f\r\x0f\f\x85\x01\x01\x03\a\x06pp\x10\x10pp\x10\x10\xfd\x90p\x10\x00\x01\x00\x00\x00\x00\t\x00\x05\x80\x00j\x00\x00\x01\x16\x14\a\x05\x06#\"'&=\x01!\x16\x17\x1e\x05;\x015463!2\x16\x15\x11\x14\x06#!\"&=\x01#\".\x05'.\x03#!\x0e\x01#\"&4632\x16\x1732>\x027>\x06;\x01>\x0132\x16\x14\x06#\"&'#\"\x0e\x04\a\x06\a!546\x17\b\xf0\x10\x10\xfe\xc0\b\b\t\a\x10\xfc\xa6%.\x10\x11\x1f\x17\x1f \x11`\x12\x0e\x01@\x0e\x12\x12\x0e\xfe\xc0\x0e\x12` :,.\x1c'\x12\x13\x17\x1c,-\x18\xfe\x98\x16\x8aXj\x96\x96jX\x8a\x16h\x18-,\x1c\x17\x13\x12'\x1c.,: k\x15b>PppP>b\x15k\x11 \x1f\x17\x1f\x11\x10.%\x04Z \x10\x02\xdb\b&\b\xc0\x05\x04\n\x12\x80:k%$> $\x10`\x0e\x12\x12\x0e\xfe\xc0\x0e\x12\x12\x0e`\x14\x1b6&L')59I\"Tl\x96ԖlT\"I95)'L&6\x1b\x149Gp\xa0pG9\x10$ >$%k:\x80\x12\x14\v\x00\x00\x00\x00\x03\x00\x00\xff\x00\a\x00\x06\x00\x00\a\x00\x11\x00!\x00\x00\x00\x14\x06+\x01\x1132\x00\x10&#!\x113\x1132\x00\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x04~O8\xfd\xfd8\x01\x02\xb7\x83\xfeO\xb4\xfd\x82\x02\x87\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x03>pN\x01\r\xfe\xf7\x01\x04\xb8\xfc\x80\x01\r\x01i\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x8e\xf0\x00\x04\x00\x00\xff\xd9\t\x00\x05'\x00'\x00:\x00M\x00a\x00\x00\x014&'\x06\a\x0e\x01#\"'.\x017654.\x01#\"\x06\a\x16\x17\x16\x14\x06\"'&#\"\x06\x14\x163!267\x14\x06#!\"&54676$32\x00\x17\x1e\x01\x17\x14\a\x06#\"'.\x0176\x10'&>\x01\x16\x17\x16$\x10\a\x06#\"'.\x017654'&676\x16\x17\x06mD5\a\x10\a)\x18\f\f\x1f\x1c\n\x17z\xd2{\x86\xe26lP\x16,@\x17Kij\x96\x96j\x04\x16Oo\x99Ɏ\xfb\xea\xa9\xf0ȕ>\x01>\xc3\xeb\x01[\x17t\x99\xfaa\x17)\x18\x13\x1a\f\x12GG\x12\f4?\x12a\x01\x00\x86\x17)\x17\x13\x1a\r\x12ll\x12\r\x1a\x1a>\x12\x01\xb6;_\x15-/\x18\x1c\x03\n9\x1eGH{\xd1z\x92y\x1cN\x17@,\x16K\x95ԕoN\x8e\xc8繁\xe4\x16\xb8\xe4\xfe\xc3\xe7\x19\xbby\xaf\x90!\r\x11?\x1ah\x01\x02h\x1a>$\r\x1a\x8eD\xfe\x18\xc7\"\r\x12>\x1a\xa4\xc2â\x1a?\x11\x12\f\x1b\x00\x02\x00$\xff\x00\x05\xdc\x06\x00\x00\t\x00n\x00\x00\x05\x14\x06\"&5462\x16'\x0e\x01\x15\x14\x17\x06#\".\x0554>\x032\x1e\x03\x15\x14\a\x1e\x01\x1f\x012654.\x04'&'.\x0354>\x0332\x1e\x03\x15\x14\x0e\x03#\"#*\x01.\x045.\x01/\x01\"\x0e\x01\x15\x14\x1e\x03\x17\x1e\b\x05\xdc~\xb4\u007f\u007f\xb4~\xe9s\x9b!\x92\xe9m\xb8{b6#\f\t\x1c-SjR,\x1b\b\x17\x1cl'(s\x96\x12-6^]I\x1c\x0ft\x8eg))[\x86\xc7zxȁZ&\x1e+6,\x11\x02\x06\x13\x1a4$.\x1c\x14\x0fX%%Dc*\n&D~WL}]I0\"\x13\n\x02\rY\u007f\u007fYZ\u007f\u007f\xbf\x0f\xafvJ@N*CVTR3\x0e\x13/A3$#/;'\x0e\"/\x1b\x1e\x02\x01fR\x1a-,&2-\"\r\a7Zr\x89^N\x90\x83a94Rji3.I+\x1d\n\n\x12&6W6\x10\x13\x01\x01>N%\x18&60;\x1d\x1996@7F6I3\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x1f\x00+\x00\x00\x01\x114&#!\"\x06\x15\x11\x14\x163!26%\x114&#!\"\x06\x15\x11\x14\x163!26\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x02\xc0\x12\x0e\xff\x00\x0e\x12\x12\x0e\x01\x00\x0e\x12\x01\xc0\x12\x0e\xff\x00\x0e\x12\x12\x0e\x01\x00\x0e\x12\x01\x80\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01`\x02@\x0e\x12\x12\x0e\xfd\xc0\x0e\x12\x12\x0e\x02@\x0e\x12\x12\x0e\xfd\xc0\x0e\x12\x12\x01\xff\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x04\x00\x00\xff\x80\x06\x00\x05\x80\x00\v\x00\x17\x00'\x007\x00\x00\x00 \x04\x12\x10\x02\x04 $\x02\x10\x12\x00 >\x01\x10.\x01 \x0e\x01\x10\x16%\"&5\x1146;\x012\x16\x15\x11\x14\x06#!\"&5\x1146;\x012\x16\x15\x11\x14\x06#\x02/\x01\xa2\x01a\xce\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01\x9e\x01(\xfa\x92\x92\xfa\xfe\xd8\xfa\x92\x92\x01\xee\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x0e\xfd\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x0e\x05\x80\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xfb\xae\x92\xfa\x01(\xfa\x92\x92\xfa\xfe\xd8\xfaN\x12\x0e\x02@\x0e\x12\x12\x0e\xfd\xc0\x0e\x12\x12\x0e\x02@\x0e\x12\x12\x0e\xfd\xc0\x0e\x12\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00\x1b\x00\x00\x01\x114&#!\"\x06\x15\x11\x14\x163!26\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04@\x12\x0e\xfd\xc0\x0e\x12\x12\x0e\x02@\x0e\x12\x01\xc0\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01`\x02@\x0e\x12\x12\x0e\xfd\xc0\x0e\x12\x12\x01\xff\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\v\x00\x17\x00'\x00\x00\x00 \x04\x12\x10\x02\x04 $\x02\x10\x12\x00 >\x01\x10.\x01 \x0e\x01\x10\x167\"&5\x11463!2\x16\x15\x11\x14\x06#\x02/\x01\xa2\x01a\xce\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01\x9e\x01(\xfa\x92\x92\xfa\xfe\xd8\xfa\x92\x92n\x0e\x12\x12\x0e\x02@\x0e\x12\x12\x0e\x05\x80\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xfb\xae\x92\xfa\x01(\xfa\x92\x92\xfa\xfe\xd8\xfaN\x12\x0e\x02@\x0e\x12\x12\x0e\xfd\xc0\x0e\x12\x00\x00\x00\x00\x03\x00\x00\xff\x00\a\x00\x06\x00\x00\v\x00%\x00=\x00\x00%\x13\x16\a\x06#!\"'&7\x13\x01\x13!\x13>\x013!\x15\x14\x1626=\x01!\x15\x14\x1626=\x01!2\x16%\x11\x14\x06\"&5\x114&\"\x06\x15\x11\x14\x06\"&5\x1146 \x16\x06\xdd#\x03\x13\x13\x1d\xf9\x80\x1d\x13\x13\x03#\x06]V\xf9TV\x03$\x19\x01\x00KjK\x01\x80KjK\x01\x00\x19$\xfe\x83&4&\x96Ԗ&4&\xe1\x01>\xe1\x80\xfe\xc7\x1c\x16\x15\x15\x16\x1c\x019\x03G\xfc\xf9\x03\a\x18!\x805KK5\x80\x805KK5\x80!\xa1\xff\x00\x1a&&\x1a\x01\x00j\x96\x96j\xff\x00\x1a&&\x1a\x01\x00\x9f\xe1\xe1\x00\x06\x00\x00\xff\x00\b\x00\x06\x00\x00\x15\x00#\x00/\x00;\x00I\x00m\x00\x00\x012\x16\x14\x06+\x01\x03\x0e\x01#!\"&'\x03#\"&463\x01>\x01'\x03.\x01\x0e\x01\x17\x13\x1e\x013%\x114&\"\x06\x15\x11\x14\x1626%\x114&\"\x06\x15\x11\x14\x1626%\x136.\x01\x06\a\x03\x06\x16\x17326\x01\x03#\x13>\x01;\x01463!2\x16\x1532\x16\x17\x13#\x03.\x01+\x01\x14\x06#!\"&5#\"\x06\a\x805KK5\x0fs\bH.\xfb\x00.H\bs\x0f5KK5\x01e\x1a#\x02 \x02)4#\x02 \x02%\x19\x01\xa0&4&&4&\x01\x80&4&&4&\x01` \x02#4)\x02 \x02#\x1a\x05\x19%\xfb~]\x84e\x13\x8cZ\xa7&\x1a\x01\x80\x1a&\xa7Z\x8c\x13e\x84]\vE-\xa7&\x1a\xfe\x80\x1a&\xa7-E\x03\x00KjK\xfdj.<<.\x02\x96KjK\xfc\xe0\x02)\x1a\x01\xa0\x1a#\x04)\x1a\xfe`\x19\"@\x01\xa0\x1a&&\x1a\xfe`\x1a&&\x1a\x01\xa0\x1a&&\x1a\xfe`\x1a&&\x15\x01\xa0\x1a)\x04#\x1a\xfe`\x1a)\x02\"\x04\xda\xfed\x01\xb9Xo\x1a&&\x1aoX\xfeG\x01\x9c,8\x1a&&\x1a8\x00\x02\x00!\xff\x80\x06\xdf\x05\x80\x00\x03\x00O\x00\x00\x01\x13#\x03\x01\a\x06#!\x03!2\x17\x16\x0f\x01\x06#!\x03\x06+\x01\"'&7\x13#\x03\x06+\x01\"'&7\x13!\"'&?\x0163!\x13!\"'&?\x0163!\x136;\x012\x17\x16\a\x033\x136;\x012\x17\x16\a\x03!2\x17\x16\x03\xdf@\xfe@\x03\xfe8\a\x18\xfe\xb9@\x017\x0f\n\n\x048\x05\x1a\xfe\xb9Q\a\x18\xe0\x10\n\t\x03N\xfeQ\a\x18\xe1\x0f\n\t\x03N\xfe\xc9\x0f\n\t\x038\a\x18\x01G@\xfe\xc9\x0f\n\n\x048\x05\x1a\x01GQ\a\x19\xe0\x0f\n\t\x03N\xfeQ\a\x19\xe0\x0f\n\t\x03N\x017\x0f\n\t\x02\x00\x01\x00\xff\x00\x01\xf8\xe0\x18\xff\x00\f\x0e\x0e\xe0\x18\xfe\xb8\x18\f\f\x10\x018\xfe\xb8\x18\f\f\x10\x018\f\f\x10\xe0\x18\x01\x00\f\x0e\x0e\xe0\x18\x01H\x18\f\f\x10\xfe\xc8\x01H\x18\f\f\x10\xfe\xc8\f\f\x00\x00\x00\x00\x04\x00k\xff\x00\x05\x95\x06\x00\x00\x02\x00\x05\x00\x11\x00%\x00\x00\x01\x17\a\x11\x17\a\x03\t\x03\x11\x03\a\t\x01\x17\x01\x00\x10\x02\x0e\x02\".\x02\x02\x10\x12>\x022\x1e\x02\x03I\x94\x95\x95\x94\x83\x01\xd0\xfe\xce\x012\xfe0\xff]\x01@\xfe\xc0]\x00\xff\x02\xcf@o\xaa\xc1\xf6\xc1\xaao@@o\xaa\xc1\xf6\xc1\xaao\x01㔕\x03\x8c\x95\x94\xfca\x01\xd0\x012\x012\x01\xd0\xfd\x9d\x00\xff]\xfe\xbf\xfe\xbf]\x00\xff\x01p\xfe^\xfe\xc7\xc9|11|\xc9\x019\x01\xa2\x019\xc9|11|\xc9\x00\x00\x00\x00\x03\x00(\xff\x00\x03\xd8\x06\x00\x00\x02\x00\x05\x00\x11\x00\x00%7'\x117'\x13\t\x01\x11\x01'\t\x017\x01\x11\x01\x02T\xad\xad\xad\xad \x01d\xfd\xe5\xfe\xd7l\x01t\xfe\x8cl\x01)\x02\x1bq\xac\xac\x01n\xac\xac\xfd\xf1\xfe\x9c\xfd\xe4\x02\xc7\xfe\xd8l\x01u\x01ul\xfe\xd8\x02\xc7\xfd\xe4\x00\x05\x00\x00\xff\x80\x06\x00\x05\x80\x00\a\x00\x0f\x00\x17\x00)\x001\x00\x00$4&\"\x06\x14\x162\x004&\"\x06\x14\x162\x00\x10\x06 &\x106 \x13\x14\a\x01\x06+\x01\"&547\x016;\x012\x16\x04\x10\x06 &\x106 \x05\x00LhLLh\xfdLLhLLh\x04L\xe1\xfe\xc2\xe1\xe1\x01>\x81\r\xfb\xe0\x13 \xa0\x1a&\r\x04 \x13 \xa0\x1a&\xfd`\xe1\xfe\xc2\xe1\xe1\x01>\xcchLLhL\x03LhLLhL\xfe\x1f\xfe\xc2\xe1\xe1\x01>\xe1\x02\xc0\x14\x12\xfa\x80\x1a&\x1a\x14\x12\x05\x80\x1a&\xbb\xfe\xc2\xe1\xe1\x01>\xe1\x00\x00\x00\x05\x00\x03\xffG\x06\xfd\x05\xb9\x00\x06\x00\n\x00\x10\x00\x17\x00\x1d\x00\x00\x13\t\x01.\x017\x13)\x01\x011\x01\x13!\x1362\x01\x13\x16\x06\a\t\x011!\x1362\x17h\x03\x18\xfc\x9c\x12\x0e\ae\x01\xce\x02\x94\xfe\xb6\xfd\xf0\xc6\xfe2\xc6\b2\x050e\a\x0e\x12\xfc\x9c\x03\x18\xfe2\xc6\b2\b\x03>\xfc\t\x02v\r+\x15\x014\xfc\t\x06[\xfd\x9c\x02d\x17\xfd\x85\xfe\xcc\x15+\r\xfd\x8a\x03\xf7\x02d\x17\x17\x00\x00\x00\x04\x00\x00\xff \a\x00\x05\xe0\x00\x03\x00\x0f\x00\x13\x001\x00\x00\x0135#\x015\x06\a\x06&'\x17\x1e\x0172\x01!5!\x05\x14\a\x16\x15\x14\x04#\"&'\x06\"'\x0e\x01#\"$547&54\x12$ \x04\x12\x01\x80\xa0\xa0\x03Eh\x8b\x87\xf9`\x01X\xf8\x94\x81\xfe(\x02\x80\xfd\x80\x04\x80cY\xfe\xfd\xb8z\xce:\x13L\x13:\xcez\xb8\xfe\xfdYc\xf0\x01\x9d\x01\xe6\x01\x9d\xf0\x02\xc0\xe0\xfd\xd4\\$\x02\x01_K`Pa\x01\x01}\xe0\xc0\xbb\xa5f\u007f\x9d\xdeiX\x01\x01Xiޝ\u007ff\xa5\xbb\xd1\x01a\xce\xce\xfe\x9f\x00\x00\x00\x00\t\x00\x00\xff\x80\x06\x00\x05\x80\x00\x03\x00\a\x00\v\x00\x0f\x00\x13\x00(\x00+\x00.\x00>\x00\x00\x01\x15#5\x13\x15#5\x01\x15!5\x01\x15!5\x01\x15!5\x01\x114&+\x01\x01'\a\x01#\"\x06\x15\x11\x14\x163!26\x017!\x057!\x05\x11\x14\x06#!\"&5\x11463!2\x16\x02\x03\xfc\xfc\xfc\x03\xf2\xfe\xab\x01U\xfd`\x02\xa0\xfd`\x03'\f\b \xfe\x86\xd2\xd2\xfe\x86 \b\f\f\b\x04\xd8\b\f\xfc\xa9\xb9\xfej\x02\x8b\xdd\xfej\x02\xe2V>\xfb(>VV>\x04\xd8>V\x02q\x80\x80\x00\xff\u007f\u007f\xfe\x01\x80\x80\x01\x00\x80\x80\x00\xff\u007f\u007f\xfc\xa4\x04\xd8\b\f\xff\x00\xab\xab\x01\x00\f\b\xfb(\b\f\f\x04^\x96\x96\x96\x14\xfb(>VV>\x04\xd8>VV\x00\x00\x00\x02\x00\x00\xff\x00\a\x00\x06\x00\x00\x1f\x00=\x00\x00\x01&'&'&'&\x06\x1f\x01\x1e\x03\x17\x16\x17\x1e\x04\x17\x1676'&'&\x02\x01.\x05\x02' \f\x01\x1e\x03\x0e\x01\a\x06\x15\x01#\x01\x0e\x02.\x02\x03\x80h8\x8b\xd0\"$Y\n''>eX5,\t\x04,Pts\x93K\x99\x01\x0125\x1cM\xcc\xfeRLqS;:.K'\x01\x11\x01\xc1\x015\xe9\x8aR\x1e\x05\x0e\r\r\x01Ch\xfe\xe7\x16\x8bh\xac\x95\xba\x02\xd0\xc4R\xcat\x13\x11(\x10\x1e\x1f+e\x84^T\x11\bT\x8a\xaa\x82u B\x06\x03\"$\x15:\x012\xfe~<\x82\x9d\x98\xdc\xc6\x012\x88Hp\xb1\xa8\xe5\xaa\xe3wTT\x17\xfe\xb9\x01\x1d\x02\x18\x0e\x02 V\x00\x00\x05\x00\x00\xff\x00\a\x00\x06\x00\x00/\x007\x00G\x00W\x00g\x00\x00\x00.\x01\a\x04 %&\x0e\x01\x16\x17\x16\x17\x0e\x02\x0f\x01\x06\x16\x17\x1632?\x01673\x16\x1f\x01\x16327>\x01/\x01.\x02'676$4&\"\x06\x14\x162\x04\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x00 \x04\x06\x02\x10\x12\x16\x04 $6\x12\x10\x02&\x00\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x05d\f-\x1a\xfe\xfb\xfe\xe8\xfe\xfb\x1a-\f\x1b\x1a\xc2m\x02\x1b\x1a\x1c\t\n\x16\x19\t\x0e,\x10\b6\x11*\x116\b\x10,\x0e\t\x19\x16\n\t\x1c\x1a\x1b\x02m\xc2\x1a\xfe\xb7KjKKj\x02\x8bo\xbd\xfe\xfb\xfe\xe2\xfe\xfb\xbdoo\xbd\x01\x05\x01\x1e\x01\x05\xbd\xfeK\xfe\xc8\xfe\xe4\xcezz\xce\x01\x1c\x018\x01\x1c\xcezz\xce\x01Ȏ\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x03U4\x1b\x06>>\x06\x1b4-\x06.\f\x9e\xdeYG\x15\x190\n\x04)\x14\x8bxx\x8b\x14)\x04\n0\x19\x15GYޞ\f.\x06\xa3jKKjKq\xfe\xe2\xfe\xfb\xbdoo\xbd\x01\x05\x01\x1e\x01\x05\xbdoo\xbd\x01lz\xce\xfe\xe4\xfe\xc8\xfe\xe4\xcezz\xce\x01\x1c\x018\x01\x1c\xce\xfe0\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x8e\xf0\x00\x00\x00\x03\x00D\xff\x00\x05\xbb\x06\x00\x00/\x007\x00H\x00\x00\x00\x16\a\x03\x0e\x01#\"'.\x017\x13\a\x16\x15\x14\a'654&#\"\a'67\x01'\a\x06.\x016?\x01>\x01\x17\x01\x16\x17\x16\x0f\x01%\x02\"&462\x16\x14\x0127\x17\x06#\".\x01547\x17\x06\x15\x14\x16\x05|D\x05,\x04=)\x06\x03,9\x03#\x8f7\x94\x89[͑\x86f\x89x\xa4\x01\b\x95\xb5!X:\x05 \xef\x1aD\x1e\x01\xe8$\f\x11+\xcd\x01s)\x94hh\x94i\xfc\xdajZ\x8b\x92\xbd\x94\xfb\x92t\x8b<\xcd\x02\xf6F/\xfd\xd9*8\x01\x03C,\x01\xad\bq\u007f\u061c\x89e\x86\x91\xce\\\x8ar\x1b\x01,W\xa1\x1e\x05BX\x1d\xd5\x17\a\x12\xfe\xe5\x15/C2\xe8\x14\x01\xa9h\x94hh\x94\xfa\xbe=\x8bt\x92\xfa\x94\xbc\x94\x8bXm\x91\xcd\x00\x00\x00\x04\x00\x00\xff\x80\x06\x00\x05\x80\x00\x0f\x00>\x00N\x00Z\x00\x00\x01\x15\x14\x06+\x01\"&=\x0146;\x012\x16\x01\x14\x0e\x02\a\x0e\x02\x1d\x01\x14\x06+\x01\"&=\x014>\x037>\x0154&#\"\a\x06\a\x06#\"/\x01.\x017632\x16\x02 \x0e\x02\x10\x1e\x02 >\x02\x10.\x01\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x03p\x12\x0e\xa0\x0e\x12\x12\x0e\xa0\x0e\x12\x01\x00\x1e=+& \x1d\x17\x12\x0e\xa0\x0e\x12\x15\x1b3\x1f\x1d5,W48'\x1d3\t\x10\v\bl\n\x04\az\xe3\x81\xdb\xee\xfe\xfc\xed\xabff\xab\xed\x01\x04\xed\xabff\xab\x01\x91\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01P\xa0\x0e\x12\x12\x0e\xa0\x0e\x12\x12\x01\xe22P:\x1e\x15\x12\x14\x1c\x0f \x0e\x12\x12\x0eD#;$#\x10\r\x19$\x1f*;\x1b\x14?\f\x06R\a\x1a\n\xc0\xb3\x01Cf\xab\xed\xfe\xfc\xed\xabff\xab\xed\x01\x04\xed\xab\xfe\xb7\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x04\x00'\xff\x03\x05Y\x06\x00\x00\t\x00>\x00O\x00`\x00\x00\x00\"&5462\x16\x15\x14\x01\x14\x06&'\x01.\x01\x0f\x01\x06\x1f\x01\x13\x03\x06\a\x06\a\x06'.\x0176\x1b\x01\a\x17\x16\x0e\x02\x0f\x01\x06.\x035\x03\x13632\x17\x01\x16\x1f\x01\a\x16\x05\x1e\x01\x1f\x01\x16\x17\x16\a\x06.\x01'#&'\x03\x01\x16\x15\x14\a\x06.\x01'&\x01\x166?\x0165\x01\xae\x80\\\\\x80[\x01\x8c(\t\x01\x06\x02|\x03\x93\x1f\x03\t\v\x14\x06r\xfe\xcb\x03\b\x03\x03\v\x04\xc9[A@[[@A\xfd#2#\x16\x17\x01\xb6\f\a\x02\x03\b\r\x8b\xfe\x9e\xfe7\xc0*\x1a\x06\x1a\x19\r<\x1b\x11\x02Y\x01\xa0\xa4\xde\x18$\x13\r\x01\x02\x03\f\x14\x18\x0f\x02\x01+\x01}\"(\xfd\xf7\x05\f\x03\x01\r\xa6q\xe087] F\x1b\x16\f \x13\x10\t\x01_\xfe\xad1\b\x05\x02\x05\v)\n\xac\x01\xe9\x01\x04\x02\x02\t\b\x00\x00\x00\a\x00\x03\x00\xe3\t\x00\x04\x1c\x00\x02\x00\v\x00#\x001\x00K\x00e\x00\u007f\x00\x00\x013\x03\x054&+\x01\x11326\x01\x13\x14\x06+\x01\"&=\x01!\a\x06#!\"&7\x0163!2\x16\x04\x10\x06#!\"&5\x11463!2\x01\x14\x0e\x03\a#>\x03?\x014.\x03'3\x1e\x03\x1f\x01\x14\x0e\x03\a#>\x03?\x014.\x03'3\x1e\x03\x1f\x01\x14\x0e\x03\a#>\x03?\x014.\x03'3\x1e\x03\x17\x01\xf8\xab\x01\x03Xe`64[l\xfd\xc2\x01\x13\x0e\xd8\x0e\x13\xfe\xdd7\n\x12\xfe\xf5\x15\x13\r\x02,\t\x12\x01L\x0e\x14\x03;\xfb\xc7\xfe\xf2\x0e\x14\x14\x0e\x01\f\xc8\x01\x98\x01\x0f\x1c=+3&9\x1a\x10\x01\x01\x01\x0e\x1a8&+)>\x1d\x11\x02\xb9\x01\x0f\x1c>+3&9\x1a\x10\x01\x01\x01\x0e\x198&+)>\x1d\x11\x02\xb6\x01\x0f\x1c=+3&8\x1a\x10\x01\x01\x01\x0e\x198&+)>\x1d\x11\x01\x02\x1e\x01\t\xa6Wj\xfe|r\x01\xca\xfd\f\x0e\x14\x14\x0e>Q\x0f$\x11\x02\xf5\x0e\x14\xc6\xfe~\xdc\x14\x0e\x02\xf4\x0e\x14\xfed\v$kaw+-wi[\x1b\x1b\b\x1d[\\\x83;/xgY\x1a\x1a\v$kaw+-wi[\x1b\x1b\b\x1d[\\\x83;/xgY\x1a\x1a\v$kaw+-wi[\x1b\x1b\b\x1d[\\\x83;/xgY\x1a\x00\x04\x00\x00\xff\x00\x05\x80\x05\xf2\x00J\x00\\\x00m\x00\x82\x00\x00\x054.\x01'.\x02'&#\"\x06#\"'.\x03'&47>\x037632\x16327>\x027>\x0254&'&#\"\a\x0e\x03\a\x06\a\x0e\x01\x10\x16\x17\x16\x17\x16\x17\x16\x17\x16327>\x01\x13\"&47654'&462\x17\x16\x14\a\x06\x16\"'&476\x10'&462\x17\x16\x10\a\x16\"'&47>\x01\x10&'&462\x17\x16\x12\x10\x02\a\x02i\x1a$\x02\x01\b\t\t\x0f$\x17^\x18\"\r\x06\n\x05\b\x01%%\x01\b\x05\n\x06\r\"\x18^\x17$\x0f\t\t\b\x01\x02$\x1aW \x14\x19\"@9O?\x1d\x1f\x06\x031&&18\x1b?t\x03\x03@\"\x19\x14 W\x9f\x1a&\x13%%\x13&4\x13KK\x15\xb86\x12\x13\x13pp\x13&4\x13\x96\x96\xa36\x12\x13\x13ZaaZ\x13&4\x13mttm\x99\v^x\t\x04-\x1b\b\x0e\v\v\x05\x15\x13\x1d\x04\x80\xfe\x80\x04\x1d\x13\x15\x05\v\v\x0e\b\x1b-\x04\tx^\v\x16=\f\b\x12\x11/U7C\f\ak\xda\xfe\xf2\xdakz'[$\x01\x01\x12\b\f=\x03\xa7&5\x13%54'\x134&\x13K\xd4K\x13\xb5\x13\x134\x13r\x01\x027>\x0254\x00 \x00\x15\x14\x06\"&54>\x022\x1e\x02\x04\x14\x06\"&462%\x14\x06\"&54&#\"\x06\x15\x14\x06\"&546 \x16%\x16\x06\a\x06#\"&'&'.\x017>\x01\x17\x16\x05\x16\x06\a\x06#\"'&'.\x017>\x01\x17\x16\x80&4&&4\xe6&4&&4S\x01\x00Z\xff\x00\x01\xad&4&&4\x02\xe9\x174$#\x1f\x1d&\x0f\xe1\x9f\x1a&&\x1aj\x96\x173$\"('$\xfe\xf9\xfe\x8e\xfe\xf9&4&[\x9b\xd5\xea՛[\xfd\xfd&4&&4\x01F&4&\x83]\\\x84&4&\xce\x01$\xce\x01\x8a\n\x16\x19\t\x0e\x13!\aD\x9c\x15\b\x10\x114\x15\xb7\x01%\t\x15\x19\v\f,\x10\\\xcd\x16\a\x10\x104\x15\xeb\xa64&&4&\x9a4&&4&\x01-\xff\x00Z\x01\x00\x874&&4&\x01\x00;cX/)#&>B)\x9f\xe1&4&\x96j9aU0'.4a7\xb9\x01\a\xfe\xf9\xb9\x1a&&\x1au՛[[\x9b\xd5\xdb4&&4&@\x1a&&\x1a]\x83\x83]\x1a&&\x1a\x92\xceΏ\x190\n\x04\x16\x13\xb2u\x104\x15\x15\b\x10\x89\x85\x190\n\x04)\xee\x9b\x104\x15\x16\a\x10\xaf\x00\x00\x00\x00\x04\x00\x03\xff\x00\b\xfd\x06\x00\x00\x11\x00#\x00g\x00\xb0\x00\x00\x01&'.\x01#\"\x06\x15\x14\x1f\x01\x1632676%4/\x01&#\"\x06\a\x06\a\x16\x17\x1e\x01326\x01\x0e\x01'&#\"\a2632\x16\x17\x16\x06\a\x06#2\x17\x1e\x01\a\x0e\x01+\x01&'%\a\x06#\"'\x03&6?\x01\x136\x1276\x1e\x01\x06\a\x06\a676\x16\x17\x16\x06\a\x06\a632\x17\x1e\x01%\x13\x16\x06\x0f\x01\x03\x06\x02\a\x06#\"'&6767\x06\a\x06#\"&'&6767\x06#\"'.\x017>\x01\x17\x16327\"\x06#\"&'&6763\"'.\x017>\x01;\x02\x16\x17\x057632\x04\b;\x19\x11>%5K$\n\"0%>\x11\x19\x02s$\n\"0%>\x11\x19;;\x19\x11>%5K\xfeV\x11L#>H30\x03\r\x03\\\x9d(\x11\x1b$\x12\x15\x15\x12$\x1b\x11(\x9d\\\x06\x10\x1c\xfe\xde\xef\x0e\x0f(\x11\xa0\v\x0e\x16є\x11\x95y\x1fO2\a\x1fF/{\x90(?\x04\x050(TK.5sg$\x1a\x03\xb1\xa0\v\x0e\x16є\x11\x95y\x1a#-\x1d\x19\a\x1fF/{\x90\x04\b$7\x04\x050(TK.5sg$\x1a\x12\x11L#>H30\x03\r\x03\\\x9d(\x11\x1b$\x12\x15\x15\x12$\x1b\x11(\x9d\\\x06\x01\x0e\x1c\x01#\xef\x0e\x0f(\x02@\x025\"'K58!\b\x1f'\"5\x828!\b\x1f'\"5\x02\x025\"'K\x01\x12#\x1a\x11\x1f\x11\x01dS$K\x11\t\t\x11K$Sd\x02\x02\x1bx\a#\x01@\x171\rw\x01\v\x9b\x01\x11d\x19\a>N\x1a;ET\x11\x050((?\x04\n-\n2\x12K|\xfe\xc0\x171\rw\xfe\xf5\x9b\xfe\xefd\x16#\x1fN\x1a;ET\x11\x010$(?\x04\n-\n2\x12K$#\x1a\x11\x1f\x11\x01dS$K\x11\t\t\x11K$Sd\x02\x02\x1bx\a\x00\x00\x00\x04\x00\x00\xff\x00\a\x00\x06\x00\x00\x13\x00D\x00N\x00\\\x00\x00\x01\x14\x162654& \x06\x15\x14\x16265462\x16\x02\"\x0e\x02\x15\x14\x162654\x00 \x00\x15\x14\x0e\x01\a\x0e\x03\x15\x14\x06#\"\x06\x14\x1632654>\x027>\x0354.\x01\x01\x17\x01\x06\"/\x01&47\x01\x17\x16\x14\x0f\x03&'?\x0162\x04 &4&\xce\xfe\xdc\xce&4&\x84\xb8\x84h\xea՛[&4&\x01\a\x01r\x01\a$'(\"$3\x17\x96j\x1a&&\x1a\x9f\xe1\x0f&\x1d\x1f#$4\x17[\x9b\xfd\xc2\xe2\xfd\xbd\f\"\f\xa8\f\f\x06@\xa8\f\f\xe9\x1aGB\x81[\xcf\r\"\x02\xc0\x1a&&\x1a\x92\xceΒ\x1a&&\x1a]\x83\x83\x01\xe3[\x9b\xd5u\x1a&&\x1a\xb9\x01\a\xfe\xf9\xb97a4.'0Ua9j\x96&4&\xe1\x9f)B>&#)/Xc;u՛\xfd\x8c\xe2\xfd\xbd\f\f\xa8\f\"\f\x06\x06\xa8\f\"\r\xe9\x19G\x99i[\xcf\f\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x14\x00X\x00h\x00\x00\x01\x14\a\x0e\x01\a\x0e\x01\a\x06#\"&5467632\x16\x014&'&#\"\a'>\x0154#\"\a\x0e\x02\x15\x14\x1632\x14\a\x06\a\x0e\x01#\"54>\x0354'.\x01#\"\x0e\x01\x15\x14\x1632>\x017>\x01767632\x17\x16326\x13\x11\x14\x06#!\"&5\x11463!2\x16\x03b\r\v)\n\x02\x05\v\x14\v:4FD\x1c\x17\x1c\x11\x01\xe6N\r\x15\r[\x87\x02\x031\xf2\x18,^\x95J\xa1\x93\x19\x01\x04\x16\x0eK-*\x15\x1d\x1e\x16\a\x18E\x1f#9\x19gWR\x92Y\x15\x06\x13\x05\x03\vvm0O\x01\x03\x05\t\xb8\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x03\xfd\x1bC2\xc82\v\x03\x01\x02c@X\xac&\x0e!\xfe9\x0e{\x05\bM\x02\x16\xe2A\xe9\x06\x11\x91\xbc_\x92\x9e\x06\x02\"S4b/\x18/ \x19\x0f\x01\x03\a\x16\x1dDR\"Xlj\x92P\x16Y\x16\f\x06<\x12\x01\t\x02\x0f\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x00\x02\x00%\xff\x00\x05\xda\x05\xff\x00\x19\x00e\x00\x00\x014.\x02#\"\a\x06\x02\x15\x14\x1e\x0232\x16>\x0276\x1276\x01\x14\x06#'.\x02#\"\a\x06\a\x0e\x01\a\x0e\x03#\"&54>\x0132\x16\x17\x14\x0e\x03\x15\x14\x1632>\x03754&*\x01\x06#\"&54>\x02763 \x11\x14\x02\a\x17>\x0132\x17\x1e\x01\x02\xe8\x04\r\x1d\x17''il\x11$E/\x04\x1c\f\x14\n\x02\x10@\x10\x13\x02\xf2\x0f\b\x06\x16P@\x1f\xa7\xb8\x0f\x06\n\x1d\b\x17^\x83\xb2`\x87\x9f'W6&\xa4\x01!.. ! -P5+\x16\x05\a\n\n\n\x01\xe3\xfaE{\xbdn46\x01vL\x05\x03e\xa3V\x16\x1f\x13z\x04\xcf\x18\x1d\x1f\x0f\x17:\xfe\xf7\x89,SN/\x01\x01\x05\f\nM\x015M[\xfd\xa7\a\r\x01\x03\x10\t]\b\x13$\x8b\x1f[\xb1\x98^\xa7\x885\x80iC\x1c\x01\x17'2H&!(?]v`*\t\x02\x03\x01\xf5\xe2l\xe2\u008d\x13\t\xfe\x98b\xfe\xa2$\x039>\r\a\xbf\x00\x03\x00\x01\xff\x00\x06\u007f\x05\xfb\x00=\x00R\x00\x87\x00\x00\x012\x1f\x01\x16\x1f\x01\x16\a\x03\x0e\x01\a\r\x01#\"&5467%!\"&7>\x013-\x01.\x017>\x01;\x01\x05%.\x017>\x0132\x17\x05\x172\x16326/\x01.\x0176\a\x17/\x02\x03.\x01'&676\x16\x1f\x01\x0e\x01\a\x06\x16\x01\x13\x16\x0f\x01\x06\x0f\x016/\x01&/\x01&#\"\a\x03&676\x16\x17\t\x01&676\x16\x17\x13\x03&676\x16\x17\x13\x17\x1e\x016/\x01&672\x16\x03? \x1b\xde=1\x92(\vH\x06/ \xfd\xf1\xfe\xa0\t'96&\x01\x04\xfe@)9\x02\x02<'\x01\xba\xfd\xf7)2\x06\x069%\n\x01\xe1\xfe\xa1&0\x06\x066#\x06\x0e\x01\xc0\xd9\x01\x04\x01\x17\x0f\x14\xba#\x0e\x19\x1b\x15\xba\xda\x05$\xee\x01\x03\x01\x18\v \x1fJ\x1b\x8e\x02\x06\x01 \x12\x03\xa5\x0f\x04\x0f0\f7j\x02)\x925@\xde\"*3%\xeb\x19\x0e\"!M\x18\x01\n\xfe\xfa\x15\x15%#K\x14\xf1\x88\x0f\x15\"%N\x11\xc1e\b\x1e\x18\x01\f\x028)'8\x03_\x12\x94(9\xaa.<\xfec +\x048 8(%6\x05 <)'4\x01@\x05@)#-<^\n?%$-\x02`%\x01.\r}\x17Q!&\xca}%\x02&\x01\x06\x01\x05\x01\x1fN\x19\x17\v\x1c\x93\x01\x05\x02-l\x01\xa7\xfe\xf6IJ\xdb;\x1c6>/\xaa=*\x94\x17%\x018!Q\x17\x16\x10 \xfe\xa0\x01\xc7#P\x13\x12\x18\"\xfe\\\x01Q#N\x11\x13\x1a&\xfea\xc4\x0f\x05\x14\x10\xe0)<\x019\x00\x00\x04\x00\x00\xff\x1e\a\x00\x05b\x00R\x00]\x00m\x00p\x00\x00%\"'.\x01'&54>\x0676%&547632\x1f\x0163 \x00\x17\x16\x14\a\x0e\x01\a\x16\x15\x14\a\x06#\"/\x02\x017\x06\a\x16\x1a\x01\x15\x14\a\x06#\"'\x01\x06\a\x16\x00\x15\x14#\"&/\x01\x03\x06\a\x1e\x01\x17\x13\x14%\x17$\x13\x02%\x1e\x01\x15\x14\x06\x00\x14\x1632\x16\x15\x14\x162654&#\"%'\x17\x01O\x02\x04V\xa59\x15\x04\x04\n\a\x0e\x06\x12\x02\xb8\x01\fn\x11t\f\x12\n|\\d\x01\n\x01ϓ\x14\x14[\xff\x97n\x11t\v\x13\n|@\xfeD\a:)\x03\xf8\xee\t\r;9\x03\xfe8'+\x18\x01|\v\x0e\x89\x04j\xe0,\"\x02 \a\xb0\x0341\x01\x11\xb1\xb4\xfe\xe9CH^\xfen\x1c\x14Vz\x1c(\x1c\xb2~\x14\x01R\t\a\xb4\x029\xb0\\\x1e'\t\x14\x10\x14\f\x16\b\x17\x03\xfbr\xc6\r\x13\n@\x10\xe5\x13\xfe\xed\xe8\x1fL\x1f\x8e\xdf@\xc6\r\x14\t@\x10\xe5w\x034\a\x18\x17\x05\xfe6\xfeH\x03\a\x02\x03\a\x03I\x1c(+\xfdC\x04\n,\x06\xc5\x01\x9d55\x03,\f\xfe\xb9\nf[o\x01\x12\x01\x15p@\xa9\\j\xbd\x02;(\x1czV\x14\x1c\x1c\x14~\xb2\x11\x04\a\x00\x00\x00\x00\x04\x00\x00\xff\x97\x04\xfe\x05i\x00\x1f\x00/\x005\x00O\x00\x00\x01\x14\a\x06#\"'&54>\x0132\x17\x06\a&#\"\x06\x15\x14\x16 654'67\x16'\x14\x02\x0f\x01\"'>\x0454'\x16'\x15&'\x1e\x01\x13\"'6767\x0e\x01\a&546767>\x017\x16\x15\x14\a\x0e\x01\x04\x1a\x93\x94\xe6蒓\x88\xf2\x93`V \aBM\xa7\xe3\xe1\x01R\xe0 B9)̟\x9f\x0e\x1d!S\u007fH-\x0f\x0377I\x85Xm\xfdSM\xdaH\x13\x02*\xc3k#\"\x1a.o;^\x1bJ\x18 q\x01\xaeן\xa1\xa1\x9fד\xf7\x92\x1f>@\x1c\xf6\xa8\xaa\xed\xed\xaaYM\r$bK\xc0\xfe\xced\x01\x05 \x8d\xa8ү[E\"\xa0\xa2\x02\xd6\xe2;\xff\xfe\xb9Kx\u007f%\x13^\x91\x196;%T\x1a,\x1e\x10U:i\x94m=Mk\x00\x00\x00\x05\x00\x00\xff\x80\x06\x00\x05\x80\x00\x1a\x00)\x00.\x00D\x00T\x00\x00\x014'\x06\a\x16\x15\x14\x06\"&54632\x1767&#\"\x06\x10\x16 6\x03\x16\x15\x14\x0e\x03\a\x16;\x016\x114'.\x01'\x16\x054'\x06\a\x0e\x01\x15\x14\x17>\x017\x0e\x01\a\x1632676%\x11\x14\x06#!\"&5\x11463!2\x16\x04\x1a\x1c),\x16\x9a蛜s5-\x04\x17\x0254&#\"\x06#\"'654'.\x01#\"\a\x06\x15\x14\x17\x06#\"&#\"\x06\x15\x14\x1e\x02\x15\x14\a\x06\a\x06\x15\x14\x17\x1e\x0232632\x1e\x0232>\x0232\x1632>\x0176\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x04\xff\x16Cf\x1d\a'/'%\x14\f(\v\x04\b\x05\x11$\x86U\xc7L\x11\x05\x04\n\f(\n\x15#'/'\a@\x86\x16\x89\x02\b\x0f\x10\f3\x0e#@,G)+H+@#\x0e3\r\x10\x0e\b\x02\x89\x01\x01\xce\xfe\x9f\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\x01\x84\x16\x05\x0fX@\x13\x06\x0f\x16\f\x1d\x16\x13\x19\x10\x02_\x13O#NW\xa5#O\x13_\x02\x0f\x18\x14\x15\x1d\f\x16\x0f\x06\x13\x8a\x1d\x05\x16.\x16\x05*\x13\t\x1e#\x1e\x1e#\x1e\b\x14(\x05\x16\x01\xfb\xfe^\xfe\x9f\xce\xce\x01a\x01\xa2\x01a\xce\xce\x00\x00\x01\x00\x0f\xff\x80\x06q\x05\x80\x00[\x00\x00\x016\x16\x17\x16\x15\x14\a\x1632632\x16\x15\x14\x0e\x02\x15\x14\x17\x1e\x01\x17\x16\x17\x16\x15\x14\a\x0e\x02#\"&#\"\a\x0e\x04#\".\x03'&#\"\x06#\".\x01'&54767>\x017654.\x0254632\x16327&547>\x01\x03P\x86\xd59\x1b\t\x0e\x0e\x12B\x12\x1d6?K?\f%\x83O\x1c4\x1c\xdb\a\b\x14\x17\x14T\x16%\x19 >6>Z64Y=6>\x1f\x1a%\x18S\x11\x19\x14\b\a\xdb\x1c4\x1cN\x85$\f?L?4\x1d\x0fB\x14\x12\x0e\t\x1b@\xd8\x05\x80\x01\x8b{:y/\x90\a\x1b$\x1c ,\x13'\x1c\x0f\x1cR\x88!\f\v\x06\x1dF!\v8%\r\x05\x05#)(\x1b\x1b()#\x05\x05\x0f%:\v!F\x1d\x06\v\f \x8aQ\x1c\x0f\x1c'\x14+\x1f\x1b%\x1a\a\x8e0z:\x89z\x00\x00\x00\x02\x00\x00\xff\x80\x06\x00\x05\x80\x00O\x00_\x00\x00\x014'.\x01'&54>\x0254&#\"\x06#\"'654'.\x01#\"\a\x06\x15\x14\x17\x06#\"&#\"\x06\x15\x14\x1e\x02\x15\x14\a\x06\a\x06\x15\x14\x17\x1e\x0232632\x1e\x0232>\x0232\x1632>\x0176\x01\x11\x14\x06#!\"&5\x11463!2\x16\x05\x00\x16Cf\x1d\a'.'%\x14\v(\f\x04\b\x05\x11$\x85V\xc6M\x12\x06\n\x05\v)\n\x14#'.'\a@\x86\x16\x8a\x02\b\x0e\x10\r3\r#A,G)+H+A#\r4\r\x0f\x0f\b\x01\x8a\x01\x00\xa9w\xfc@w\xa9\xa9w\x03\xc0w\xa9\x01\x84\x16\x05\x0eXA\x0e\v\x0f\x16\f\x1d\x16\x13\x19\x10\x02?4N$NW\xa5&M&L\x02\x10\x19\x14\x15\x1d\f\x16\x0f\v\x0e\x8a\x1d\x05\x16/\x16\x05*\x13\n\x1e#\x1e\x1e#\x1e\t\x13+\x03\x16\x03\v\xfc@w\xa9\xa9w\x03\xc0w\xa9\xa9\x00\x00\x00\x00\x01\x00\x00\xff\x80\t\x00\x06\x00\x00O\x00\x00\x01\x0e\x05\a\x0e\x01\a\x0e\x03\a\x06\a$\x05\x06\a>\x01?\x01>\x0376\x052\x17\x1e\x01\a\x03\x06'&#\"\x04\a\x06.\x02/\x01454327\x12\x0032\x1e\x05\x177>\x047>\x03\t\x00EpB5\x16\x16\x03\n3\x17\x0fFAP\b/h\xfe\xab\xfe\xdf\\\xd3/N\x10\x0fG\xb8S\x85L\xba\x01\x17\x01\t\v\x06\x06\xc2\x0f \x80\xe2\x92\xfe\x00\x88R\x86P*\f\x01\x06\x8a\xe9\xc0\x01m\xc9\x05\x1395F84\x0ef\x02&3Ga4B|wB\x06\x00.\\FI*/\x06\x12\xed.\x1d?&,\x06\x1f\xc8\x0e\xac5~\x10\x1e\a\a\x1bK %\r\x1f&\x03\x06\x16\v\xfe\xa7\x1d\a\x18Y\x02\x01\x1c.\"\x11\x01\x01\x01\x067\x01n\x01<\x01\t\x0f\"-I.\xb1\x04M`{\x90ARwJ!\x00\x05\x00\x00\xff\x00\x06\x00\x06\x00\x00F\x00X\x00^\x00d\x00j\x00\x00\x01\x14\a'\x17\x06\a'\x17\x06\a'\x17\x06\a'\x17\x06\"'7\a&'7\a&'7\a&'7\a&547\x17'67\x17'67\x17'67\x17'632\x17\a7\x16\x17\a7\x16\x17\a7\x16\x17\a7\x16\x174\x02$#\"\x0e\x02\x15\x14\x1e\x0232$\x12\x13\x11\t\x01\x11\x01\x11\x01\x11\t\x01\x11\x01\x11\t\x01\x11\x01\x05*\x05\xec\xe0\x13'ֱ,?\x9dg=OO\x0e&L&\x0eNJBg\x9d;1\xb2\xd6'\x13\xe0\xed\x05\x05\xee\xe1\x13'ֱ.=\x9egCIM\r$'&&\x0eNJBg\x9e=.\xb1\xd5%\x15\xe0\xed\x05\x1e\x9d\xfe\xf3\x9ew\u061d\\\\\x9d\xd8w\x9e\x01\r\x9dI\xfdo\xfdo\x02\x91\x02\xc4\xfd<\xfd<\x05\xc4\xfd\x00\xfd\x00\x03\x00\x02\x80-\x1f\x0eNIDg\x9e=/\xb2\xd7%\x16\xe4\xf0\x06\x06\xee\xe2\x13(ײ+A\x9ehEHO\x0e*\"#*\x0eOICh\x9f=/\xb2\xd7'\x13\xe0\xec\x06\x06\xed\xe1\x13(ֲ/=\x9fh>ON\x0e\x1f.\xa0\x01\x0f\x9d]\x9d\xdaxwڝ]\x9d\x01\x0f\x02\x1e\xfd\x02\xfe\x81\x01\u007f\x02\xfe\x01\u007f\xf9\xcb\x01\x9c\x037\x01\x9b\xfee\xfc\xc9\x03[\xfc\x80\xfe@\x01\xc0\x03\x80\x01\xc0\x00\x00\x03\x00\x00\xff\x00\x06\x80\x06\x00\x00\x14\x00)\x006\x00\x00\x01!\a!\"\x06\x15\x11\x14\x16\x17\x163\x15#\"&5\x1146%3\x01\x0e\x06\a567654'\x013\x13\x01\x11!67!\x114&'7\x1e\x01\x01S\x02\xb3\x1a\xfdgn\x9dy]\x17K-\x8c\xc7\xc7\x03\xdf\xf7\xfe\x1e\x17#75LSl>\xa39\x14\x14\xfe\xe3\xe4\xbb\x03V\xfc\xe5%\b\x02\xa6cP\x19e}\x05&H\x9en\xfc\xfd_\x95\x13\x05HȌ\x03\x03\x8c\xc8\xda\xfa\xf2=UoLQ1!\x02\xc3\x1a\x9c4564\x02\xdd\xfd\xb7\x01\xf2\xfb\xa97\x12\x04\x0eU\x8c\x1dC\"\xb3\x00\x00\x00\x00\n\x00\x00\xff\x00\a\x00\x06\x00\x00\a\x00\x14\x00!\x00-\x009\x00[\x00n\x00x\x00\x90\x00\xe7\x00\x00\x00\x14\x06\"&462\x0354&\"\x06\x1d\x01\x14\x16326754&\"\x06\x1d\x01\x14\x16326754&\"\x06\x1d\x01\x14\x1626754&\"\x06\x1d\x01\x14\x1626\x01\x06\x04#\".\x02547\x06\x15\x14\x12\x17632\x17632\x1762\x17632\x16\x176\x12'4#\"\a\x06#\"547\x06\x15\x14\x163276\x014&\"\x06\x15\x14\x1626\x014.\x01#\"\x06\a\x06\x15\x14\x16327632\x16\x15\x14\a>\x01\x05\x14\x02\a\x06\x04\x0f\x01\x15\x14\x06#\"'\x06\"'\x06#\"'\x06#\"&5\x06#\"'67&'\x16327&'&54>\x0332\x1767>\x017>\x027>\x0132\x17632\x17\x16\x15\x14\x0e\x02\a\x1e\x01\x15\x14\a\x16\x17632\x17\x16\x03T\"8\"\"8\x82)<()\x1d\x1e)\xac(<))\x1e\x1d)\xae)<))<)\xae)<))<)\x01\fT\xfeد{ՐR\x15h\x82x\x1e=8\x1e 78\x1e n \x1e8\x1c1\rp\x82\x8eH\x11\x1e_6\xe2\x1eS\xb2\x92oc\r\xfeF@b@?d?\x02uK\x97bM\x9070[f5Y$\x1135\x04KU\x01\x17C<:\xfe\xee[\x04;+8\x1e n \x1e87 \x1e8/8Zlv]64qE 'YK\xc00\x18\x12-AlB;\x16\x13\x17\x02\x14\x03\n\x1a\x18\x10W\xf9\x88#\x1b;WS9\x05\f\r\x13\x01\x11&\x10\x9d(\x19#-7Z\x04\xe8://:/\xfaTr\x1e++\x1er\x1e,,\x1er\x1e++\x1er\x1e,,\x1er\x1e++\x1er\x1e,,\x1er\x1e++\x1er\x1e,,\x02ʠ\xc7g\xab\xe0xXV\xafע\xfe\xd4e9222222\x1f\x19^\x01\x13\xb3K\x06\x13\xf3Vv\u007f\x94\x96\xddF0\x02\xb22OO23OO\xfe\xe0`\xa6lF;\x9fmhj\x13\x0684\x1a\x14D\xc3ro\xfe\xebB@\x9d\x1a\x01r+@222222C0DP\x01\x13\x1f`\a.\xc0r8h9\x89\x9c~T4\x1d\x19\x03\x14\x06\x0f.&\x14o\x84\x04@9\x05\a\x05\x11\x0f\x13\x01\x06\x18\f\x06\x13\x8a\xf0\x1e1P\x00\x00\x03\x00\x00\xff\x80\x06\x00\x05\x80\x00\x19\x00%\x001\x00\x00\x014'!\x153\x0e\x01#\"&4632\x177&#\"\x06\x10\x16326%35#5#\x15#\x153\x153\x00\x10\x02\x04 $\x02\x10\x12$ \x04\x03\x95\x06\xfe\x96\xd9\f}Pc\x8c\x8cc]\x0132\x16\x06\x001\xae\xa4I\xfe\xe3U\xa4Π?L\x80\xb6\x80L?\xbe\x99cc\x0e\xc34MX\v\x8a\x14\x1a&\x04\x00\xfc\xb90\x0e4;0\xfe\xae\x05X\x19pD[\x80\x80[Dp\x19D,\x0f\x02)\x12\x02&&\x00\x00\x05\x00\x00\xffQ\t\x00\x05\x00\x00\x05\x009\x00V\x00\\\x00\x94\x00\x00\x1226&\"\x06\x05.\x05'\a\x06&'&6?\x01.\x02\x06#\"\x0f\x01#\x1126\x1e\x03\x17\x01\x16327\x1667\x167>\x01'\x1632>\x01&\x173\x11#'&+\x01\"\x0f\x01\x06\x14\x17\x1e\x01?\x016\x1e\x01\a\x1e\x01\x17\x1e\x01\x17\x16\x0426&\"\x06\x01\x11\x14\x06#!\x0e\x01\a\x0e\x01\a\x0e\x01'\x0e\x01.\x01'\x01!\"&5\x11463!>\x06;\x012\x176;\x012\x1e\x06\x17!2\x16\x98P P \x06\t\n9\x1a2#.\x16}S\xfbP9\x01:\xb1\x16:%L\v\\B\x9e\x9b\x05 \f\x1b\x0e\x15\b\x01)spN/9o\x11J5\x14 \x02\n!+D\x1f\a\x84`]\x9dBg\xa7Y9\xd1\x1c\x1b+\x86,\xc1\x199%\n\x10P\x14\x1dk\v4\x01\x00P P \x01\b&\x1a\xfeN\x1bnF!_7*}B<\x84{o0\xfe\xe1\xfe\x9a\x1a&&\x1a\x01\xa5\x0eB\x1d;*<@$ucRRc\xa7#@16#3\x1b7\x0e\x01c\x1a&\x01\x80@@@\x06\rJ\"@*4\x17\x8c^\x04`E\xb2D\xce\v\v\x01\x02B\x9e\xfd\xe0\x01\x01\x03\x06\v\b\xfe\xdco/\x1489\x062\x127\x17\n*@O\x18\x02\x00\xb4LC\xf3!T!3\x022\xda\x17\x033\x1f\x13X\x18$\x8b\x0fBJ@@@\x02\x00\xfd\x80\x1a&AS\n0C\f59\x04\"\v'D/\x01\x1a&\x1a\x02\xa0\x1a&\x0eD\x1c4\x17\x1c\v88\f\x11$\x1a5\x1fA\x10&\x00\x00\x00\x02\x00\x00\xff\x00\a\x00\x06\x00\x00%\x00O\x00\x00\x01\x11\x14\x06#!\"&5\x1147>\x067>\x032\x1e\x02\x17\x1e\x06\x17\x16\x01$7>\x01/\x01.\x01\a\x06\a\x0e\x03\".\x02'&'&\x06\x0f\x01\x06\x16\x17\x16\x05\x1e\x042>\x03\a\x00^B\xfa@B^\v\b>\x15FFz\xa5n\x05_0P:P2\\\x06n\xa5zFF\x15>\b\v\xfd\xcc\x01\aR\v\x03\b&\b\x1a\v\xe7p\x05^1P:P1^\x05\xba\x9d\v\x1a\b&\b\x03\vR\x01\a\nP2NMJMQ0R\x03r\xfc.B^^B\x03\xd2\x0f\t\a7\x11:5]yP\x04H!%%\"F\x05Py]5:\x117\a\t\xfd\xa8\xbf=\b\x19\v4\v\x03\b\xa9Q\x03H!%%!H\x03\x86t\b\x03\v4\v\x19\b=\xbf\b<\"-\x16\x16/ ?\x00\x00\x00\x00\x03\x00\x00\xff\x00\a\x00\x06\x00\x001\x00P\x00p\x00\x00\x01\x17\x16\x06\a\x0e\x02\a\x0e\x03+\x02\".\x02'.\x02'.\x01?\x01>\x01\x17\x16\x17\x1e\x03;\x022>\x027$76\x16\x13\x11&'&%.\x03+\x02\"\x0e\x02\a\x0e\x02\a\x06\a\x11\x14\x163!26\x13\x11\x14\x06#!\"&5\x11476\x007>\x03;\x022\x1e\x02\x17\x1e\x02\x17\x16\x05\xc2'\b\x03\n+\xa7~\x04'*OJ%\x01\x01%JN,&\x05x\xa7'\v\x03\b%\b\x1b\v^\xd4\x05M,E\x18\x01\x01\x18E,M\x05\x01\x027\v\x1a\xc6ZE[\xfe\xd6\x03P*F\x18\x01\x01\x18F*P\x03\xd7\xc9:5\x0e\a\x13\r\x05\xc0\r\x13\x80^B\xfa@B^){\x01\xc6\x06$.MK%\x01\x01%KM.$+\xe2\xe2X)\x02o3\v\x19\b\"\x81a\x03 2\x17\x172!\x1f\x04]\x81\x1e\b\x19\v4\v\x04\tI\xa3\x04>\x1f\"\"\x1f>\x04\xc6,\b\x03\xfd&\x03\xa0S8J\xe6\x02B\x1e##\x1eB\x02\xa6\x9f12\f\a\xfc`\r\x13\x13\x03\xad\xfc`B^^B\x03\xa08&r\x01a\x05\x1e#1\x18\x181#\x1e$\xac\xb6R&\x00\x00\x00\x00\v\x00\x15\xff\x00\x05\xeb\x06\x00\x00\x03\x00\a\x00\v\x00\x0f\x00\x1a\x00\x1e\x00\"\x00&\x00.\x002\x00v\x00\x00%\x17/\x01\x01%'\x05\x01\x17\x03'\x01%\x03\x05\x01\x17/\x01\x14\x16\x06\x0f\x01\x17\x16\x01\x05\x03%\x017\a\x17\x01%\x03\x05\x017'\a\x17\x16\x0f\x01%7\x0f\x02'\a\x14\x0f\x01\x06/\x01\x17\x14\a\x05\x06#&5'&\x03&?\x01&'\x03&?\x01&'\x03&7%2\x17\x05\x16\x15\x13\x14\x0f\x01\x17\x16\x15\x1776\x1f\x0174?\x016\x1f\x01\x1e\x01\x0e\x01\x15\x14\x0f\x01\x06\x01J\xca\"\xd8\x01\x12\x01\x12\v\xfe\xd4\xfe\xee\xe30\xf5\x01<\x01=\x0e\xfe\xa0\x01\x8d_\x02g\x02\x02\x04NU\a\xfd?\x01\x00D\xfe\xe9\x04f\x0f\xe6\x02\xfd\xe1\x01u\x13\xfeY\x03\x9a\x14\xe2\x02\x90\x06\x02\a\x01\x02\x1e\xb3\x14\x13G\b\x04\xea\a\ab\a\x04\xfe\xdb\x04\x02\b\xe4\x047\x02\a=^\x01H\x02\b^\x85\x02`\x02\t\x01\xb1\x05\x03\x01=\x06\x14\x06v~\x05\x05y\x05\x06T\x03\x05\xce\x06\x05\xf5\x04\x02\x0f\x14\x04\xbf\x06\x01\xd6\xec\xd5\xfe3\xda\xf5\xd7\x01\x86\xd5\x01G\xcc\xfd\xe2\xd6\x01D\xc8\xfe\xa3P\xefO\x01\x0f\t\x034F\x06\x02\x9e\xc8\x01ѭ\xfb\xb3\xea\xa4\xf0\x02q\xc2\x01\xb9\xa3\xfc\xbb\xe9\x8ei_\x04\x05w\\ހ\xe4!1u\x05\x03\xbb\x05\x05S\xa1\x05\x03\xea\x02\x02\x01\xf2\x04\x01\x11\a\x04%V\x06\x01_\a\x05-d\b\x01\xd2\n\x03\x87\x01\x99\x04\x05\xfe1\a\x03=U\x02\x06{J\x04\x048n\x06\x03~\x03\x03\x87\x04\x06r\x87\x03\x05\x02\x99\x05\x00\x00\x03\x00\x00\xff\x00\x06\x80\x06\x00\x00\x1d\x00'\x00U\x00\x00\x014.\x03#\x0e\x04\".\x03'\"\x0e\x03\x15\x14\x163!26\x034&\"\x06\x15\x14\x1626\x01\x15\x14\x06+\x01\x15\x14\x06#!\"&5\x11463!2\x16\x1d\x0132\x16\x1d\x01\x14\x06+\x01\x1532\x16\x1d\x01\x14\x06+\x01\x1532\x16\x04\xb1\v\x1f0P3\x067\x1e3/./3\x1e7\x063P0\x1f\vT=\x02@=T\xad\x99֙\x99֙\x02|\x12\x0e`^B\xfb@B^^B\x04\xc0B^`\x0e\x12\x12\x0e``\x0e\x12\x12\x0e``\x0e\x12\x01*9deG-\x04!\x10\x18\n\n\x18\x10!\x04-Ged9Iaa\x02\x9bl\x98\x98lk\x98\x98\xfeO\xc0\x0e\x12\xe0B^^B\x05\xc0B^^B\xe0\x12\x0e\xc0\x0e\x12\x80\x12\x0e\xc0\x0e\x12\x80\x12\x00\x00\x04\x00\x00\xff\x00\x06\x80\x06\x00\x00\t\x00+\x00Y\x00i\x00\x00\x01\x14\x06\"&5462\x16\x032\x1e\x04\x15\x14\x06#!\"&54>\x03;\x01\x1e\x052>\x04\x01\x14\x06+\x01\x1532\x16\x1d\x01\x14\x06+\x01\x1532\x16\x1d\x01\x14\x06+\x01\x15\x14\x06#!\"&5\x11463!2\x16\x1d\x0132\x16\x15\x01\x114&#!\"\x06\x15\x11\x14\x163!26\x04\x04\x99֙\x99֙0.I/ \x10\aOB\xfd\xc0BO\t\x1c-Q5\x05\a2\x15-\x1d)&)\x1d-\x152\x02\xb3\x13\r``\r\x13\x13\r``\r\x13\x13\r`^B\xfb@B^^B\x04\xc0B^`\r\x13\xff\x00\x13\r\xfb@\r\x13\x13\r\x04\xc0\r\x13\x03|k\x98\x98kl\x98\x98\xfe\xb8\"=IYL)CggC0[jM4\x04\x1f\v\x17\t\t\t\t\x17\v\x1f\x01\x04\r\x13\x80\x13\r\xc0\r\x13\x80\x13\r\xc0\r\x13\xe0B^^B\x05\xc0B^^B\xe0\x13\r\xfb@\x05\xc0\r\x13\x13\r\xfa@\r\x13\x13\x00\x00\x06\x00\x00\xff\x80\b\x00\x05\x80\x00\x19\x00!\x001\x00A\x00Q\x00u\x00\x00\x004.\x02#\x0e\x04\".\x03'\"\x0e\x02\x14\x163!2\x024&\"\x06\x14\x162\x0154&#!\"\x06\x1d\x01\x14\x163!26\x1154&#!\"\x06\x1d\x01\x14\x163!26\x1154&#!\"\x06\x1d\x01\x14\x163!26\x01\x11\x14\x06#!54&+\x01\"\x06\x1d\x01!54&+\x01\"\x06\x1d\x01!\"&5\x11463!2\x16\x04\x00\x12)P9\x060\x1b,***,\x1b0\x069P)\x12J6\x02\x006S\x85\xbc\x85\x85\xbc\x04\"\x12\x0e\xfd\xc0\x0e\x12\x12\x0e\x02@\x0e\x12\x15\x0f\xfd\xc8\x0f\x15\x15\x0f\x028\x0f\x15\x12\x0e\xfd\xc0\x0e\x12\x12\x0e\x02@\x0e\x12\x01\x00^B\xfe\xa0\x12\x0e@\x0e\x12\xfd\x00\x12\x0e@\x0e\x12\xfe\xa0B^^B\x06\xc0B^\x01U\x80kc9\x04\x1c\x0f\x14\t\t\x14\x0f\x1c\x049ck\x80U\x02?\xbc\x85\x85\xbc\x85\xfe\xe6@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x128\x0f\x15\x15\x0f8\x0f\x15\x15\x01\v@\x0e\x12\x12\x0e@\x0e\x12\x12\x01N\xfb@B^`\x0e\x12\x12\x0e``\x0e\x12\x12\x0e`^B\x04\xc0B^^\x00\x00\a\x00\x00\xff\x80\b\x00\x05\x80\x00\x19\x00!\x001\x00A\x00Q\x00u\x00\x85\x00\x00\x00\x14\x06#!\"&4>\x023\x1e\x042>\x0372\x1e\x01\x02\x14\x06\"&462\x01\x15\x14\x06#!\"&=\x01463!2\x165\x15\x14\x06#!\"&=\x01463!2\x165\x15\x14\x06#!\"&=\x01463!2\x16\x13\x114&#!\"\x06\x15\x11\x14\x163!546;\x012\x16\x1d\x01!546;\x012\x16\x1d\x01!26\x13\x11\x14\x06#!\"&5\x11463!2\x16\x04\x00J6\xfe\x006J\x12)P9\x060\x1b,***,\x1b0\x069P)\x8b\x85\xbc\x85\x85\xbc\x04\"\x12\x0e\xfd\xc0\x0e\x12\x12\x0e\x02@\x0e\x12\x15\x0f\xfd\xc8\x0f\x15\x15\x0f\x028\x0f\x15\x12\x0e\xfd\xc0\x0e\x12\x12\x0e\x02@\x0e\x12\x80\x13\r\xf9@\r\x13\x13\r\x01`\x12\x0e@\x0e\x12\x03\x00\x12\x0e@\x0e\x12\x01`\r\x13\x80^B\xf9@B^^B\x06\xc0B^\x01ՀUU\x80kc9\x04\x1c\x0f\x14\t\t\x14\x0f\x1c\x049c\x01\xbb\xbc\x85\x85\xbc\x85\xfd`@\x0e\x12\x12\x0e@\x0e\x12\x12\xee8\x0f\x15\x15\x0f8\x0f\x15\x15\xf5@\x0e\x12\x12\x0e@\x0e\x12\x12\xfc2\x04\xc0\r\x13\x13\r\xfb@\r\x13`\x0e\x12\x12\x0e``\x0e\x12\x12\x0e`\x13\x04\xcd\xfb@B^^B\x04\xc0B^^\x00\x00\x00\x00\x03\x00\x00\xff\x00\a\x00\x06\x00\x00\x0f\x00\x17\x00(\x00\x00%.\x01'\x0e\x01\"&'\x0e\x01\a\x16\x04 $\x02\x10& \x06\x10\x16 \x00\x10\x02\x06\x04#\"$&\x02\x10\x126$ \x04\x16\x05\xf3\x16\x83wC\xb9ιCw\x83\x16j\x01J\x01~\x01J\x89\xe1\xfe\xc2\xe1\xe1\x01>\x02\xe1\x8e\xef\xfe\xb4\xb7\xb6\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0ś\xcd\x10JSSJ\x10͛\x96\xaf\xaf\x02\xb2\x01>\xe1\xe1\xfe\xc2\xe1\x016\xfe\x94\xfe\xb5\xf1\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x8e\xf0\x00\x00\x03\x00\x00\xff\x00\a\x00\x06\x00\x00\x10\x00$\x00,\x00\x00\x00 \x04\x16\x12\x15\x14\x02\x06\x04 $&\x02\x10\x126\x01654\x02&$ \x04\x06\x02\x15\x14\x17\x123\x16 72&\x10& \x06\x10\x16 \x02\xca\x01l\x01L\xf0\x8e\x8d\xf0\xfe\xb4\xfe\x92\xfe\xb4\uf38e\xf0\x04m\x95z\xce\xfe\xe4\xfe\xc8\xfe\xe4\xcez\x95B\xf0\x83\x01l\x83\xf0\xa9\xe1\xfe\xc2\xe1\xe1\x01>\x06\x00\x8e\xf0\xfe\xb4\xb6\xb5\xfe\xb4\xf0\x8f\x8e\xf1\x01K\x01l\x01L\xf0\xfbG\xcd\xfa\x9c\x01\x1c\xcezz\xce\xfe\xe4\x9c\xfa\xcd\x01G\x80\x80\xa1\x01>\xe1\xe1\xfe\xc2\xe1\x00\x00\x00\x00\x03\x00\x00\xff\x00\x06\x00\x06\x00\x00\x1f\x00'\x007\x00\x00\x01\x1e\x04\x15\x14\x06#!\"&54>\x037&54>\x022\x1e\x02\x15\x14\x00 \x06\x10\x16 6\x10\x132654\x02'\x06 '\x06\x02\x15\x14\x163\x04\xb1/U]B,ȍ\xfc\xaa\x8d\xc8,B]U/OQ\x8a\xbdн\x8aQ\xfe\x9f\xfe\xc2\xe1\xe1\x01>\xe1+X}\x9d\x93\x91\xfe\x82\x91\x93\x9d}X\x02\xf0\x0e0b\x85Ӄ\x9a\xdbۚ\x83Ӆb0\x0e}\x93h\xbd\x8aQQ\x8a\xbdh\x93\x02\x13\xe1\xfe\xc2\xe1\xe1\x01>\xfa\xe1\x8ff\xef\x01\x14\a\u007f\u007f\a\xfe\xec\xeff\x8f\x00\x00\x00\x00\x04\x00\x00\xff\x00\x05\x00\x06\x00\x00\x11\x00\x19\x00#\x00=\x00\x00\x00\x14\x06#!\"&4>\x023\x16272\x1e\x01\x02\x14\x06\"&462\x01\x11!\x11\x14\x163!26\x13\x11\x14\x06#!\"&5\x11463!\x15\x14\x16;\x0126=\x01!2\x16\x04\x00J6\xfe\x006J\x12)Q8P\xd8P8Q)\x88\x87\xbe\x87\x87\xbe\x01\xa1\xfc\x00\x13\r\x03\xc0\r\x13\x80^B\xfc@B^^B\x01`\x12\x0e\xc0\x0e\x12\x01`B^\x01V\x80VV\x80ld9KK9d\x01\xb9\xbc\x85\x85\xbc\x85\xfb\xa0\x05`\xfa\xa0\r\x13\x13\x05\xcd\xfa@B^^B\x05\xc0B^`\x0e\x12\x12\x0e`^\x00\x00\b\x00\x00\xff\x80\b\x00\x05\x80\x00\x13\x00\x1b\x00+\x00;\x00K\x00[\x00e\x00u\x00\x00\x014.\x02#\x06\"'\"\x0e\x02\x15\x14\x163!26\x024&\"\x06\x14\x162\x0154&#!\"\x06\x1d\x01\x14\x163!26\x0154&#!\"\x06\x1d\x01\x14\x163!26%54&+\x01\"\x06\x1d\x01\x14\x16;\x0126\x1154&#!\"\x06\x1d\x01\x14\x163!26\x01!54&#!\"\x06\x15!\x11\x14\x06#!\"&5\x11463!2\x16\x03\x80\x0f\"D/@\xb8@/D\"\x0f?,\x01\xaa,?\x80p\xa0pp\xa0\x04p\x12\x0e\xfd@\x0e\x12\x12\x0e\x02\xc0\x0e\x12\xfe\x80\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\x01\x80\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x0e\xfd@\x0e\x12\x12\x0e\x02\xc0\x0e\x12\xf9\x80\a\x00\x12\x0e\xf9@\x0e\x12\a\x80^B\xf9@B^^B\x06\xc0B^\x01D6]W2@@2W]67MM\x01\xa3\xa0pp\xa0p\xfe\xe0@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x01n`\x0e\x12\x12\x0e\xfb@B^^B\x04\xc0B^^\x00\b\x00\x00\xff\x80\b\x00\x05\x80\x00\x13\x00\x1b\x00+\x00;\x00K\x00[\x00e\x00u\x00\x00\x01\x14\x06#!\"&54>\x023\x16272\x1e\x02\x02\x14\x06\"&462\x01\x15\x14\x06#!\"&=\x01463!2\x16%\x15\x14\x06#!\"&=\x01463!2\x16\x05\x15\x14\x06+\x01\"&=\x0146;\x012\x165\x15\x14\x06#!\"&=\x01463!2\x16\x13\x11!\x11\x14\x163!26\x13\x11\x14\x06#!\"&5\x11463!2\x16\x03\x80?,\xfeV,?\x0f\"D/@\xb8@/D\"\x0f\x80p\xa0pp\xa0\x04p\x12\x0e\xfd@\x0e\x12\x12\x0e\x02\xc0\x0e\x12\xfe\x80\x12\x0e\xfe\xc0\x0e\x12\x12\x0e\x01@\x0e\x12\x01\x80\x12\x0e\xc0\x0e\x12\x12\x0e\xc0\x0e\x12\x12\x0e\xfd@\x0e\x12\x12\x0e\x02\xc0\x0e\x12\x80\xf9\x00\x13\r\x06\xc0\r\x13\x80^B\xf9@B^^B\x06\xc0B^\x01D7MM76]W2@@2W]\x01֠pp\xa0p\xfd\xa0@\x0e\x12\x12\x0e@\x0e\x12\x12\xf2@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\x0e@\x0e\x12\x12\xf2@\x0e\x12\x12\x0e@\x0e\x12\x12\xfc\xb2\x04`\xfb\xa0\r\x13\x13\x04\xcd\xfb@B^^B\x04\xc0B^^\x00\x02\x00\x1d\xff\x00\x06\xe2\x06\x00\x00\x1a\x00A\x00\x00\x01\x10\x02#\"\x02\x11\x10\x12327.\x04#\"\a'632\x16\x176\x013\x16\x0e\x03#\".\x02'\x06#\"$&\x0254\x126$32\x1e\x03\x15\x14\x02\a\x1e\x01326\x04\xe7\xd2\xe1\xde\xd0\xd0\xdeJ9\x16\"65I).!1i\xab\x84\xa7CC\x01\x86u\x03\n+I\x8d\\Gw\\B!al\x96\xfe\xe3݇\x87\xde\x01\x1d\x95y\xebǙV\xa1\x8a/]:=B\x02\xed\x01>\x019\xfe\xc6\xfe\xc3\xfe\xc4\xfe\xc9\x11+\x0132\x16\x15\x14\a\x06\a\x06\x15\x10\x17\x16\x17\x1e\x04%\x14\x06#!\"&5463!2\x16\x03\x14\a\x0e\x01\a\x06#\"&54>\x0254'&#\"\x15\x14\x16\x15\x14\x06#\"54654'.\x01#\"\x0e\x01\x15\x14\x16\x15\x14\x0e\x03\x15\x14\x17\x16\x17\x16\x17\x16\x15\x14#\"'.\x0154>\x0354'&'&5432\x17\x1e\x04\x17\x14\x1e\x0532654&432\x17\x1e\x01\x05\x10\a\x0e\x03#\"&54>\x0176\x114&'&'.\x0554632\x17\x16\x12\x17\x16\x01\xc5 \x15\x01\f?c\xe1\xd5'p&\x13 ?b1w{2V\x02\x19\x0e\x14\t\x05?#\x1d\xfb\xc7\x1a&#\x1d\x049\x1a&\xd7C\x19Y'\x10\v\a\x10&.&#\x1d\x11\x03\x0f+\x17B\x03\n\r:\x16\x05\x04\x03 &65&*\x1d2\x10\x01\x01\x12\x06\x1bw\x981GF1\x19\x1d\x1b\x13)2<)<'\x1c\x10\b\x06\x03\b\n\f\x11\n\x17\x1c(\n\x1bBH=\x02ӊ\x13:NT \x10\x1e:O\t\xb7)4:i\x02\x16\v\x13\v\b \x13F~b`\f\x02e\x15!\x03\x0f}\x01\x1c\x01\x88\x01U\x01\x113i\x1b\x13\x1b?fR\xc7\xfa\xfe\xe7\xd2UX\x03\x1a\x10\x19\x16|\x1d'&\x1a\x1d'&\x02I\x86c&Q\x14\n\f\x06\t*2U.L6*\x05\f/\r\x16\x1aL\x0f:\x0f\x19\x15\x199\x01\x04\x04\x020\x1e%>..>%b>+\x14\x05\x05\x02\x03\x10\v+\xc1z7ymlw45)0\x10\t\f\x14\x1d\x1333J@0\x01!\x11!\x15\x16\v\x1c\x17\x19T\x14FL\xa0\x87\xfe\xee\xe5 P]=\x1f\x10\x0fGS\v\xe6\x01-\x83\xd0kwm\x03\x15\f\x17\x11\x14\t\x13!\xa9\x83\xfe\xe4\xac*\x00\x00\x02\x00\x00\xff\x00\a\x00\x06\x00\x00\x18\x00(\x00\x00%\x136&\a\x01\x0e\x01\x16\x1f\x01\x016\x17\x16\a\x019\x01\a2?\x01\x17\x16\x00\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x04\xa5\x93\t' \xfc\xa0\x1d\x15\x10\x18\xdd\x02\x01\x15\v\a\v\xfea\x10\x17\x16l\xe0@\x02l\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\xe5\x02\xb5,&\f\xfe\xb3\v\x1c\x19\aE\x01C\x0e\b\x05\n\xfe\x89\xe4\x16h\xa5$\x02\x9b\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x8e\xf0\x00\x00\x06\x00\x00\xff\x00\x04\x00\x06\x00\x00\r\x00\x1f\x00/\x003\x007\x00;\x00\x00%\x14\x06\"&5467\x113\x11\x1e\x01\x174&'\x114&\"\x06\x15\x11\x0e\x01\x15\x14\x16 67\x14\x00 \x00547\x1146 \x16\x15\x11\x16\x13\x15#5\x13\x15#5\x13\x15#5\x02\x80p\xa0pF:\x80:F\x80D\x00F\x00N\x00V\x00^\x00f\x00n\x00v\x00~\x00\x86\x00\x8e\x00\x96\x00\x9e\x00\x00\x01\x16\x14\a\x01\x06\"/\x01&4?\x01.\x017&#\"\x06\x15\x11!\x114>\x0232\x16\x176\x16\x17762\x17\x022\x16\x14\x06\"&4\x04\"&462\x16\x1462\x16\x14\x06\"&4\x042\x16\x14\x06\"&4\x04462\x16\x14\x06\"$2\x16\x14\x06\"&4\x042\x16\x14\x06\"&4\x04\"&462\x16\x1462\x16\x14\x06\"&4\x04\"&462\x16\x1462\x16\x14\x06\"&4\x042\x16\x14\x06\"&4$2\x16\x14\x06\"&4\x062\x16\x14\x06\"&4\x062\x16\x14\x06\"&4\x05\x99\n\n\xfd\x8e\n\x1a\nR\n\n,H\x138Jfj\x96\xff\x00Q\x8a\xbdhj\xbeG^\xceR,\n\x1a\n!4&&4&\x01Z4&&4&\xa64&&4&\xfd\xa64&&4&\x01\x00&4&&4\x01\x004&&4&\xfd\xa64&&4&\x01Z4&&4&\xa64&&4&\xfe\xda4&&4&\xa64&&4&\xfe\xa64&&4&\x01&4&&4&Z4&&4&Z4&&4&\x05\a\n\x1a\n\xfd\x8e\n\nR\n\x1a\n,[\xe8cG\x96j\xfb\x00\x05\x00h\xbd\x8aQRJ'\x1dA,\n\n\xfe\xa7&4&&4Z&4&&4Z&4&&4Z&4&&444&&4&\x80&4&&4Z&4&&4Z&4&&4Z&4&&4\xda&4&&4Z&4&&4Z&4&&4&&4&&4Z&4&&4Z&4&&4\x00\x11\x00\x00\xff\x00\a\x00\x06\x00\x00\x1d\x00%\x00-\x005\x00=\x00E\x00M\x00}\x00\x85\x00\x8d\x00\x95\x00\x9d\x00\xa5\x00\xad\x00\xb5\x00\xbd\x00\xc5\x00\x00\x01\x15\x14\a\x15\x14\x06+\x01\"&=\x01\x06#!\"'\x15\x14\x06+\x01\"&=\x01&=\x01\x00\x14\x06\"&4626\x14\x06\"&462&\x14\x06\"&462\x16\x14\x06\"&462&\x14\x06\"&462&\x14\x06\"&462\x01\x15\x14\x06#!\"&=\x0146;\x01\x114632\x176\x16\x1776\x1f\x01\x16\a\x01\x06/\x01&?\x01.\x017&#\"\x06\x15\x11!2\x16\x00\x14\x06\"&462&\x14\x06\"&462&\x14\x06\"&462\x16\x14\x06\"&462&\x14\x06\"&462&\x14\x06\"&462\x16\x14\x06\"&462&\x14\x06\"&462\x16\x14\x06\"&462\x06\x80\x80\x12\x0e@\x0e\x12?A\xfd\x00A?\x13\r@\r\x13\x80\x02@\x12\x1c\x12\x12\x1cR\x12\x1c\x12\x12\x1c.\x12\x1c\x12\x12\x1c\x92\x12\x1c\x12\x12\x1c.\x12\x1c\x12\x12\x1c.\x12\x1c\x12\x12\x1c\x04R\x12\x0e\xf9@\x0e\x12\x12\x0e`\x96jlL.h)\x16\v\v*\v\v\xfe\xc6\v\v*\v\v\x16$\t\x1c%35K\x05\xe0\x0e\x12\xfc\x80\x12\x1c\x12\x12\x1c.\x12\x1c\x12\x12\x1c.\x12\x1c\x12\x12\x1c\xd2\x12\x1c\x12\x12\x1c.\x12\x1c\x12\x12\x1c.\x12\x1c\x12\x12\x1c\xd2\x12\x1c\x12\x12\x1c.\x12\x1c\x12\x12\x1c\x92\x12\x1c\x12\x12\x1c\x01\xc0\xc0\xa9u\xc2\x0e\x12\x12\x0ev\x16\x16n\x11\x17\x17\x11\xbau\xa9\xc0\x01\xae\x1c\x12\x12\x1c\x12.\x1c\x12\x12\x1c\x12.\x1c\x12\x12\x1c\x12\x12\x1c\x12\x12\x1c\x12.\x1c\x12\x12\x1c\x12.\x1c\x12\x12\x1c\x12\xfd\xe0@\x0e\x12\x12\x0e@\x0e\x12\x02\x80j\x96N\x13\x0e \x16\v\v*\v\v\xfe\xc6\v\v*\v\v\x16.t2#K5\xfd\x80\x12\x01\xc0\x1c\x12\x12\x1c\x12.\x1c\x12\x12\x1c\x12.\x1c\x12\x12\x1c\x12R\x1c\x12\x12\x1c\x12.\x1c\x12\x12\x1c\x12.\x1c\x12\x12\x1c\x12R\x1c\x12\x12\x1c\x12.\x1c\x12\x12\x1c\x12\x12\x1c\x12\x12\x1c\x12\x00\x00\x00\x04\x00\x01\xff\x00\x06\x00\x05\xfe\x00\r\x00@\x00H\x00q\x00\x00\x01\x14\a\x06\a\x06 '&'&54 \x01\x14\x00\a\x06&76767676\x1254\x02$\a\x0e\x03\x17\x16\x12\x17\x16\x17\x16\x17\x1e\x01\x17\x16\x06'.\x01\x0276\x126$76\x04\x16\x12\x04\x14\x06\"&462\x01\x14\x06\a\x06&'&'&7>\x0154.\x01\a\x0e\x01\a\x06\x16\x17\x16\a\x06\a\x0e\x01'.\x017>\x0276\x1e\x01\x03\xe2\x11\x1f\x18\x16\xfe\xfc\x16\x18\x1f\x11\x01\xc0\x02\x1e\xfe\xf4\xd8\b\x0e\x01\a\x03\x04\x02\x01\b\x9f\xc1\xb6\xfeȵ|\xe2\xa1_\x01\x01ğ\a\x02\x03\x03\x01\b\x02\x01\x0f\b\x94\xe2y\b\av\xbf\x01\x03\x8f\xa4\x01/ۃ\xfd\u20fa\x83\x83\xba\x01\xa3k]\b\x10\x02\x06\x17\a\n:Bu\xc6q\x85\xc0\r\nCA\n\a\x18\x05\x02\x10\b_k\x02\x03\x84ނ\x90\xf8\x91\x01XVo\xd7bZZb\xd7nW\xa8\x01\x00\xf0\xfe|V\x03\f\t0\x12 \x0f\t\x03Q\x012\xb8\xb4\x01-\xa8\n\al\xad\xe7}\xb8\xfe\xcfO\x03\t\x15\x18\t/\f\t\f\x04:\xdf\x011\xa7\x8f\x01\x05\xc1z\t\nq\xd0\xfe\xdb%\xba\x83\x83\xba\x83\xff\x00z\xd5G\x06\b\n4(\n\n6\x92Ro\xbaa\f\x0fą\\\xa8<\n\n)4\t\b\x06J\xda}\x83\xe2\x89\x06\a\x86\xf1\x00\x02\x00\x00\xff\x80\a\x00\x05\x80\x00\x03\x00\x13\x00\x00%!\x11!\x01\x11\x14\x06#!\"&5\x11463!2\x16\x01\x00\x05\x00\xfb\x00\x06\x00^B\xfa@B^^B\x05\xc0B^\x80\x03\x00\x01`\xfb@B^^B\x04\xc0B^^\x00\x01\x00\x00\xff\x80\a\x00\x01\x80\x00\x0f\x00\x00%\x15\x14\x06#!\"&=\x01463!2\x16\a\x00^B\xfa@B^^B\x05\xc0B^\xe0\xc0B^^B\xc0B^^\x00\x00\x00\x03\x00\x00\xff\x00\b\x00\x06\x00\x00\x03\x00\f\x00&\x00\x00)\x01\x11)\x02\x11!\x1132\x16\x15\x01\x11\x14\x06#!\x11\x14\x06#!\"&5\x11463!\x11463!2\x16\x01\x00\x03\x00\xfd\x00\x04\x00\x02\x00\xfd\x00`B^\x03\x00^B\xfd\xa0^B\xfc@B^^B\x02`^B\x03\xc0B^\x02\x00\x03\x00\xff\x00^B\x02\x00\xfc@B^\xfe\xa0B^^B\x03\xc0B^\x01`B^^\x00\x00\x00\x02\x00\x00\xff\x80\a\x00\x05\x80\x00#\x003\x00\x00%764/\x01764/\x01&\"\x0f\x01'&\"\x0f\x01\x06\x14\x1f\x01\a\x06\x14\x1f\x01\x162?\x01\x17\x162\x01\x11\x14\x06#!\"&5\x11463!2\x16\x04\x97\x92\n\n\xe9\xe9\n\n\x92\n\x1a\n\xe9\xe9\n\x1a\n\x92\n\n\xe9\xe9\n\n\x92\n\x1a\n\xe9\xe9\n\x1a\x02s^B\xfa@B^^B\x05\xc0B^ג\n\x1a\n\xe9\xe9\n\x1a\n\x92\n\n\xe9\xe9\n\n\x92\n\x1a\n\xe9\xe9\n\x1a\n\x92\n\n\xe9\xe9\n\x04\x13\xfb@B^^B\x04\xc0B^^\x00\x03\x00\x00\xff\x80\a\x00\x05\x80\x00#\x00'\x007\x00\x00\x01\a\x06\"/\x01\a\x06\"/\x01&4?\x01'&4?\x0162\x1f\x01762\x1f\x01\x16\x14\x0f\x01\x17\x16\x14\x01!\x11!%\x11\x14\x06#!\"&5\x11463!2\x16\x04\xe9\x92\n\x1a\n\xa9\xa9\n\x1a\n\x92\n\n\xa9\xa9\n\n\x92\n\x1a\n\xa9\xa9\n\x1a\n\x92\n\n\xa9\xa9\n\xfc\r\x05\x00\xfb\x00\x06\x00^B\xfa@B^^B\x05\xc0B^\x01\xa9\x92\n\n\xa9\xa9\n\n\x92\n\x1a\n\xa9\xa9\n\x1a\n\x92\n\n\xa9\xa9\n\n\x92\n\x1a\n\xa9\xa9\n\x1a\xfe\xcd\x04\x00`\xfb@B^^B\x04\xc0B^^\x00\x02\x00\x00\xff\x00\a\x00\x06\x00\x00\x03\x00\x13\x00\x00\t\x01!\x01\x00\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x04.\x012\xfdr\xfe\xce\x05`\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x01f\x024\xfd\xcc\x01\xd0\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x8e\xf0\x00\x00\a\x00\x00\xff\x00\a\x02\x06\x00\x00\a\x00\x13\x00#\x00.\x00C\x00\xc4\x00\xd4\x00\x00\x01&\x0e\x01\x17\x16>\x01\x05\x06\"'&4762\x17\x16\x14\x17\a\x06\"/\x01&4?\x0162\x1f\x01\x16\x14'\x06\"'&4762\x16\x14%\x0e\x01'.\x01>\x02\x16\x17\x1e\a\x0e\x01\x136.\x02'.\x01\a>\x01\x1f\x016'>\x01/\x01>\x0176&'&\x06\a\x0e\x01\x1e\x01\x17.\x01'&7&'\"\a>\x01?\x014'.\x01\x06\a67\x06\x1e\x01\x17\x06\a\x0e\x01\x0f\x01\x0e\x01\x17\x16\x17\x06\a\x06\x14\x167>\x017.\x02\a>\x043\x167654'\x16\a\x0e\x01\x0f\x01\x0e\x05\x16\x17&'\x0e\x04\x16\x17\x166\x127>\x017\x16\x17\x1676\x12\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x05\v\x0f(\f\v\x0e4\x10\xfeZ\b\x17\a\b\b\a\x17\b\a\x9e#\f#\r&\f\f#\f#\r&\fy\a\x17\b\a\a\b\x16\x10\x01\x8b\"\x936&.\x04JM@&\x02\x16\a\x13\x06\x0e\x03\x05\x03\a\xc3\x03\x17 \"\x06(XE\x13*\f\f\x02$\x06\x01\x03\x03+8\x06\njT\x01?\x013\x03\x13#'.\x01'&!\x11\x14\x163!2>\x04?\x013\x06\x02\a.\x01'#!\x0557>\x017\x13\x12'.\x01/\x015\x05!27\x0e\x01\x0f\x01#'.\x01#!\"\x06\x02\x06g\xb1%%D-\x11!g\x0e\ag\x1d\x0f<6W\xfe\xf7WZ\x01e#1=/2*\x12]Y\x063\x05\x92\xeb-,\xfd\x8c\xfe\x88\u007fC1\x01\b\x03\v\x02/D\u007f\x01x\x02\xbe\x8b\xeb\x06\x10\x04\x05] \x1fVF\xfd\xdc\x1c\x0f\x05I\xfdq\x01\x05\x03\x03\x02-H\x8e\xfe\xbe\xfe\xc1\u007fD2\x01\b\xfd\xd4NK\x04\v\x19'>*\xd8%\xfeR=\x05\x06\x01\ff\x19\r07\x02\x83\x01\x92\xf3=.\r\x18f\f\x1bD\xfd]\\|yu\x11\x00\x00\a\x00\x00\xff\x80\x06\x00\x05\x80\x00\x11\x00,\x000\x00>\x00S\x00e\x00u\x00\x00\x01\x15\x14\x16\x0e\x04#\x112\x1e\x03\x1c\x01\x05\x15\x14\x16\x0e\x02#\"'&5<\x03>\x0232\x1e\x03\x1c\x01\x053\x11#\x013\x11#\a&'#\x113\x11\x133\x13\x054'.\x05\"#\"+\x01\x1123\x166'&\x0554.\x02#\"\a5#\x1137\x16326\x13\x11\x14\x06#!\"&5\x11463!2\x16\x03\x9a\x01\x01\x02\x05\b\x0e\t\t\x0e\b\x05\x02\x01<\x01\x01\x04\v\b\t\x05\x04\x03\x04\x06\x05\x06\b\x05\x03\x01\xfb\xdezz\x01\xb2j\x9f\x1c\x14\f\x9ek-L+\x01\xa9\x05\x03\x10\x12 \x15)\x11\x15\b\x04[\x14$\xa98\x03\x01\x01=\x04\x0f\"\x1d.\x1fun\a\x1e/2 \xb4^B\xfb@B^^B\x04\xc0B^\x02\xe3\xb6\x04\x16\b\x10\a\b\x03\x015\x02\b\x03\x10\x05\x16cy\x01\x17\b\x0f\x06\t\n\x9b\x02\n\a\v\x06\b\x03\x03\x06\x06\v\x05\x0e\xee\x01\xd8\xfe(\x01\xd8ݔI\xfe(\x018\xfe\xc8\x01?\x0eC\x17\x10\x19\x10\f\x05\x03\xfe(\x013\x9b>\x9f\x85\x1d #\x0f\"\x9a\xfe(\x1e$=\x03\x12\xfb@B^^B\x04\xc0B^^\x00\x00\x00\x00\x05\x000\xff\x02\bK\x05\xf8\x00\f\x00\x15\x00\x1a\x00S\x00\x8f\x00\x00\x05&'.\x04'&'\x16\x00\x01\x17.\x01/\x01\x06\a\x16\x13\x06\a67\x014\x02&$#\"\x04\a\x06\a>\x03\x1f\x01\x1e\x03\a&\x0e\x02\a\x1e\x02\x17\x16>\x02?\x01>\x01\x16\x17\x16\a\x06\x05\x06'\x1e\x03\x1f\x01\x1676\x12\x13\x06\a\x06\x02\a\x06\a\x06'\x06# \x00\x03\"&#\x06\x1e\x02\x1f\x01\x16\x17.\x03/\x01.\x06'\x1e\x02\x177676767>\x0176$\x04\x17\x16\x12\x04w\x06\x05\r.~ku\x1f\x11\x9eB\x01R\xfe]\xa8\x19 \x03\x04T%\x05z+\",\x1e\x05\xa0|\xd3\xfeޟ\x93\xfe\xf4j\x1e\x0f<\xa6\x97\x87)(!(\t\x04\x03~ˣzF\x04\x0f8\"{\xf9\xb4\x91%%\x16#\x1a\x04\x0e5\xd0\xfe\xfd\x87\xb6)\x8a\x88}''\x8fx\xc3\xeeJ\x0e\x1aF\xdf\xcf0\"H[$%\xfe\xe5\xfeEJ\x01\x06\x02\x06\x11#%\r\x0e\b.Gk2\x1d\x03\x02\x059(B13\"\b\x13?\xa3@\x02\vS)\x87\x1c5\x0f\" \x9e\x01#\x019\x96\xdc\xe2\xc5\x01\x03\b\x1edm\xabW\x03\"\xd5\xfe\xd6\x02;\x1cL\xb765R\x8eA\x020@T.\x16\xfe\x9e\xa1\x01$\xd4}i`:f3A\x15\x06\x04\x03\x01\x1d%%\n\v\x15BM<$q\xf3:\x06)BD\x19\x18\x10\t\x13\x19a\x18a%\x14\x04`\xa1]A\v\f\x17&c\x01|\x01\t\x87M\xd0\xfe\xebs!\v\x1a\n\x03\x01Z\x01\r\x012}i[\x1a\x1a\fF&\x89\x8f\x83**\x02\x15\x0f\x1a\x18\x1b\x1b\f\n\x1f<\b \x95\x8dʣsc\x1c\"\x0fJ<&Ns\xfeF\x00\x05\x00%\xff\f\x06\xd8\x05\xf4\x00\x17\x000\x00@\x00W\x00m\x00\x00\x016&'.\x01\x06\a\x06\x16\x17\x1e\x02\x17\x1e\a6\x01\x0e\x02\x04$.\x01\x027>\x037\x06\x1a\x01\f\x01$76\a\x14\x02\x14\x0e\x02\".\x024>\x022\x1e\x01\x05.\x01,\x01\f\x01\x06\x02\x17&\x02>\x04\x1e\x02\x17\x1e\x01\x036\x00'\"'&7\x1e\x04\x0e\x03\a>\x03\x05=\x1dGV:\x87e\x12\f\x0f#\x17\x1f:\x1b$?+%\x18\x14\r\v\n\x01q4\xc1\xec\xfe\xf2\xfe\xfa\xf0\xb4g\x05\x01\x0f\n&\x043h\xf2\x01T\x01`\x01Zt\x14\x02\xf3Q\x88\xbcм\x88QQ\x88\xbcм\x88\x01pA\xe7\xfe\xed\xfe\xcb\xfe\xdb\xfe\xfe\xb6P\x1e1\x05L\x8e\xbd\xe1\xef\xf6\xe2\xceK!:<\f\xfe\xd7\xf8\b\x02\x02\x1a}҈`\x15\x17d\x91\xe1\x88l\xbb\xa1b\x02\xf0,\xab9'\x1d\x14\x1b\x17\n\x05\x03\x04\x0f\n\r%%($!\x18\r\x01\xfd\xcb\u007f\xbaa\x183\x83\xc0\x01\x17\xa4)W)x\r\xd0\xfe\x86\xfe\xfe\x9a\f\xa1\xa4\x1b\r\x04\x02\x1fо\x8aQQ\x8a\xbeо\x8aQQ\x8a\x06\x93\xd0c\bQ\xb1\xf6\xfe\xa4ǡ\x01-\xf4җe)\x17U\xa4s2\x8e\xfe\x81\xf4\x01XD\x05\x05\x03\x04\\\x94\xbd\xd1ϼ\x92Y\x02\x1ed\x92\xcf\x00\x00\x00\x00\v\x00\x00\xff\x80\x06\x00\x06\x00\x00\x0f\x00\x1f\x00/\x00?\x00O\x00_\x00o\x00\u007f\x00\x8f\x00\x9f\x00\xaf\x00\x00\x13\x15#\"=\x01#\"=\x014;\x01543\x13\x15#\"=\x01#\"=\x014;\x01543\x13\x15#\"=\x01#\"=\x014;\x01543\x13\x15#\"=\x01#\"=\x014;\x01543\x13\x15#\"=\x01#\"=\x014;\x01543%\x11\x14\x06#!\"&5\x11463!2\x16\x01\x15\x14+\x01\x15\x14+\x01532\x1d\x01325\x15\x14+\x01\x15\x14+\x01532\x1d\x01325\x15\x14+\x01\x15\x14+\x01532\x1d\x01325\x15\x14+\x01\x15\x14+\x01532\x1d\x01325\x15\x14+\x01\x15\x14+\x01532\x1d\x0132\xc0p\x100\x10\x100\x10pp\x100\x10\x100\x10pp\x100\x10\x100\x10pp\x100\x10\x100\x10pp\x100\x10\x100\x10\x04\xb08(\xfc\xc0(88(\x03@(8\x01\x00\x100\x10pp\x100\x10\x100\x10pp\x100\x10\x100\x10pp\x100\x10\x100\x10pp\x100\x10\x100\x10pp\x100\x10\x01\x00\x80\x10\x10\x10 \x10\x10\x10\x01\x00\x80\x10\x10\x10 \x10\x10\x10\x01\x00\x80\x10\x10\x10 \x10\x10\x10\x01\x00\x80\x10\x10\x10 \x10\x10\x10\x01\x00\x80\x10\x10\x10 \x10\x10\x10\xa0\xfa@(88(\x05\xc0(88\xfb\b \x10\x10\x10\x80\x10\x10\xf0 \x10\x10\x10\x80\x10\x10\xf0 \x10\x10\x10\x80\x10\x10\xf0 \x10\x10\x10\x80\x10\x10\xf0 \x10\x10\x10\x80\x10\x10\x00\x00\x00\x00\x01\x00/\xff\x00\x06Q\x06\x00\x00\x90\x00\x00\x01\a\x17\x1e\x01\a\x0e\x01/\x01\x17\x16\x06&'\x03%\x11\x17\x1e\x01\x0e\x01&/\x01\x15\x14\x06\"&=\x01\a\x0e\x01.\x016?\x01\x11\x05\x03\x0e\x01&?\x01\a\x06&'&6?\x01'.\x01>\x01\x17\x05-\x01\x05\x06#\".\x016?\x01'.\x01>\x01\x1f\x01'&6\x16\x17\x13\x05\x11'.\x01>\x01\x16\x1f\x015462\x16\x1d\x017>\x01\x1e\x01\x06\x0f\x01\x11%\x13>\x01\x16\x0f\x0176\x16\x17\x16\x06\x0f\x01\x17\x1e\x01\x0e\x01#\"'%\r\x01%6\x1e\x01\x06\x06\x1e\xa7\xba\x17\r\r\x0e2\x17\xba7\r2G\rf\xfe\xf1\xd0\x10\x02\x18!)\x10p&4&p\x10)!\x18\x02\x10\xd0\xfe\xf1f\rG2\r7\xba\x172\x0e\r\r\x17\xba\xa7\x1d\x1a\t*\x1d\x016\x01\x0f\xfe\xf1\xfe\xca\x04\t\x1b\"\x04\x1a\x1b\xa7\xba\x17\r\x1a4\x16\xba7\r2G\rf\x01\x0f\xd0\x10\x02\x18!)\x10p&4&p\x10)!\x18\x02\x10\xd0\x01\x0ff\rG2\r7\xba\x172\x0e\r\r\x17\xba\xa7\x1b\x1a\x04\"\x1b\t\x04\xfe\xca\xfe\xf1\x01\x0f\x016\x1d*\t\x1a\x01\xa3!k\r3\x17\x17\r\rj\xa0&3\n%\x01,\x9c\xfe\xc7\xee\x12*\x1f\x13\b\x12\x80\xd6\x1a&&\x1aր\x12\b\x13\x1f*\x12\xee\x019\x9c\xfe\xd4%\n3&\xa0j\r\r\x17\x173\rk!\x06./!\x06>\x9d\x9d>\x01$,*\x05!k\r3.\x0e\x0ej\xa0&3\n%\xfeԜ\x019\xee\x12*\x1f\x13\b\x12\x80\xd6\x1a&&\x1aր\x12\b\x13\x1f*\x12\xee\xfeǜ\x01,%\n3&\xa0j\r\r\x17\x173\rk!\x05*,$\x01>\x9d\x9d>\x06!/.\x00\x00\x00\x00\x02\x00\x00\xff\x00\a\x00\x06\x00\x00\x12\x00&\x00\x00\x016.\x02'&\x0e\x02\a\x06\x1e\x02\x17\x16$\x12\t\x01\x16\x12\a\x06\x02\x04\a\x05\x01&\x0276\x12$76$\x05\xc1\aP\x92\xd0utۥi\a\aP\x92\xd1u\x9b\x01\x14\xac\x01G\xfe\xa3xy\n\v\xb6\xfeԶ\xfc\x19\x01[xy\n\v\xb6\x01-\xb6\xa7\x02\x9a\x02_v١e\a\aN\x8f\xcfuv١e\a\t\x88\x00\xff\x04=\xfe\xa4u\xfeʦ\xb7\xfe\xc8\xc7\x19\x84\x01[t\x017\xa6\xb8\x018\xc7\x19\x16X\x00\x06\x00\x00\xff\x00\a\x00\x06\x00\x00\n\x00\x0e\x00\x12\x00\x16\x00&\x006\x00\x00\x01\x13#\v\x01#\x13'7\x17\a\x01\x05\x03-\x01\x17\a'%\x17\a'\x04\x10\x02&$ \x04\x06\x02\x10\x12\x16\x04 $6\x12\x10\x02\x06\x04 $&\x02\x10\x126$ \x04\x16\x03\xb4\xa33\xaf\xab1\xb3N\x15\xf0\x15\xfeE\x010\x82\xfe\xd0\x01\xda\xf0g\xef\x01\u007f\xbfR\xbe\x02=|\xd3\xfe\xde\xfe\xc2\xfe\xde\xd3||\xd3\x01\"\x01>\x01\"\xd3\xec\x8e\xf0\xfe\xb4\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x01\xfc\xfe\xb7\x01^\xfe\xa2\x01v!1f2\x02i\x82\xfeЂwg\xeffZQ\xbeQ^\x01>\x01\"\xd3||\xd3\xfe\xde\xfe\xc2\xfe\xde\xd3||\xd3\x02w\xfe\x94\xfe\xb4\xf0\x8e\x8e\xf0\x01L\x01l\x01L\xf0\x8e\x8e\xf0\x00\f\x00&\xff\x01\aZ\x05\xff\x00X\x00b\x00l\x00w\x00\x81\x00\xab\x00\xb7\x00\xc2\x00\xcd\x00\xd8\x00\xe4\x00\xee\x00\x00\x01.\x03'&>\x01'&'&\x0f\x01\x0e\x03\".\x01'.\x06'&\x06\a\x0e\x03&'&'&\x06\a\x0e\x03\x15\x06\x167>\x0176\x127>\x01\x17\x16\a\x0e\x01\a\x06\x1667>\x0276\x172\a\x06\x02\a\x06\x16\x17\x1e\x026\x04\x16\x06\a\x06&'&>\x01\x01\x16\x0e\x01&'&>\x01\x16\x00\x0e\x01'.\x017>\x01\x17\x16\x01\x16\x0e\x01.\x01676\x16\x13\x16\x02\a\x06'\x0e\x01&'\x06\a\x06&'&'.\x0267.\x01>\x017>\x02\x16\x176\x1e\x03\a\x1e\x02\x06\x01\x16\x06\a\x06&'&676\x16\x13\x16\x0e\x01&'&676\x16\x01\x16\x06\a\x06.\x01676\x16\x01\x16\x06\a\x06&'&>\x01\x16\x01\x16\x06\a\x06&'&676\x16'\x16\x06\a\x06.\x01>\x01\x16\x056\x04/4-\x03\x05LJ\x05\x0eg-\x1e\x03\x04\x02\a\x03\a\x05\a\x03\x03\f\x06\v\b\v\v\x06\x1e$\x1b\x01\x10\t\x15\f\v6\x1e)j\x17\x102%+\x16QF\x1e)\x12\a\x90\x05\x06\x1f\x0e\x1b\x06\x02b\x01\x063F\x14\x04SP\x06\x14\x15\x1d\x04\x02\u007f\a\f21\x11DK2\xfcA\x06\x10\x0f\x0e\x19\x03\x03\x10\x1c\x02W\f\a\")\f\v\a\")\xfd\x15$?\x1a\x1a\f\x12\x12?\x1a\x1a\x05\x04\x13\f8A&\f\x1b\x1cA\x84E5lZm\x14\x81\x9e=\f\x01g\xf4G2\x03Sw*&>$\x045jD \x86\x9f\xb1GH\x88yX/\x064F\x15 \xfbr\x0e\t\x14\x131\r\x0e\t\x14\x131\xac\x04\x12\"\x1c\x04\x03\x13\x10\x11\x1c\x04\xa5\x04\x15\x14\x13\"\b\x15\x14\x14!\xfdl\x10\x0f\x1c\x1b=\x10\x10\x0f6>\x02\xfa\x04\x10\x0f\x0f\x19\x03\x03\x10\x0f\x0e\x19\xbc\x0f\t\x16\x166\x1e\n,5\x01.\x18\x14\x01\x18\x1a/\xb9\xb1'e\x02\x01\x11\x02\x02\x01\x03\x01\x03\x04\x03\x02\r\x05\n\x05\x06\x03\x01\x05\x10\x17\x01\x0f\a\r\x02\x02\x1b\r\x12.*\x1c\x8d|\x90\x01Ed\x04\x02\x1a!\r\x01u\b\v\x0e\a\x0f&\x12\xf3\v&%\x17&\b\xa8\x9f\t\x1d\x01&\x10\xfe\xf9\x1c5d\x18\t\r\x03\x1f\xa8\x1e\x19\x03\x03\x10\x0f\x0e\x1a\x06\xfe\xda\x11)\x18\b\x11\x11)\x18\b\x0366\f\x13\x12@\x1a\x1b\f\x12\x13\xfd\x01\x1cC&\f8B\x14\x13\f\x02@q\xfe\xf9L?\x03P^\x057\t\x01G-hI[\x0eq\x8f\xa1:<\x88rS\tU~9\x177\x15\aA_\x87I\x10R`g\x02p\x141\x0e\x0e\t\x14\x141\x0e\x0e\t\x01\x05\x10\x1d\b\x13\x11\x11\x1c\x04\x04\x13\xfc;\x14\"\x04\x04\x15(\"\x05\x04\x17\x03j\x1b?\x10\x10\x0f\x1b\x1c>\"\x10\xfdT\x0f\x19\x04\x03\x11\x0e\x0f\x1a\x03\x03\x10\xe2\x166\x10\x0f\n,6 \n\x00\x00\x00\x18\x01&\x00\x01\x00\x00\x00\x00\x00\x00\x00/\x00`\x00\x01\x00\x00\x00\x00\x00\x01\x00\v\x00\xa8\x00\x01\x00\x00\x00\x00\x00\x02\x00\a\x00\xc4\x00\x01\x00\x00\x00\x00\x00\x03\x00\x11\x00\xf0\x00\x01\x00\x00\x00\x00\x00\x04\x00\v\x01\x1a\x00\x01\x00\x00\x00\x00\x00\x05\x00\x12\x01L\x00\x01\x00\x00\x00\x00\x00\x06\x00\v\x01w\x00\x01\x00\x00\x00\x00\x00\a\x00Q\x02'\x00\x01\x00\x00\x00\x00\x00\b\x00\f\x02\x93\x00\x01\x00\x00\x00\x00\x00\t\x00\n\x02\xb6\x00\x01\x00\x00\x00\x00\x00\v\x00\x15\x02\xed\x00\x01\x00\x00\x00\x00\x00\x0e\x00\x1e\x03A\x00\x03\x00\x01\x04\t\x00\x00\x00^\x00\x00\x00\x03\x00\x01\x04\t\x00\x01\x00\x16\x00\x90\x00\x03\x00\x01\x04\t\x00\x02\x00\x0e\x00\xb4\x00\x03\x00\x01\x04\t\x00\x03\x00\"\x00\xcc\x00\x03\x00\x01\x04\t\x00\x04\x00\x16\x01\x02\x00\x03\x00\x01\x04\t\x00\x05\x00$\x01&\x00\x03\x00\x01\x04\t\x00\x06\x00\x16\x01_\x00\x03\x00\x01\x04\t\x00\a\x00\xa2\x01\x83\x00\x03\x00\x01\x04\t\x00\b\x00\x18\x02y\x00\x03\x00\x01\x04\t\x00\t\x00\x14\x02\xa0\x00\x03\x00\x01\x04\t\x00\v\x00*\x02\xc1\x00\x03\x00\x01\x04\t\x00\x0e\x00<\x03\x03\x00C\x00o\x00p\x00y\x00r\x00i\x00g\x00h\x00t\x00 \x00D\x00a\x00v\x00e\x00 \x00G\x00a\x00n\x00d\x00y\x00 \x002\x000\x001\x006\x00.\x00 \x00A\x00l\x00l\x00 \x00r\x00i\x00g\x00h\x00t\x00s\x00 \x00r\x00e\x00s\x00e\x00r\x00v\x00e\x00d\x00.\x00\x00Copyright Dave Gandy 2016. All rights reserved.\x00\x00F\x00o\x00n\x00t\x00A\x00w\x00e\x00s\x00o\x00m\x00e\x00\x00FontAwesome\x00\x00R\x00e\x00g\x00u\x00l\x00a\x00r\x00\x00Regular\x00\x00F\x00O\x00N\x00T\x00L\x00A\x00B\x00:\x00O\x00T\x00F\x00E\x00X\x00P\x00O\x00R\x00T\x00\x00FONTLAB:OTFEXPORT\x00\x00F\x00o\x00n\x00t\x00A\x00w\x00e\x00s\x00o\x00m\x00e\x00\x00FontAwesome\x00\x00V\x00e\x00r\x00s\x00i\x00o\x00n\x00 \x004\x00.\x007\x00.\x000\x00 \x002\x000\x001\x006\x00\x00Version 4.7.0 2016\x00\x00F\x00o\x00n\x00t\x00A\x00w\x00e\x00s\x00o\x00m\x00e\x00\x00FontAwesome\x00\x00P\x00l\x00e\x00a\x00s\x00e\x00 \x00r\x00e\x00f\x00e\x00r\x00 \x00t\x00o\x00 \x00t\x00h\x00e\x00 \x00C\x00o\x00p\x00y\x00r\x00i\x00g\x00h\x00t\x00 \x00s\x00e\x00c\x00t\x00i\x00o\x00n\x00 \x00f\x00o\x00r\x00 \x00t\x00h\x00e\x00 \x00f\x00o\x00n\x00t\x00 \x00t\x00r\x00a\x00d\x00e\x00m\x00a\x00r\x00k\x00 \x00a\x00t\x00t\x00r\x00i\x00b\x00u\x00t\x00i\x00o\x00n\x00 \x00n\x00o\x00t\x00i\x00c\x00e\x00s\x00.\x00\x00Please refer to the Copyright section for the font trademark attribution notices.\x00\x00F\x00o\x00r\x00t\x00 \x00A\x00w\x00e\x00s\x00o\x00m\x00e\x00\x00Fort Awesome\x00\x00D\x00a\x00v\x00e\x00 \x00G\x00a\x00n\x00d\x00y\x00\x00Dave Gandy\x00\x00h\x00t\x00t\x00p\x00:\x00/\x00/\x00f\x00o\x00n\x00t\x00a\x00w\x00e\x00s\x00o\x00m\x00e\x00.\x00i\x00o\x00\x00http://fontawesome.io\x00\x00h\x00t\x00t\x00p\x00:\x00/\x00/\x00f\x00o\x00n\x00t\x00a\x00w\x00e\x00s\x00o\x00m\x00e\x00.\x00i\x00o\x00/\x00l\x00i\x00c\x00e\x00n\x00s\x00e\x00/\x00\x00http://fontawesome.io/license/\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xc3\x00\x00\x00\x01\x00\x02\x00\x03\x00\x8e\x00\x8b\x00\x8a\x00\x8d\x00\x90\x00\x91\x00\x8c\x00\x92\x00\x8f\x01\x02\x01\x03\x01\x04\x01\x05\x01\x06\x01\a\x01\b\x01\t\x01\n\x01\v\x01\f\x01\r\x01\x0e\x01\x0f\x01\x10\x01\x11\x01\x12\x01\x13\x01\x14\x01\x15\x01\x16\x01\x17\x01\x18\x01\x19\x01\x1a\x01\x1b\x01\x1c\x01\x1d\x01\x1e\x01\x1f\x01 \x01!\x01\"\x01#\x01$\x01%\x01&\x01'\x01(\x01)\x01*\x01+\x01,\x01-\x01.\x01/\x010\x011\x012\x013\x014\x015\x016\x017\x018\x019\x01:\x01;\x01<\x01=\x01>\x01?\x01@\x01A\x01B\x01C\x01D\x01E\x01F\x01G\x01H\x01I\x01J\x01K\x01L\x01M\x01N\x01O\x01P\x01Q\x01R\x01S\x01T\x01U\x01V\x01W\x01X\x01Y\x01Z\x01[\x01\\\x01]\x01^\x01_\x01`\x01a\x01b\x00\x0e\x00\xef\x00\r\x01c\x01d\x01e\x01f\x01g\x01h\x01i\x01j\x01k\x01l\x01m\x01n\x01o\x01p\x01q\x01r\x01s\x01t\x01u\x01v\x01w\x01x\x01y\x01z\x01{\x01|\x01}\x01~\x01\u007f\x01\x80\x01\x81\x01\x82\x01\x83\x01\x84\x01\x85\x01\x86\x01\x87\x01\x88\x01\x89\x01\x8a\x01\x8b\x01\x8c\x01\x8d\x01\x8e\x01\x8f\x01\x90\x01\x91\x01\x92\x01\x93\x01\x94\x01\x95\x01\x96\x01\x97\x01\x98\x01\x99\x01\x9a\x01\x9b\x01\x9c\x01\x9d\x01\x9e\x01\x9f\x01\xa0\x01\xa1\x01\xa2\x01\xa3\x01\xa4\x01\xa5\x01\xa6\x01\xa7\x01\xa8\x01\xa9\x01\xaa\x01\xab\x01\xac\x01\xad\x01\xae\x01\xaf\x01\xb0\x01\xb1\x01\xb2\x01\xb3\x01\xb4\x01\xb5\x01\xb6\x01\xb7\x01\xb8\x01\xb9\x01\xba\x01\xbb\x01\xbc\x01\xbd\x01\xbe\x01\xbf\x01\xc0\x01\xc1\x01\xc2\x01\xc3\x01\xc4\x01\xc5\x01\xc6\x01\xc7\x01\xc8\x01\xc9\x01\xca\x01\xcb\x01\xcc\x01\xcd\x01\xce\x01\xcf\x01\xd0\x01\xd1\x01\xd2\x01\xd3\x01\xd4\x01\xd5\x01\xd6\x01\xd7\x01\xd8\x01\xd9\x01\xda\x01\xdb\x01\xdc\x01\xdd\x01\xde\x01\xdf\x01\xe0\x01\xe1\x01\xe2\x01\xe3\x01\xe4\x01\xe5\x01\xe6\x01\xe7\x01\xe8\x01\xe9\x01\xea\x01\xeb\x01\xec\x01\xed\x01\xee\x01\xef\x01\xf0\x01\xf1\x01\xf2\x01\xf3\x01\xf4\x01\xf5\x01\xf6\x01\xf7\x01\xf8\x01\xf9\x01\xfa\x01\xfb\x01\xfc\x01\xfd\x01\xfe\x01\xff\x02\x00\x02\x01\x02\x02\x02\x03\x02\x04\x02\x05\x02\x06\x02\a\x02\b\x00\"\x02\t\x02\n\x02\v\x02\f\x02\r\x02\x0e\x02\x0f\x02\x10\x02\x11\x02\x12\x02\x13\x02\x14\x02\x15\x02\x16\x02\x17\x02\x18\x02\x19\x02\x1a\x02\x1b\x02\x1c\x02\x1d\x02\x1e\x02\x1f\x02 \x02!\x02\"\x02#\x02$\x02%\x02&\x02'\x02(\x02)\x02*\x02+\x02,\x02-\x02.\x02/\x020\x021\x022\x023\x024\x025\x026\x027\x028\x029\x02:\x02;\x02<\x02=\x02>\x02?\x02@\x02A\x02B\x02C\x02D\x02E\x02F\x02G\x02H\x02I\x02J\x02K\x02L\x02M\x02N\x02O\x02P\x02Q\x02R\x02S\x00\xd2\x02T\x02U\x02V\x02W\x02X\x02Y\x02Z\x02[\x02\\\x02]\x02^\x02_\x02`\x02a\x02b\x02c\x02d\x02e\x02f\x02g\x02h\x02i\x02j\x02k\x02l\x02m\x02n\x02o\x02p\x02q\x02r\x02s\x02t\x02u\x02v\x02w\x02x\x02y\x02z\x02{\x02|\x02}\x02~\x02\u007f\x02\x80\x02\x81\x02\x82\x02\x83\x02\x84\x02\x85\x02\x86\x02\x87\x02\x88\x02\x89\x02\x8a\x02\x8b\x02\x8c\x02\x8d\x02\x8e\x02\x8f\x02\x90\x02\x91\x02\x92\x02\x93\x02\x94\x02\x95\x02\x96\x02\x97\x02\x98\x02\x99\x02\x9a\x02\x9b\x02\x9c\x02\x9d\x02\x9e\x02\x9f\x02\xa0\x02\xa1\x02\xa2\x02\xa3\x02\xa4\x02\xa5\x02\xa6\x02\xa7\x02\xa8\x02\xa9\x02\xaa\x02\xab\x02\xac\x02\xad\x02\xae\x02\xaf\x02\xb0\x02\xb1\x02\xb2\x02\xb3\x02\xb4\x02\xb5\x02\xb6\x02\xb7\x02\xb8\x02\xb9\x02\xba\x02\xbb\x02\xbc\x02\xbd\x02\xbe\x02\xbf\x02\xc0\x02\xc1\x02\xc2\x02\xc3\x02\xc4\x02\xc5\x02\xc6\x02\xc7\x02\xc8\x02\xc9\x02\xca\x02\xcb\x02\xcc\x02\xcd\x02\xce\x02\xcf\x02\xd0\x02\xd1\x02\xd2\x02\xd3\x02\xd4\x02\xd5\x02\xd6\x02\xd7\x02\xd8\x02\xd9\x02\xda\x02\xdb\x02\xdc\x02\xdd\x02\xde\x02\xdf\x02\xe0\x02\xe1\x02\xe2\x02\xe3\x02\xe4\x02\xe5\x02\xe6\x02\xe7\x02\xe8\x02\xe9\x02\xea\x02\xeb\x02\xec\x02\xed\x02\xee\x02\xef\x02\xf0\x02\xf1\x02\xf2\x02\xf3\x02\xf4\x02\xf5\x02\xf6\x02\xf7\x02\xf8\x02\xf9\x02\xfa\x02\xfb\x02\xfc\x02\xfd\x02\xfe\x02\xff\x03\x00\x03\x01\x03\x02\x03\x03\x03\x04\x03\x05\x03\x06\x03\a\x03\b\x03\t\x03\n\x03\v\x03\f\x03\r\x03\x0e\x03\x0f\x03\x10\x03\x11\x03\x12\x03\x13\x03\x14\x03\x15\x03\x16\x03\x17\x03\x18\x03\x19\x03\x1a\x03\x1b\x03\x1c\x03\x1d\x03\x1e\x03\x1f\x03 \x03!\x03\"\x03#\x03$\x03%\x03&\x03'\x03(\x03)\x03*\x03+\x03,\x03-\x03.\x03/\x030\x031\x032\x033\x034\x035\x036\x037\x038\x039\x03:\x03;\x03<\x03=\x03>\x03?\x03@\x03A\x03B\x03C\x03D\x03E\x03F\x03G\x03H\x03I\x03J\x03K\x03L\x03M\x03N\x03O\x03P\x03Q\x03R\x03S\x03T\x03U\x03V\x03W\x03X\x03Y\x03Z\x03[\x03\\\x03]\x03^\x03_\x03`\x03a\x03b\x03c\x03d\x03e\x03f\x03g\x03h\x03i\x03j\x03k\x03l\x03m\x03n\x03o\x03p\x03q\x03r\x03s\x03t\x03u\x03v\x03w\x03x\x03y\x03z\x03{\x03|\x03}\x03~\x03\u007f\x03\x80\x03\x81\x03\x82\x03\x83\x03\x84\x03\x85\x03\x86\x03\x87\x03\x88\x03\x89\x03\x8a\x03\x8b\x03\x8c\x03\x8d\x03\x8e\x03\x8f\x03\x90\x03\x91\x03\x92\x03\x93\x03\x94\x03\x95\x03\x96\x03\x97\x03\x98\x03\x99\x03\x9a\x03\x9b\x03\x9c\x03\x9d\x03\x9e\x03\x9f\x03\xa0\x03\xa1\x03\xa2\x03\xa3\x03\xa4\x03\xa5\x03\xa6\x03\xa7\x03\xa8\x03\xa9\x03\xaa\x03\xab\x03\xac\x03\xad\x03\xae\x03\xaf\x03\xb0\x03\xb1\x00\x94\x05glass\x05music\x06search\benvelope\x05heart\x04star\nstar_empty\x04user\x04film\bth_large\x02th\ath_list\x02ok\x06remove\azoom_in\bzoom_out\x03off\x06signal\x03cog\x05trash\x04home\bfile_alt\x04time\x04road\fdownload_alt\bdownload\x06upload\x05inbox\vplay_circle\x06repeat\arefresh\blist_alt\x04lock\x04flag\nheadphones\nvolume_off\vvolume_down\tvolume_up\x06qrcode\abarcode\x03tag\x04tags\x04book\bbookmark\x05print\x06camera\x04font\x04bold\x06italic\vtext_height\ntext_width\nalign_left\falign_center\valign_right\ralign_justify\x04list\vindent_left\findent_right\x0efacetime_video\apicture\x06pencil\nmap_marker\x06adjust\x04tint\x04edit\x05share\x05check\x04move\rstep_backward\rfast_backward\bbackward\x04play\x05pause\x04stop\aforward\ffast_forward\fstep_forward\x05eject\fchevron_left\rchevron_right\tplus_sign\nminus_sign\vremove_sign\aok_sign\rquestion_sign\tinfo_sign\nscreenshot\rremove_circle\tok_circle\nban_circle\narrow_left\varrow_right\barrow_up\narrow_down\tshare_alt\vresize_full\fresize_small\x10exclamation_sign\x04gift\x04leaf\x04fire\beye_open\teye_close\fwarning_sign\x05plane\bcalendar\x06random\acomment\x06magnet\nchevron_up\fchevron_down\aretweet\rshopping_cart\ffolder_close\vfolder_open\x0fresize_vertical\x11resize_horizontal\tbar_chart\ftwitter_sign\rfacebook_sign\fcamera_retro\x03key\x04cogs\bcomments\rthumbs_up_alt\x0fthumbs_down_alt\tstar_half\vheart_empty\asignout\rlinkedin_sign\apushpin\rexternal_link\x06signin\x06trophy\vgithub_sign\nupload_alt\x05lemon\x05phone\vcheck_empty\x0ebookmark_empty\nphone_sign\atwitter\bfacebook\x06github\x06unlock\vcredit_card\x03rss\x03hdd\bbullhorn\x04bell\vcertificate\nhand_right\thand_left\ahand_up\thand_down\x11circle_arrow_left\x12circle_arrow_right\x0fcircle_arrow_up\x11circle_arrow_down\x05globe\x06wrench\x05tasks\x06filter\tbriefcase\nfullscreen\x05group\x04link\x05cloud\x06beaker\x03cut\x04copy\npaper_clip\x04save\nsign_blank\areorder\x02ul\x02ol\rstrikethrough\tunderline\x05table\x05magic\x05truck\tpinterest\x0epinterest_sign\x10google_plus_sign\vgoogle_plus\x05money\ncaret_down\bcaret_up\ncaret_left\vcaret_right\acolumns\x04sort\tsort_down\asort_up\fenvelope_alt\blinkedin\x04undo\x05legal\tdashboard\vcomment_alt\fcomments_alt\x04bolt\asitemap\bumbrella\x05paste\nlight_bulb\bexchange\x0ecloud_download\fcloud_upload\auser_md\vstethoscope\bsuitcase\bbell_alt\x06coffee\x04food\rfile_text_alt\bbuilding\bhospital\tambulance\x06medkit\vfighter_jet\x04beer\x06h_sign\x04f0fe\x11double_angle_left\x12double_angle_right\x0fdouble_angle_up\x11double_angle_down\nangle_left\vangle_right\bangle_up\nangle_down\adesktop\x06laptop\x06tablet\fmobile_phone\fcircle_blank\nquote_left\vquote_right\aspinner\x06circle\x05reply\ngithub_alt\x10folder_close_alt\x0ffolder_open_alt\nexpand_alt\fcollapse_alt\x05smile\x05frown\x03meh\agamepad\bkeyboard\bflag_alt\x0eflag_checkered\bterminal\x04code\treply_all\x0fstar_half_empty\x0elocation_arrow\x04crop\tcode_fork\x06unlink\x04_279\vexclamation\vsuperscript\tsubscript\x04_283\fpuzzle_piece\nmicrophone\x0emicrophone_off\x06shield\x0ecalendar_empty\x11fire_extinguisher\x06rocket\x06maxcdn\x11chevron_sign_left\x12chevron_sign_right\x0fchevron_sign_up\x11chevron_sign_down\x05html5\x04css3\x06anchor\nunlock_alt\bbullseye\x13ellipsis_horizontal\x11ellipsis_vertical\x04_303\tplay_sign\x06ticket\x0eminus_sign_alt\vcheck_minus\blevel_up\nlevel_down\ncheck_sign\tedit_sign\x04_312\nshare_sign\acompass\bcollapse\fcollapse_top\x04_317\x03eur\x03gbp\x03usd\x03inr\x03jpy\x03rub\x03krw\x03btc\x04file\tfile_text\x10sort_by_alphabet\x04_329\x12sort_by_attributes\x16sort_by_attributes_alt\rsort_by_order\x11sort_by_order_alt\x04_334\x04_335\fyoutube_sign\ayoutube\x04xing\txing_sign\fyoutube_play\adropbox\rstackexchange\tinstagram\x06flickr\x03adn\x04f171\x0ebitbucket_sign\x06tumblr\vtumblr_sign\x0flong_arrow_down\rlong_arrow_up\x0flong_arrow_left\x10long_arrow_right\awindows\aandroid\x05linux\adribble\x05skype\nfoursquare\x06trello\x06female\x04male\x06gittip\x03sun\x04_366\aarchive\x03bug\x02vk\x05weibo\x06renren\x04_372\x0estack_exchange\x04_374\x15arrow_circle_alt_left\x04_376\x0edot_circle_alt\x04_378\fvimeo_square\x04_380\rplus_square_o\x04_382\x04_383\x04_384\x04_385\x04_386\x04_387\x04_388\x04_389\auniF1A0\x04f1a1\x04_392\x04_393\x04f1a4\x04_395\x04_396\x04_397\x04_398\x04_399\x04_400\x04f1ab\x04_402\x04_403\x04_404\auniF1B1\x04_406\x04_407\x04_408\x04_409\x04_410\x04_411\x04_412\x04_413\x04_414\x04_415\x04_416\x04_417\x04_418\x04_419\auniF1C0\auniF1C1\x04_422\x04_423\x04_424\x04_425\x04_426\x04_427\x04_428\x04_429\x04_430\x04_431\x04_432\x04_433\x04_434\auniF1D0\auniF1D1\auniF1D2\x04_438\x04_439\auniF1D5\auniF1D6\auniF1D7\x04_443\x04_444\x04_445\x04_446\x04_447\x04_448\x04_449\auniF1E0\x04_451\x04_452\x04_453\x04_454\x04_455\x04_456\x04_457\x04_458\x04_459\x04_460\x04_461\x04_462\x04_463\x04_464\auniF1F0\x04_466\x04_467\x04f1f3\x04_469\x04_470\x04_471\x04_472\x04_473\x04_474\x04_475\x04_476\x04f1fc\x04_478\x04_479\x04_480\x04_481\x04_482\x04_483\x04_484\x04_485\x04_486\x04_487\x04_488\x04_489\x04_490\x04_491\x04_492\x04_493\x04_494\x04f210\x04_496\x04f212\x04_498\x04_499\x04_500\x04_501\x04_502\x04_503\x04_504\x04_505\x04_506\x04_507\x04_508\x04_509\x05venus\x04_511\x04_512\x04_513\x04_514\x04_515\x04_516\x04_517\x04_518\x04_519\x04_520\x04_521\x04_522\x04_523\x04_524\x04_525\x04_526\x04_527\x04_528\x04_529\x04_530\x04_531\x04_532\x04_533\x04_534\x04_535\x04_536\x04_537\x04_538\x04_539\x04_540\x04_541\x04_542\x04_543\x04_544\x04_545\x04_546\x04_547\x04_548\x04_549\x04_550\x04_551\x04_552\x04_553\x04_554\x04_555\x04_556\x04_557\x04_558\x04_559\x04_560\x04_561\x04_562\x04_563\x04_564\x04_565\x04_566\x04_567\x04_568\x04_569\x04f260\x04f261\x04_572\x04f263\x04_574\x04_575\x04_576\x04_577\x04_578\x04_579\x04_580\x04_581\x04_582\x04_583\x04_584\x04_585\x04_586\x04_587\x04_588\x04_589\x04_590\x04_591\x04_592\x04_593\x04_594\x04_595\x04_596\x04_597\x04_598\x04f27e\auniF280\auniF281\x04_602\x04_603\x04_604\auniF285\auniF286\x04_607\x04_608\x04_609\x04_610\x04_611\x04_612\x04_613\x04_614\x04_615\x04_616\x04_617\x04_618\x04_619\x04_620\x04_621\x04_622\x04_623\x04_624\x04_625\x04_626\x04_627\x04_628\x04_629\auniF2A0\auniF2A1\auniF2A2\auniF2A3\auniF2A4\auniF2A5\auniF2A6\auniF2A7\auniF2A8\auniF2A9\auniF2AA\auniF2AB\auniF2AC\auniF2AD\auniF2AE\auniF2B0\auniF2B1\auniF2B2\auniF2B3\auniF2B4\auniF2B5\auniF2B6\auniF2B7\auniF2B8\auniF2B9\auniF2BA\auniF2BB\auniF2BC\auniF2BD\auniF2BE\auniF2C0\auniF2C1\auniF2C2\auniF2C3\auniF2C4\auniF2C5\auniF2C6\auniF2C7\auniF2C8\auniF2C9\auniF2CA\auniF2CB\auniF2CC\auniF2CD\auniF2CE\auniF2D0\auniF2D1\auniF2D2\auniF2D3\auniF2D4\auniF2D5\auniF2D6\auniF2D7\auniF2D8\auniF2D9\auniF2DA\auniF2DB\auniF2DC\auniF2DD\auniF2DE\auniF2E0\auniF2E1\auniF2E2\auniF2E3\auniF2E4\auniF2E5\auniF2E6\auniF2E7\x04_698\auniF2E9\auniF2EA\auniF2EB\auniF2EC\auniF2ED\auniF2EE\x00\x00\x00\x00\x00\x00\x01\xff\xff\x00\x02\x00\x01\x00\x00\x00\x0e\x00\x00\x00\x18\x00\x00\x00\x00\x00\x02\x00\x01\x00\x01\x02\xc2\x00\x01\x00\x04\x00\x00\x00\x02\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\xcc=\xa2\xcf\x00\x00\x00\x00\xcbO<0\x00\x00\x00\x00\xd41h\xb9"), + } + filee := &embedded.EmbeddedFile{ + Filename: "favicon.ico", + FileModTime: time.Unix(1576651902, 0), + + Content: string("\x00\x00\x01\x00\x01\x00 \x00\x00\x01\x00 \x00\xa8\x10\x00\x00\x16\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\x00\x01\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x907,\x17U\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9f?0\x9a\x82&\x1b^\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9dA.'\xa0?0\xfb\x82&\x1e\xbbq\x1c\x1c\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9e?0\xb1\x9f?0\xff\x88*\x1f\xc3}#\x1b|\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9d@/<\x9f?0\xff\x9f?0\xff\x8f3%\xc9~#\x1a\xf1y$\x18\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x01\xa3D6\xb9\x9f?0\xff\x9f?0\xff\x9a:+\xe5~#\x1a\xff~$\x1a\x96\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ڨ\x9fR\xbcn_\xc1\xa5C4Ɵ?0\xff\x9e>/\xfe}#\x1a\xf6~#\x1a\xfa|!\x1a'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbf\xbf\x80\x04ڨ\x9e\xd6͎\x83\xc0\xabI9\xff\xaaI8̠@2\xe2\x80%\x1c\xd5~#\x1a\xff}#\x1a\xb1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ۨ\x9fjڨ\x9f\xff֣\x9a֫I9\xff\xabI9\xff\xabI9\xf8\x8a1(\xc0~#\x1a\xff~#\x1a\xff\x80%\x19>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ժ\x95\f٨\x9f\xe7ڨ\x9f\xffڨ\x9f\xfc\xaeP@\xf0\xabI9\xff\xb1UG\xeb\xb1tk\xc4~#\x1a\xff~#\x1a\xff~#\x1b\xca\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00٧\x9f\x80ڨ\x9f\xffڨ\x9f\xffڨ\x9f\xff\xbeoaȫI9\xffܮ\xa6\xc2Х\x9e\xda~#\x1a\xff~#\x1a\xff~#\x1a\xff}\"\x1aZ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbdh^\x1b\xadUH\xb7\xc0ym\xc6٥\x9c\xf9ڨ\x9f\xffϑ\x87\xc1\xacI:\xd9\xe7\xc9\xc4\xd8\xe7\xc9\xc3\xf9\xabM@\xb6\x923(\xee\x913'\xef\x925(َ9\x1c\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbfk\\\x98\xaeRCƟ?0\xff\xa0A3\xe3\xb5fY\xc0Җ\x8f̬J:S\xe8\xc9\xc6Z\xe9\xca\xc5\xff\xc3qd\xbb\xafL<Õ6)\xf7\x935(\xff\x924'u\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbei\\'\xc0k\\\xfa\xb4[L\xbf\x9f?0\xff\x9f?0\xff\x9f?0\xff\xa0>0\xc1\x00\x00\x00\x00\xff\xff\xff\x02\xe9\xca\xc5\xd0\u2daf\xb6\xb5Q?\xff\xb4O?Ԗ8+\xe7\x935(\xed\x96<-\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0j\\\xaf\xc0k\\\xff\xb9aS\u009f?0\xff\x9f?0\xff\x9f?0\xff\x9e>.B\x00\x00\x00\x00\x00\x00\x00\x00\xe9\xc8\xc5F\xf2\xdfܿ\xb7UCߵQ?\xff\xb5P>\xe9\x9d=.ғ5)\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbfi[8\xc0k\\\xfe\xc0k\\\xff\xbegYϟ?0\xff\x9f?0\xff\xa0?0\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\xdbٛ̇y\xbf\xb5Q?\xff\xb5Q?\xff\xb5Q?\xf9\xa5D4\xbe\x965&\"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x00\x00\x01\xbfm`\xa8\xc0k\\\xff\xc0k\\\xff\xc0j\\\xe6\x9f?0\xff\x9f?0\xfd\x9f@00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf3\xe2\xe2,\xed\xd5\xd1\xe1\xb5Q?\xfe\xb5Q?\xff\xb5Q?\xff\xb5Q?\xff\xaeQ<\x94\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9e>/W\xa5J<\xcf՜\x93\xc2\xc0k\\\xff\xc0k\\\xfd\xa0@2\xf8\x9f?0\x9f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf6\xe9褺[JҵQ?\xff\xb5Q?\xff\xb5Q?\xff\xabZN\xb6}%\x1c7\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xaa\xaa\x03\xbesh\xa0\xa0?0\xf1ӟ\x98\xcf⸱\xc2\xc1n_\xf8\xa5G8ע<3\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf7\xe6\xe6\x1fє\x89\xbc\xb5Q?\xff\xb5Q?\xff\xbddUʲf\\\xce~#\x1a\xc3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ک\x9fȟ\x82\xbf\xaaI8ѤG7\xd0\xe9\xc9\xc4\xfd\xe7\xc6\xc0\u05fdrbp\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xeb\xd1̀\xb5Q?\xfa\xb6QA\xfd˄w׳h\\\xd0~#\x1a\xff\x80\"\x19R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00㪪\tک\xa0\xe3і\x8b«I9\xff\xaaH9\xcbʍ\x83\xc4\xe9\xcb\xc5\xee\xe4\xc9\xc9\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1\xf1\xe3\x12\xbc_PÿiZ\xc4ˆy\xff\xb3i]\xd1~#\x1a\xff~#\x1aր@\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ک\x9e|ڨ\x9f\xffԝ\x92ɫI9\xff\xabI9\xff\xacN=\xc8⽺h\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc2p``ʅx\xe4ˆy\xff\xb6k_\xd2~#\x1a\xff~#\x1a\xff~$\x1ak\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00٦\x99\x14ڨ\x9f\xf1ڨ\x9f\xff֢\x98ӫI9\xff\xabI9\xff\xabJ9\u07b6II\a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ےm\aˆy\xdeˆy\xff\xb6m_\xd3~#\x1a\xff~#\x1a\xff~#\x1a\xe8v'\x14\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ڨ\x9f\x90ڨ\x9f\xffڨ\x9f\xffإ\x9c\xe1\xabI9\xff\xabI9\xff\xaaI8W\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ʇxWˆy\xff\xb8ma\xd5~#\x1a\xff~#\x1a\xff~#\x1a\xff\u007f#\x1b\x85\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ק\x9f ڨ\x9f\xf8ڨ\x9f\xffڨ\x9f\xff٨\x9e\xf2\xabI9\xff\xabI9\xcb\xff\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x01ˆyʹoc\xd6~#\x1a\xff~#\x1a\xff~#\x1a\xff~#\x1a\xf5{&\x1c\x1b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ڨ\x9f\xa5ڨ\x9f\xffڨ\x9f\xffڨ\x9f\xffڨ\x9f\xff\xacL;\xf8\xabH9C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00͇xB\xbbpd\xd8~#\x1a\xff~#\x1a\xff~#\x1a\xff~#\x1a\xff\u007f#\x1a\x9f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00٨\x9d/ڨ\x9f\xfdڨ\x9f\xffڨ\x9f\xffڨ\x9f\xffڨ\x9f\xff\xb3XI\xa5\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4h^\x9a~#\x1a\xff~#\x1a\xff~#\x1a\xff~#\x1a\xff~#\x1a\xfc\x80!\x1c.\x00\x00\x00\x00\x00\x00\x00\x00۩\x9eGۧ\x9fwۧ\x9fwۧ\x9fwۧ\x9fwۧ\x9fwŃu#\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x97H@ ~\"\x1aw~\"\x1aw~\"\x1aw~\"\x1aw~\"\x1aw~$\x19G\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xfe\u007f\xff\xff\xfc\u007f\xff\xff\xfc?\xff\xff\xf8\x1f\xff\xff\xf8\x1f\xff\xff\xf0\x0f\xff\xff\xf0\x0f\xff\xff\xe0\a\xff\xff\xc0\a\xff\xff\xc0\x03\xff\xff\x81\x83\xff\xff\x81\x81\xff\xff\x03\xc0\xff\xff\x03\xc0\xff\xfe\a\xe0\u007f\xfe\a\xe0\u007f\xfc\x0f\xf0?\xfc\x1f\xf0?\xf8\x1f\xf8\x1f\xf8?\xfc\x1f\xf0?\xfc\x0f\xe0\u007f\xfe\a\xe0\u007f\xfe\a\xc0\xff\xff\x03\xc0\xff\xff\x03\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"), + } + filef := &embedded.EmbeddedFile{ + Filename: "fee66e712a8a08eef5805a46892932ad.woff", + FileModTime: time.Unix(1576651902, 0), + + Content: string("wOFF\x00\x01\x00\x00\x00\x01~\xe8\x00\r\x00\x00\x00\x02\x86\xac\x00\x04\x00\a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00FFTM\x00\x00\x010\x00\x00\x00\x1c\x00\x00\x00\x1ck\xbeG\xb9GDEF\x00\x00\x01L\x00\x00\x00\x1f\x00\x00\x00 \x02\xf0\x00\x04OS/2\x00\x00\x01l\x00\x00\x00>\x00\x00\x00`\x882z@cmap\x00\x00\x01\xac\x00\x00\x01i\x00\x00\x02\xf2\n\xbf:\u007fgasp\x00\x00\x03\x18\x00\x00\x00\b\x00\x00\x00\b\xff\xff\x00\x03glyf\x00\x00\x03 \x00\x01_y\x00\x02L\xbc\x8f\xf7\xaeMhead\x00\x01b\x9c\x00\x00\x003\x00\x00\x006\x10\x89\xe5-hhea\x00\x01b\xd0\x00\x00\x00\x1f\x00\x00\x00$\x0f\x03\n\xb5hmtx\x00\x01b\xf0\x00\x00\x02\xf4\x00\x00\n\xf0Ey\x18\x85loca\x00\x01e\xe4\x00\x00\a\x16\x00\x00\v\x10\x02\xf5\xa2\\maxp\x00\x01l\xfc\x00\x00\x00\x1f\x00\x00\x00 \x03,\x02\x1cname\x00\x01m\x1c\x00\x00\x02D\x00\x00\x04\x86㗋\xacpost\x00\x01o`\x00\x00\x0f\x85\x00\x00\x1au\xaf\x8f\x9b\xa1\x00\x00\x00\x01\x00\x00\x00\x00\xcc=\xa2\xcf\x00\x00\x00\x00\xcbO<0\x00\x00\x00\x00\xd41h\xb9x\x9cc`d``\xe0\x03b\t\x06\x10`b`d`d:\x04$Y\xc0<\x06\x00\f\xb8\x00\xf7\x00x\x9cc`f\xcbd\x9c\xc0\xc0\xca\xc0\xc0\xd2\xc3b\xcc\xc0\xc0\xd0\x06\xa1\x99\x8a\x19\x18\x18\xbb\x18\xf0\x80\x82ʢb\x06\a\x06\x85\xaf\fl\f\xff\x81|6\x06F\x900#\x92\x12\x05\x06F\x00\xd0\xcb\bn\x00\x00x\x9c͒\xdfJ\xe2q\x10\xc5\xe7gje\xe6\xf9>\xc0\"\xea\x03D\xbd\x80\xc8>\x80\b{\xd3E\x88O >\x81\xf8\x04\xe2\x13\x88\x97\x1b,\"\xd1u\xc8^\xec\xa5\b[[[\xf9\xc3\xddj\xfbos\xa6\xf5\xd6_\xbfM\xe8\xa2\xeb%:0g80\xcc\a\x86\x11\x91\x05\x99\xd7\a\xf1B\x17\xef.L\xdes\x8ezðפ 1Y\x97\x8clKWv\xe5\x9b\x1ces\xb9t\xae\xa2)Mk^\x8bZֵ֪\xa9m\xed\xea\x8e\x0e\xd4\u05c9Θb\x9ak̳\xc82\xab\xac\xb3\xc96\xbb\xdc\xe3\x80>'\x9cY\xcaҖ\xb7\xa2\x95\xadjukZۺ\xb6g\x03\xf3m2\x95 \b\xc9\x19\xf9\xfc\x8a(\xea4\xab\x05-iEk\xdaЖv\xb4\xa7}\x1d\xeaX\x95B\xc7\f\xd7Y`\x89\x15\xd6\xd8`\x8b\x1d\xf6\xd8\xe7\x90c\xaa\x899\xcbZ\xc1JV\xb1\x9a5\xace\x1d\xebY߆6\xfeG\f\u0382\xad`3\xf8\x14|\f6\xfc\xab\xd1\xfd\xe8\x8b[uI\x97p\xcbn\xc9-\xba\xb8\x8b\xb9\xa8[p\x11L\xf1\x17\x8f0\x10\x8a\aLp\x8f;\xdc\xe2\x06\u05f8\xc2%\xfe\xe0\x02\xe78\xc3o\xfc\xc2\x18>F8\xc5\t\x8e\xf1\x13G8\xc4\x0f\x1c`\x1f\xdfW\xbfί\xfd\xb6\xf2\xe2\xf2\x82\xf5\"\xa1E^\x0f\xcc_\xe1=(\x1eK,F\x93K\xcb+\xffy\xef\x13b\xf9\xc3\xf3\x00\x00\x00\x00\x00\x00\x01\xff\xff\x00\x02x\x9c\xbc\xbd\t\x80TՕ0\xfc\xee\xbdo\xa9}{\xb5uuuwUWի\xean\xe8njmz-\x9a\x9dnv\x04\x04\xc4\x16E\x91EAA\x10\x17J!*\x88\x1b(\xe2\xdehD\xc92c\x16\xf3%F\x9cʦ\x93Eb\x12b6\xbf\xf9\xda$&\x99\xb8\x8c\x93\xe47\x11\xba\x1e߹\xf7UUW7\r\xe8\xcc\xfc\x1ft\xbdw\xf7\xf5\xdc{\xcf9\xf7\x9c\xf38\xccm\xe68b\x13\xe1\xc1I\x1c\x97\tڃ\xc4\x1e\xb4\x0f\xa1\xbc\x9a\u074c\a7\v\x81S\x9bE\xee\x14G\xff!\xee\x923\x9c\xf8\x8c\x90\xe3j\xc0㔐=\x18w;\xc5P\xb0^I\xa6\x13A;RR\xc9n\x94\b\xc6k\x91\xf8LS\xe1.\x94\xf5)\x8ao8G\x9f([\xb8\xab)\x1c\xf3\b9O,,\xcc\bAt\x81S\x92\n\xfc\x11\x0e\xefh\ny\xaau\xbajZ\a\aupPG\x13x\xecN\v\xaeo\xc6\xc9n\x9c\x88{\xec\xc2ho2\x9dA\xe9D\xdc-r\xd3\xd6]\xb5\xe2\xaau\xd3\xe05\xf1\xeae\x85\xd1^\xa5\x96dM\xb6X\x9b\x108=\x18\x9f\xd7\xe4r5ͻ\x02^Q\\\xf5~\xa1\xa32\x80\xbcV\x970 \x8eo\xe30kC\x0e\xda qA跍\v\xd0\x1f\x82\xae\xd6G\x11<\xc2\n\xb69\xd2\xe1\x00\xefv\xb8`\x18\xdc|N\xfdX\xbdW\xfd\x18I\xe8:\"\xf5'\xd3a\xf5\xd8W\u07baO=}\xfc\xdak\x8f#\x01\xd5\"\xe1\xf8\xb57\xa3e\x11\f\t\x90\xa4%Vs\xc9~\x05-\xbdy$ŵ\xc7\xd5\xd3\xf7\xbd\xf5\x15\xf5X\x84\xce\x06w&'q\x02\xc7\xf9\xb8.n.\xc7E\xec\xa2\xc4K\x16\xdc\x04#\x80\xa2JD\x89ڝn\x18봽\x137\x13\x98\x03\xd1\xe5\xf4\xb8=\xb5|\a\x8ew\x93L:Ӎ2vmrRv:=0P\xb9@D\xfdۓ\x89\xec\xa6V\x84Z7e\x13O\xaa\u007f\x8b\x04d\xb3\x907\xcbH\x10M\xbaSY\xb3|\xf0[o\x88\xed\xf5\x99f'B\xce\xe6L}\xbb\xf8Ʒҗ\xe4V\xf7\x9e\xca\xf6\xae^\xdd+\xe4{W\a\b\x17\xae=\xb1\xa7\xa9uҤ֦='j\xc3\x05\xce,\xcb|\f;\xf4v\x9dA\x90\xcd\xcfo=\xfc\xac0\xc9\x17q8\"\xbeI³\x87\x9b\x1e\x188\x9d\xa7\xb9yZ\x866Ǵo9\xce\xcfq<\fi3\x9f\x82\x16\xc6k\xb1\xa7\x9b\xc0\x84\xd21%\x8f&\x1d\x85\xfb\r\xa1\xfe\xce\x16u\xa8\xfb\xb6k\x17\x84\xc3\v\xae\xbd\xad{H}\xa7\xf0@\u0381W\xe8\u0097^q\xefԷ\xfe\xd14;\x1b\x0egg7\xfd\xe3\xad\xff\xfdN\xe1y\xad\xec/\xc2\xdc\rq\xf5\x1a\x8c\xcaP\x1c\x9d\xb7\x88\x00O\x00ЌL\xc14\x13\x91\xd3q\x8f,\xc0\x98\xf8ԇ\x96\"\x97Sv\xa9=j\x0fL\xa8\v/U\x1f\xacjC\x1f\xbd-w\xcao\xa3\x8f\xdaȍn\x9f\xfa\xa4j\x92̮\x1a\xd3{\xef\x99j\\\xa2\x05\xfd\r\xad\xa9vE\xf4\xb3\xd1k\r\r\xea\xe4\xd9z\xba>p\xb9n=\x85^=\x8a\x18ajID(\xb5\xe3\xdc\xcd\u0de0\xb8\xba\xe2\xf8qu\x05\x8a\xcfF;э\xe85֮\x86s7\v;QC7\xbaU\xbd\xbd[\xfd\x85\xba\xf2\xb5\u05c8\xa1\xd4\xcc\xf8yZIۘ\x13\xe8ػ\xe8*\x8e\x14!$\t\x03\xef\x0edⵄ\xb3\x89\x01Ŗ\x0e\b\xdc-ˇ?\xb7\xfc\x16{\xf3\xccm\xfd\xbb\xd1\xc6\xdd\xfd\xdbf6\xdb\xcfpo\xab\xdf~\xfbmԽw\xd3\xe3\x8fo\xba\xe8\xe1G6M\xcf\xe5\xa6oz\xe4a\xf2--\xfcm\x18\a#]?\x12]?V\xae\x8ek\xe1z\xb8\xf9ܥܵ\xdc.\xee>\xee)\xee\x9f9NH%\x95&T/\xd6 \xa7\xbb\x03\x01\b_\xc0\x8f\xecI\x85Ax\x11\xe4\xd1\xd8\xf8O\x99\xfeB\xf5\x8d]8(\xa7\xf8\xd8.v\x8e\a\xcf)\xbe\x02G=\x04\x9e\xc3\xdcH\x8cP\x91S\xcdU\xa6\xbaP\x99\xb0\xe4>f\x8bF\x84E\x93-G\xa1G\xc7s\x16|\x98\x15\xac\xd2'?\x12~z\xc4I*\x93\xa8\xe3\x96R\xe1|\xe9\x14\xab[`\v\x96\xa7\xc0-V\xce'ݙG\x8dP\x15\x1a3b\x17\x88'\\\u007fR\xe5\x92\xfd\xfdI̞#n\x92;W\f\xe6\xe8\x96ٟD\xf4\x89\u007fT\xe1\x19\xfeѹb8\xb60\xd9^s6,rȥ\xb5\xaa\vi\xad\xb2\x8f\xf1\x8f\x8d\xff\x9f\xf6\x8f\xad\x0fsm15\x1fkk\x8b\xa1,}\x8e\xb8q\xae\xd2Wȝ;\ue4e7\xact\xa3\x00s\xd2\a\xfae\xd9Y\x18q\x92qC/\x98\xa0\xa20\x00\xa1q\xe7\xe2\u007f|\x16>\xf9\xa8\n\x103\xcc\xc2\b\x84\x9d\xe6\xce\x1dW\xe9\xfe/\x8eը\xa1\x80s\xeaF\xce\"\xde\xc9\u007f\x99s\x83\x0f\xce\aI\xacoAHI\xf6 8\x11\xf4\xf0\xa8C\xe2\x9d\xfe\u0084\xbb\xfc\v\xfcw\xa9\x87\xfc~\xea@\n\xbe\x9f\xfa\xc9_\x16\xb0(\xff]h=\xf5\xfb\xfd\xea\xaf\xf0\x03\xe0\x85r\xaf9\xf3\x81\xe0\xe0\x0fp!\x8e\v;\xadH\xac\x8f\xea\x11-[If\xf4\xa3\xcbw;%=\x12\x1c\xacd\xf5\xd7꯵\x92\x90\x02\xaebmH)\x96\xfek\b=o\xac\xbf\\\x8a\x86\xbbh\xfbE\b\xce\xc1i\xda\f7i\x0f:-!mn:`[\x86G\xdc]\x83\xe0\xecGE,\x8b;\x17\x96\xc5s\xb2yH6\x03\x8a2\x04\xe8ƈs\x14\xee\u0557:\x17\ue147\xce\xcaI\x9d\u007f\xa8@\xc8^\\\xdfw\x0e\x84\xac\xb2OV\xceõ\x9e\x05\xb5\x9f\xac\xfd\x85<\xad\x15g?]\xabY{?qK\x8bg\xbcH\x97[\x03\x97\xa2X\x10\x16\xf9\x00\xb4&\x95td\xd2n\x8f[\x94,\xd0\xfaZ\xc0\x13!H\x896#\xc0\x15=n\aݳ\xb5\x1d\x9a\xe2\xd4;O\xa8\xbfW\xffU\xfd\xfd\x89\x9dG\x0e4]]\x17\xb06\xaeٰp\xdf\xf17\x8e\xef[\xb8aM\xa35P\xb7\xbe\xf1\xc0\x91B\xae\u007f]?\xfc\xe1\xdc\xe34\xe5\xce\x13\xc8\xff\xf8\xd7P呂\xa5\xa9\xf1\xea\xc0\x9c7o\\\a\xc9!\u05fa\x1bߜ\x13\xb8\xba\xb1\xc9\x12ؤ\xbe\x82\xe7\x14\xd8\x06\x8d\xd9\x06\r\xff\x842>8\xb2/p\x912\xb8h@\x12\xb1k~ھ\xf1\xfc\xe8B~\xcea\xc9[\x1c\xec\x81r\x9f\xce=Pr8\xaeS\x99\x13e\xe1\xf9\x97\x02sc\xeaF\xd7\rӗ\x85\xd0 \xf4\x97S\xcc#P\xcf\xc8|0z\xe2\x1a\xf0'\x95z\xd1\xe9\x8eS\b\x82\xf5)\xc1\x8c8aFB\xb0FE\t\xfe\xd3V\xc3r\x8dJ\x14\x90\x94(E\x13\x01\x97\x87\xa0fD\a\x03\x16p\xa6\x14\x9a\x80U\x9c\x06\\\x9f\xf5\x10\x16\xb4'\x03h4P\x01\x14\x85\xb6 \t\x82j\x01\xee\x0e\x9dd3}Cv\x86f\x19\xf4\xd5\xf7\xbbM\x96}\x13Zlf\xa9\xe6\xdf,.\xe4\x9f\xd4p\x8f\xc1j1\xde\x1a\x95t\xd6Y\x8ej\xcb\xff2\xdblƗ,U\xb1\xa9\x06\xbd\xef\x01\xb7\xd9<:\xf1\xbdz\xab\xd9t[\x98%\xf6Y!1v\xd3\x1a\x0e\xa1M\xfffrc\u007f:\x12_n\xf2\x19\"\xf7\xea7z\xacw\xc5\xfdv\xf3\xd7m\xae\rz\xe3ui\x83\xd9dt\xad\xac\x8aO\xaa\xc6.3K\xdb\xdcu\xe2\x04\xba\f=\x8d.#Cj\x19n(,\x14THu\xa0\x98\x03_Z\x99\xf4\xc4\t6\x8fq\xc0\x97\xe6\xc1\xf6h\ah\xe7P\x8a4#J\xa6H\xc4%jt\x8e3\x04\xd4M\x14\x82)\xb5#\x11\x11\xa8\x9dz\xd8\x18\x10\x85\xdcz\xba\xb9\xb0dt\xe7\b\xd11Dn~\x99\x179\xcd/\x99\x9dȋ\x1c\xa6\xbf\x99\x1c\xf8\xa3\xe6B\xd6\xec@N\bV?\x84p'r\x98\v\xd9f\x1f:\xa2\v;\xd1b\b\xb1B\xc8QHb\x85$h\xb13\xacCG|\xd8\xcf#v2\xa9y\xded\xb3\x01m)\x9b\x11e\x03\x98\xcf\xc0sv\xba\x9bw\xca~٬\xed\x9bfp\x9e~\xaf\xbbDG\x88\x14\t\xb4r\x11\xae\v0\x94\xe2^Xzˣ\xa6\xdd\xe3\x8e\xf7\xd0Շ\xdc\x12\xc5c\x90\x92\xa1l&\r \\\xf6`\\\xd08HHa\xaf\xa3\x00\x0e\fIC?\xb9\xb3\xfd\xf1\xf6\xbb\xd0\x1b\xb16\xf5\x9b\xf6:5\xebH;\xd4l\x9d\xddވ\x804C\x94\xf8\xe2\x1a\x8f&\xb5\\\xf4\x0f\x05F\xf0\xbe\xbb\xda\xe0\x0f\xdb\x1bjԬ,\xa3|MC\x14\xe5\x19ݔ\xad\x80\x15/\x17f8\x80\xb3ܮ2\xa8\xb8\xec\t\xd8.\x8a\xc0ҍl\n_\x01/\xfc\x80A\xfd\x96\xd1kT\xf3V\x9dΝg\v\a\xfe~T\x86\x99\x03\a\u0382\x1a<`2\xa9\xdf\xd2\xebQ\xd6&;\x19\xdcX\xd4A\a\x8eW@\xda\xf1\xb3@g\x9c\xb6j{\x9c\xb6\x19j,\b\x8a\t\xa2s\xb7uuE\v\r\xa8\a\x9a\x8d\xb2֟\x9e\xb7\xa9\x0f:\xd5A\xb6\xc9\r8,&\x13\xea\xd1\xebռ\r}|\x9e\xa6b\x06\x13\x14\x050\xb3\x95\x1flFQ\x12$px\x05=\xc1\xc8\b4ddm7\xf6\xc8nr\x06u\"\x82N\x16:O\xc2\vu^\x8a\xb2x@\U0005d08d\xaa\xea\x03C\xcaG\xb2\xbe\x94\xe1\x83*\x9c%F\x8c>Tm\xf0\xca?\xad\xd62.\xe4o\xbb\xbbp\xac\xaa\xbe\xbe\xaa\xf0ˮ\x8a1\xb2r\xd5\\T\xc3\xc3١K+L\xc3\u061cc\xd9\xf3\x83\x81\u0090\xd5n\xb3\x05\x02\xc1:\x1c8\xef\xa2\xc7\xcf\xceq\xa8y\xbdN\x8e\xe0\\Dv\xc8j\xfe\x87\xe7[\xf5\xa8ܦDy/\x8a*=H\t\xd5[0\xe0l\x898=\xef\xe3\xf4`\x97D\xbe\x8cd&\xe2<\x9c\xfd\x80\xdaq\x14R\x1b\xed\xf6\xba}\x0f~\xbf\x84|m?9[\xb2Y\r{\xf5H\xb7I\xfd\xc1\x17FP\xb5\x83H\xdep;@\xb8\xc0\xa9Y\x9f\x12\x8b\xd6\xee\xdb[D\xf1\xd6]j\xc0\xfa}\xba*Þ\ahJԆ\xfc'v^\xbb\xf66XD\x95\xf8L\x98\x9b\xc9V\x01\xe6\x82\xf5a@XF\xf6k\xa0<\xe0\x98\x8d\x97\x91\x93\xd2\xc2N\xb2\xae\x94\xf1\x9c.\xe4\xe0\x82\xac\xedpV\xff\x11e\xd5u\xea\a\a\xd4\xff\xd8p\x9b\x9c\xa4\xd3\x05+O\xde;\xf3\xab\x97\xdd\xf1\xa7\x19\xc6F\x00G\xb3\\E\xfb\a\xa1нb\xe0kfy\nz\x14\xc9\a\x90s\xc3\xed\x90\r\r\tX\xfd\x9b\xfa\x95k\xae\xbcM֊P\x92\xf2\xde\xdeY\xb7_g\xbf\xc2#\x13\x99f\x87\x90}{\xb5\x00\xb3\x84Lh.tMV((\xea\xce\xc9/\xe0\xd0\x18\x8c4u\x01\xffX\xba4u\x01\xbf<\x86k%\x9fŅ\xd2\b\x81s=x\x88\x1ff\x1e\xc2Ȍ\xf1ݐ\xe8\x14\xf3P\xae\xef(\xbe.\x1a(\x17\xf7\xd7q\\\x85\xf1\x02+\xa2\x13\x84\xb9\x87i}\xfc\xdcJ\x86/[\xe3\xbc\xc6O\xaf\xa3k\xa5\xce\xd5\xfe\xde76\xbct\xab\x12O\xef\xbad\xb1٧\b\xdc,崅v\x9c\xff\x8b2+\xd5\u05f7\xad TU[\xb6NHN8\xa0W|\xf8\x0f\x01\x8f\xa5fG{\x87ܘlT\x18\xdd_\xe2\xa5\xf5\xd1\x16Z1 \xfe\xae\xd18j\r\xfc`A\xa4\x92\x18\xb6\x1a\xecr\xd6\xd1㼌\x9a\x95`\fh\x04\f\xbd*\x12\x98b\xae\xd3\xf9\r\xf7\xde\xe5#\xd8\xe8\xcc\x1b\xea\xa7ռ\xa0\xfeB\xfd\xb2\xfa\x8b\x17j\xa6\xd5\xdf0s$n\xf9^\xf77\x9c\x9dw\f\xa1$\xeaGɡ;\xf0\xbe\xa3\x0fN\n.\xde\x10\x18A>\x033;M\x97\xaey\x10\x89\x8f?\xae\x9ezpͥ\xa6Ι\x81\x11\xa44\xb0aqp҃G\x1fF\xde\xd7w\xee|]\xfd\x93֯\x00\xe1\xf8!\xc0\xe1ؾ\x05\xc7b\x19v\xe1\xa0q\x138\xabe\xf5+\xea)\xb6\x0f\x8bh.,U~\xf04]\xe1h.\x84P4s\xae\xb6\x06)\xbc\x04\xf8\x1c+k\xe2\xf8\xa5q\xdaD2\xc6u\xb2\x99\xb0\xeb\x03ϸu\xa0\xdcE3\fV\x9f⭯\xf7ҟ\xe2\xb3\x1af\x8cS\xb1\xea8\xbc\xdb/D\xaa]5\xae\xaa\x96ޖ*xWG\x84j\x06\xba\xb0\xdf}\x03\xe6l&k\xcflnçi\x13\x1c\xa9\xc5Pv'\x03\xf46#\xde\xc6\xc6\x01\x85\a\x80\xe8\xb0\xe1(%\xc8\xcb)>q\x8f\xd0E\x9f\xdbo6U+\xd16\xe7\x9cŋ\xe78ۢ\x8a\xcflޏ>\xa7\xfe\xcc\f`\x1a\x95\xea\xa4\xe6\xf0M\xfb\xf6\xdd\x14n\x06'\x8b\xfc\xd9'\x1f\x85\x8czB-t\b\x8a/ꬱ\xa6\x9f\xf9\xfa3ik\x8d3\n\xd0\xdf\xf155\xa9\xeeZ\t1a\x0fo\xe6\xab|+\x91\rőm\xa5\xaf\n\xbc\x9e0$Yə\x18\x91Oa\x9e\xde1\x1aag\x959\x0f\x9c\xb8up\xe2\xb7\xc09Gת+\x94\x92\xe1\x17\x84\x1fb\xb4\x8a=H߀\xee\xdbQ1\x1ch\xb7T\xc8\x1e\xb2\a]\x89\x14Ғ\xd8Q\x0e\xfe\x91\x1c\x90^\x94\xec\xa0?\xc2\xd1\xe7\x19\xae\x90\xe3s9\x1a\xad\xe6ػ\x00\xff\x05\xf8\xd1 \xc2\xd1l\xc3\b\xedB\xc5|4\x16\xe7T\x16N\xf9\xcc\x10\x88YB\x1aL\u007f\x1c\xbb\a,\x9d\rg\xf7#\xca5\x15\xfb\xd2A\xf9㉐=!\xff7~=\xf0/\x10X]W\xf7\x04\xfcuw\xdfZW\xd7\xc3\xfe\x9e\xe8避[\xd9\xdfꞞ\xe3\xabW\xd3d==B\xee\xd4m®\xffҏ\u038bv\xa6?$\xbc\xcb\xf6\xe8\x9a\n\x1eE\x11#\x02\n\xa2L\x89!7\xca\xc3\xe6ط\x9e\xbf!\xa2\xba\xa2\xc9T\xa4\x90RR\xfdI4\x98\xca)\xf8\x87\x11\xdeH#\xfb\xd4l*\xa2:#\x11\xfc\xa3H.\x85\x06\x93\xfd)\xa5\x90\x8e\x96pӇ\xa4\rźR\x17\xaaM\xd0B\x81\xfa\x83=\x91ƅ\x12\x9f\xa0\x15(ǂ\xc3͵\xe8\xcd\b\x8d˥\x86>A\xfb\x92,\xd0_\a\x99\xa02\xfc\x03%\xa55\x9bp\x06\xc0yn\x846/\xe1\xae\xe0\xb6\x02\xc4\x02Mb\xa1t\x17,\xe7L\x12֮\x92\xe9\xc6l\x19+\xf49\xd6\x01Q\xa2Gb]*\xe6\x93D\x0f;\xe6\x01\r\x8f\xba\x05\x91\xb9{PZ\x19!\xe5*\xfc\xe2U1\xb7\xfa\xbe|\xfd\x94\xe1\xb5s\xef\xf3{\xdd\"\x823\x11\x9b\\\xa2g\x82\x8e\b\x98\xf8\x89\xab\x91G\x12χy\xb9\x85G:\x8c-nQg7\xcb\xce`ԏ\x143\xfex\xce\x02\xb7\xfaAx\xe6%ÏU\x1b\x8d\x06\xef\x0e\xf2XMZ\x87&HX9\xfd>o\xb2\xe0\x01s\x15\xef\x02Ga\x10\x1c\xeb\xce\n\xe1\xeb'\xcf\x1a\xbe!\xbblü\xa9\x9d|\xb3EW-\x1a\x9d\xd5\x06e\x83b\x88\xe9\x8c\xf5bxs\xbd\xbeY0\x87\x04\xdf6E\x17\xd2\xeb\x9c>\x9d)\x12\x8cV\xb9\x91H\xf4\x9b\xe7\f߰}\xba\xd5V=\xa3\xceG~\xe3\x0eYk\xcbh\x8b\x9a/;\xb5\xbbۇ\x85\xe2\xbd0\x8a{4.\x00c\x83\xe9\x19\\h`\x01\xe75\xbf\xdf\xe3\nF\xa3A\xb9\xaa5\xa4\xceTg\x86[4\xbf\xcb#\xe4\xf4\xe6\xb6\xfaS\u007f\xafo3\xeb\x02\xe8yuy\x90\xfa\x05=\xf8\xf5\xa5\xbd<'j{\x91\th\xfeN\x8ek\xd06\x13\xc6\xf7\t\x96@1c/\xb2\xac5\f-T:\x9e\x8b`Y\xc7X\x14\x14]\x80\xddg\x18~\x83\xf4\xae\x85\xcfi\x84\xa8l\x1e\xd2p\x97!\xb3\xbce>\xe01x06\xe0?\xec\x8fe\xe7oA\x1c\xdds\xdab\x83\x05\x8d\xf6̪\x03fy\x90b3\x83@B\x0f\xce߂\x03\x94Yq\xd8?\x10;\xc3m)\xca\x01h4s\x90k\x80\x1eP\x91\v\xc0\xa3\x8b\xc8\xc0\b\x02UfW\x15\xf9\xd062\xfb\x83c\xc7>8F\x86(\xcat*G\x9fC\tym\ns\xa9\xb5r\xa2p\xd5\b?\x99\f\x1c\xa3I\xf1\xecC\xeb\x87Y:\x02ϻ&͜9\xe9\xae\xd39T\x96Y\x18\xe1-k\xb8\xdc\x02\x98%\x12\a\xc4)\xa3@\xed|FF\x1d\x88\x12h\x0e\x989*\x8a\x80(\x1fRt\xd5\x03\xc2\xcfK\x80\xf8ǻ\x85T\x12\x0e\xb7\x88\bXM-IP.%\x8d\x14C\"\xfe\xf9\xe7\x82?\x9e,+ˆ\u007f\x80=\xbd\xad\t\xc5\xf4>\xf2\xf6\xa5t\xe4\xf5\xe0\x81\x06\xeb\xd2\x1a\xa7U\xdeg\x15Q\x8f\x9a\xedW\xff\x1c\xe5w#\x8fΥ7\v\u074b\x90\xda\xed[\xeb\xefP\xfa\t\xc2\xed\xffޮ\x8b\x90\x05\xe4'j7\x8f\v\xc37̗\x8c\x069Z\x87\xd7\xe1\x93\x16I\r\xccS\x1f\xb9\xb4\xfe\u007f\xb7O4YkDE\x16\xec\xbc͂\x9aB~\x01\xce`\x83Ig;\xf2m\x82\xdb\xd5\xf7\xab\xdcu\x0e\xa0֢z\x87Sg)\xd2\xd1\xec\xecr\xc1\x0e\u007f\x19\xc7E܉\x80=\x19m\x06\xdaK\x82\xce9\xc5ZD\x18\xee\b]\xc34\x8c\xf5\xd9\xc9\x16~7߉R6Hۂ(\x89\x06\xc9j\x89\xcbi!\x12\x00\x0f\xbcBldpӜ^\xb4\xa3\xa1zz拾\xdbg\xfb\x11F:\xb1qꢝk\x12\xedWl\xed\x8d/С\xc2\xef\xb1u\u007fX2\x8a\x02r\xf3\xe1TsB\xe0נ\xdf\xef\xf6\xac\xf0\xcc\xf8\xccͫڂ\x13\x97t\xa7\x1e}}ƶ\xa7\x9e_5\xe1\x85\t\xeb\xd5k\xac\x014\xff\xba\xde\t\x9dA;oH\x9dL\xea\xb6Ϲ\x04\xbf)\xf9z\xb6.\x99qu\x87\xdf\x1c\xffA\xa2z\xbd\xafyx\xf3j\xdek5\xd5F\xfc-\xae\xb8@\xdelҙ\xf5\x02\x8f\x16c\x19\xf9ڗ\xdcҗ\\6\xb9=\xe0\r\xbd\xfa\xd0\x15O]9\xdd/\xba5ڔ\xa7볝\xe3\\tO\x83\xb5\xe8C\xd1T3\x8ef(i\n]\xa6w\v\x12\xf4P\xc4\xf0\xa4\x1ciQ\xaa\xa7\x9bw\x88γ\xdd=\u007fJ\xb5ߌv\xaeGޮy\xb2\x1c\xfc\xa7[\xda[\xd7\xde\xe3\x17,\xb5\xf7Et&Q\x8f\xabo\xb4c\xb7Â\x90\xfdyb66\x19k\xb6\xfa\xf7MK|\xfd\u058b$Y\xb6\x84z%\x9c\xc4\xc6P\x95\xd9(\x90\xab\xb0^\x10\xf48\x1a7D\xacrK\xb0\xdd\xfc`\xe1\xed%\xfa5\x8b.\xb2:\xf8\xea\t\x19\xe2Ď\x11x=\x05m\xae\xe6n\x81ً\xbb\xad\xdam\x18]\xcbЮ\x1e\xed&\x8c2G\x10\xa5\x01(-@\x97Q7\x06xu3\x10\x15%@\xc9p\xb4\x99\xd0~н\xd8\xe3t\xc0\x1c\x97\x00\x1c\xca\vS\x18\x86]\x82\x8e\x88=\x89)AG\xe1\x9c\x11\xba\x16\f\xd9\xed\xe2\x1bA\x87\xf3Vg;\xfc\x1c\xc1\x05\v*=\x1f\xff$mz\r\xe6-|_\x18E\xc4Z\xa3ˢk\xe4\x9d<\x16\xa25U5\xc4fF\xa2I\x96j\xb0\xfd\xf2\xf8\xbc\x80\x1e\xf1\x82`\x88=\x1f\x16H}\xbf\xfa\xfb)0\x93\xc4~\xf1F\xaf,\"\xcc\x13\xe3\xc3\xc1\x1dN\xb96\xe8k\xb4\xe4\"\xbe\xa7}\xf0\x17Ṓk\x98\xe3\xcfT\xc3\xfc\"$\x98\x8d\bm\x1eZPc\xe1',\xd1ϛ\x8etz\x82\x11\xe2\xf9\x85\x99Յ\xaf\x1e\xb1];+\xe8j\xb2\xc5\f\x16+\xc2NG\x02\xe9\xab\x03>K#\xbah-zp\xed6\\\xed\xf1;y\x93\xd7b\xde~\x15\xf69\xd0.m\x8c\t\xe3\a\\\xc6=\xc4qrq\x1cü\xc7=f\x10S\n\x1d\x146\x88u(\xe5\xa4\xcb\xe0\x1c\xe3؍\x93\x80\x033\x81\xb2\xd1#\x89\xa8\x98\x10\xbd0\x81\xe5\xd3\f\x03\x9d\n:\xddNz{\x02S\xa4\x00\x1eM\xe8]\"\xac\xc0`R\x81\xbc\v\xb5\xb1\x9d\x81.C\xdc\xf6\xa0\xa7r`-\x06\xbb\xd0U{낍\x8dz\x04\x8bn\xdcq\x95\xf4\x04\tt\xc4x\xe3\xc3\r\u007f\xb3ic+Ԛ:3Y\xde\xe7㳙N\x93\xd9*\x90a\x8e\bV\xf3\xd8P\x9e\x86\n\xbb`\xcc1\xe2Q\xa0b\xc8\xe7\xce@f\x11c^X\x989\x9c̼\xfa\xf4\xac\xf1\x87ܶ\xf5\x9f\xef\xfc\x02\x91jtҜY\vӂ\xa9\xdahھ\x8e\x8d\xf9\xa93\xd1\ti\xe2js\x91\xf4\x84\xa8+\\\x17\xc28T\x17v\x8d\x1b\xc8i|\xd7Q<\rv\xbb\xf6߹c\x978\xc5\xf71\x93\x16\x11\x8b\x92-\xa7\x99t\x89\xc0\x98\xab\x8a\xef\x14\xf3\x89\\1\x8e\xa5\xe4\xe1\x99\x1f\x116\xb9\xf2\x02\xce\xffG\xed\xd6\xc4\x13I\xae\xd8n\xe6\x13J\xd2:̇\xff\u007fh\xf7X\x19\x85\v\xf9G\xb7\xbbr\xb4+\xc7\xfa\xbf<\xd2\xffO\xda|a\xf7\xa7l\xf3yxuco\x8f\xed\x17\xf0\x8f\a7狿P\xdf\x11'\x9b\x19j{\x8e\x87\b\xf1\xa7\x98G\x00\xe4\xf7\x14w\xae\x98s\xb9\x87ʥ\xa1\xeb\xc7s\x0e\xff\xb5\xec\xe4\xc7\r\x1d?\x1b\xbb\x8b?kL5>4\xbd\xe7Hj\x12\xb7\x9fv4\xce\x1a\x9d\x9cl\xb6\xe8\xd5!\xbd\x1e\x05\xf4\x16\xb3,\x80\xffc\xd6C\x915\xe54{\xf2ٱ\xee\x914d\x88\x8aR\xd0\xec~\xfa\xb8p\xcf*;9n\x1f\x8b\xbc\u007f\x8d\x9fC%d\xfe\xbb}\x1c\xa0\x1dd\x9cA\v4Q8\xf6i\xbb\x88O\xf8i\t\x9a\xb8\b\xb8T\xfd\xa7\xe8\xa2\xc6gd\xf2\xc3ul\xfe\x18\x15U\xeaS\x89\xb8\xaeA\x88q\x99$.j6U;\xd4MǶ\x17\xb2ۏ\x1dێ\xf3ۏ\xa1\x83\x8ej\x939J\x99D\x8dvAF\a\x8f\x96b\x8em\u007f\x16\x1d\x00\x04\xbaLOI\x1a=`\xe1j\xb9f:\x92\x94>Iǁ\xacJ!\x18\xc8\n\x966T\xacxư\xb5qn\xf3\xe0\xe6̓\xfc\xe6S9\x94\x1dĀM|\xcc\xfa!ґ8X)\x05\xc9\xdbh\xc2ͅ\xbc\x9aͳ\xa4(\x00\x83\xc7\x06\x8c\x87,\x81ӌ\x95\xcd\xe7\x8b2\x8b\x80\xb7\xbf+l\xe0D\xa0\xf2\xaa\xb8\b\xc7\x053Qɕp\xa1$`\xe9\bPt\xa0[\x80\xf4\x86\xf6\xd9\x11 \x1f\x88\xb2\x81\x01\x13D\x1bV\xbe\xbb2\x87op\x1b\xa4\xc2o%x\xe2Z)\x8d\x06\x87\xf3\xea\x80\xf0n\xe4\xa8:p4\x9cN)\xefF Ն\x1c\x19t\xd3T\x067M\xf5\x03u`8\x8f\x06\xf1P*r\x14\r>\xab(\u007f\x8e\x16\xf1O^\x93\xfd\xf0\x8c\xe6tX\x10\xe5i(\x8c\xf1M4!\rt(\xa8>h\xeb\x99\xd5cU\x0f\x06\xd1\x04\xf4<\x9a@\x8a\xb2\x15ܦ\x19ç\x82\x8a\x12$\xe2\x8cM'\xd1\x04\xf5\xe4(\xb9\x12\x99J\x88׳\xbb\xaaQ\x17\xd4܃\xf4\xae\x89<8\xe6Vj\x80\xcfj7P\xf8?Ͼ;\xd4\xf8\xf5\x9c\x90\a\x9a\x87\xf2_\x81\xda!Q\xa5\x9e\xa1\xf5.h|:B\xef\xca)Ӓ\x00\x95\x13\a\x04\x8exܘs\xa2\x1a\xb7_\xe2\x81\xd6\xf3\x03d9\xfb\xd6\xf7aN=\xa9.WO.\x14\xb7\\|\x8d_\x1fO&t\xfek.\xde\".D\xb9p\x105\x053\x1e\x9b͓\t6\xa1`8\xd5\xd7\xf7\xe2I\x15\xfau\xf2\x81\xdb\xf5\xcf\xdc\xfd\xabKj\xeb\xebk/\xf9\xd5\xdd\xcf\xe8wi\xebU\xfc\a\xf4S\x04\x18\x9b\xccus\xb3\xa0U\xdalr\n̥;\x83\xe4ѠMe`\xacT\xb8\xa1\xf2B\x05\x96&\xa0\xfbn¦\\\x82\tg2pd\xc7\xd6\xc3[\a0\x17\xb0\xabO\xdb\x03v\xb4z\xe1\xb1\xed\xc3\f\xcaI\xb6'm%\xc44\xc9\xe2\xf0\xb8\x87\x19\x18\x12\x001}\xd6\x1a\x1b@\x81\u0080:įZ\xa5\x0e\xad\xf2/\x00r\x1d\r@1m\x038_.\xa7\xf0\xe3W\xb4R\xb6\x1f\xab\x92lv(F\x145A\x90ս\xb7\x9a\xa1\x14\x1b~]\x1d*@Qؿ\n\x05V\xf9\xa1\x94\x05\xe5\xf1g\xf7\xe4M܊\xb1\xb2\xb6\x93\xe2\x1a:M\x8f\xa7ʞQZ\xcc㖵\xfb\xcb.\x14\nH\xa2\xecf\xab\x9eJ\xd7wK\xf4\x86\x85I\aA\x97\x85\\\xa9\x8b\xdc\x19\xb3\xec\x9b\xdbf\x107\x97z\xe7\xf0\xfbl\xb2\xeb}5\xc7V\xff\xa0z\xfc\xfa\xed\x13\x89G\xc7\xdb\f\x06\xf7\xe4Ɛ\xe4\nu̻vߋ\xeb\aa\xcb\xf0ɰ\x93\xe3\x90Z(\xf5S6W\v\xbez\xbe\xd4\xcb7e\x83\xd9k\xd3\xe9\xd1[j\x0e\xf6\x8b\xc6\xfc\xee\xbd\xea\v\x1e#6[\xea\xaf\x1a\xd8\xd36i\xc9\xc0\x82\xc5Sڣn\xb6\xc1@\x92d\xa9\xef\xbb`\xae[\x98\xe4\xa0}\xbci\xa5]<{b\xe9N&k\xf7\xf1\xa3\xa5\x1cG\xba[\x9eQ\x83\x99\x88\xa3\xe7\xd4`\x16E\xe7\x1f\x87\u007f\xea\xed\xf5\xaa\x8b\xbc\xdek\xe0\x8d$|'\xbc\xae\xf1\xe2\xd5\xea\xb7GO\xa5\x01\x97\xa7R\x85\xa94\x10\x1d:\ty\xbd\xe8\x9fX\x06\xaf\xfa1d\xa5\x85hz3T\x1e\x9eʷL-\x9e3\x8c\xd5D\xd9G%\x01\x02\xc6Z\n\xba\x9cb锥\x9b3\xe3I\x95\xae陌R\x90^cy\x10,\xf73\x9c\x9c\x04\x1c\x15P!\xe6\xa4\x0f@\x8c\x00ieN\x19q좀FS'}@4\xa2шÏ~\xba\xf4\xf2\xe8\xda*\xf8\x00T\x0f(\xcd\xf8P\xd0\xec\xe8\x18Y+\x97=\x9d!?\x93}>\xb9Ю\xe7+\xa4\xe5\xf5\xc2\xf5\xb2\xc9w*\xeb3\xc9\xf8U\xbd\xa1\xb0\xa2\x84s\x03ƽ\u00a0\xaf\xd0\x0fi\x1a[\xfe9\xaaa\x89\xd2\x19\xb1\\\xdb\xd9u\xe2We\xdfY5\xb7\x9f\xa3\t\x90\xd8\xe4+\xb4\xb3\xb6\xec,\xf2\xbb\xaa\xc6iK\xb2\\\xf3\xe2ʚe\xf9<\xb5\xc1\xe8\x8e\x14\xcf\xfaz\xb3\xb0K\xd8C\xb5&\xf4Hd\xddbktݩ7<\xc1\xa0Gh\xf5\xe0\xcb\n\xb5f\xa7O\xc8\xfb\x9cfp\x85+d<\x8b8\xccY\xf2\xf8\xc2X\xd5\x1f\xae(\xf9ϴ\x00\x86s\x95>!;B\xf5TR@J\tvK\xf5\x9cU\x8b8\x8ab\x1aU\xceH^Q\x1b;O\xb9k\x9eb\x0f%\xd6[Q\x9aH\x87\x0e\x06\x88\xa7O\x99\x0e\x1f\f\x1d\x1d9谉\x8e\xa9\x01\xbf\xca\x1c0r\xf00\xf9\xf0\xab\x06}\xb9\xfc\x12\x9c\x9cU\xbe\xc7>\xfaʔV5^\x8d\xa3\xc1\xe4ܵ\x83\xe3\xe8\xc8\x00\xe1\xa3\x06}ecF\xad\x89\xd1m\x19ۈr\xed\x95\xf5\x8e\xaeqLEl\xbe\xa1\x06\x11\t\"\xc0I5\xc7\xc9ڦ\xc0f\x03U\xcc\b\xad\xc72\x02c\x14\xf6\x84W+\xa6\x05O,\r\xb1\xaf\xf0\aM\x16J\U0005d0676\x9e\x8f\x9ey\x94?*\xfc\x010&N\x8fݚ\xf4xq?\xa2\x1b)\u007f\xb0\xf0>\x96e\xf9(\x9d\t\x1f@\xf9\x1f\xc0qT\xe6\u007fVx\xbf\xf0>sjA\xf0\xa0i\xb42W@\x99W\x16\xcb\xea\xf0U\x83\xf3\xec\x10\xb4{L\xdbГ\xe7K^\fA'\xce96\x1e&\xe7E[\vh8\xa0\x95\xac\xad\x1e\xdaJ*\xb7X\xd1>\x81w\xac\x84yW\xd7\xfd\x16\x9e+\x1d\x0e\xb4\x9eV\x81\xeb\x1c\xc3c\xe5*\xeb\xfd\x0e\xa8Y\xbd\xfa\xb7P\xb5\xc3\x0f\x84\xcc!\x99\xa6\x9b3\xa6\r\x95\xf2^\xed\xdc\f\xc0\x98\xc7\xea\x8d%\x9b\x11\x10\a\"\x1b\xb3\xa2`\b\x9cɒ\x05\x95R\xc0\xf9\x9b\xe9\xe6\xc3cD@\xcb2\xe3ܵG\x97\xfd5g\xf5\xec\x91L6}*X\x9fl틵\xf6\\\xcd\"\x9b\x82\x81\xfa\xf6\xba*\x94\x1b\xd3\xfa\xc1\xb2p9\xfe\xa7\xe5\x87\x16\xfd\xdc\xeb\xb8B4M\xf3z\x93A\xa5\xd9\xed\xdf65L\xa3\xe5.\xd9\xe1\x9a\xd42\xa7k,0\x8c\xf4\x89\xd2^\xed\xa5>\xd9G@\x8f\xf1\xb9\xcb@H\xc6ty\x94\xc4\x1f\xe7\xb0\f\x94\x04Z\a4iepWt\x10\x9f\xd5\xf8A\b\xe4h,8\xd4<{9Ƚ\x83\xc5\x10Ƿƶw\x04\x0eZ\x98\xeeOY\x17\xa4\x19E\xcb<\x17\v\x92\x12\x14\x01\xa2\xfeZ\xe4)\xab\x89t#\x8d/\x03\xf1崐\xaf\\F7ʔ\xd3B>(\x83\xff\xe2&\xba\x906\x05\x8eld\xcbi\xe3\x91\xc0\xd8\x00t\xbd\xe2\xbb/\xf2\xee\x11\xe6=\xf2n\xe4>\x1a?&\x00s\xe7\xca]\x0e@\x13Ν\xbd\x180Z.3Ĥ\xd89M\xf1G\xd26\xc6\x1eX\x10I\xedJ\xa2H\x9dXa\xe5:\xd3\xe7\x92C\x9c}\xc0\xe03\xec\xdd\v\x8f\x03\x06\xfa6\x8c\xf1\xbf~>\xc9D\xf4\xfd\xf13\x95\xfdU\xe7\x17O>[vZ_\x81}ס\xe2\xa1qN!ʃ\xea\n\xba\xbc\u007f-\xcbW\xc2\xfb \xa2\x9b\xfc\x95\xf2\xce\xf3\nS\xfe\f\xf2\xc8Ha)Y\x16\x9a\xf7\xd4'l\xe7g8=\xe7`z\xc1\xc9(bwv\x02\x93\xab\x04\xa0\x82\x86i:2E\x8d\x1d!\xb0\xac`\xd9;x\xed\xf7\x0f,\x1d\xae\xc2\u007f\xbd\xf3Y \xa3\x85\xc0\xce\xd7\xd5ߩ\xff\xaa\xfe\x8e\n=\xc1\x96Іj^ǻ\x8f\xdcQ\xb0^\xbc\xec\xc0\x0f_\xc6\u007fYy`\xf8\xc1\xa7Q\x8f\xfa\xaa\xfa[&aY\x8b\xdaQ\ru\xd1s0{&\x05m胑*\xea\x0e\xb1\xd9\xd5\xf8j)\x8d\xb1\xc6T\xb2\x10C\xac\xa6$\vY\x14Q\x94>*\x86P\xd8\x16\x89\xe0\xbb\xe9}H\x9f\xa2\xa8\xbf\xc1\xf9\xe4\x14\x9c˥\xfa\xd4_\x877\x86\xfb!n?\x13Vا(s\x94\xf5\x90\xa0O\xc3GRB\xbeX\x9f\xc6\xdbbG/*\U000e8d09b\x14\xa1\x90\x8f\x14\xb6E\x93\x89(\x94\x8f\"\x85lrʔ$Ϋ\xbf\x81\xfa\x95dJ\xc1wGp6\x1d\xa1\xcd\xe8\x83\nP\xa4/\x05\xb5#\x05j\x87\f\x85mtC\xe7R0\xc6}B\x96j̣R\xc7\xcaX\x8fv\xf0\x17\xbbI\x11\x97>(\x89j=\xfd\x9a\x15\xc5:\x02E\xe1\xbbC\x99t\x84V\x97:O[h[5\xdc\"u\xe6E\xa83W\xd2\xf5.\rf\xb1[eܫ8\xb6P)\xede\n\x9e0Rԁ\x94\xfed.ُ\x14:~}\x11\x9c\x87\xb8\xadt<)\x8f\xa7/\x12Q\u007f\rc\xdd\xdfO\xe7B\x81\xbeGGp\xce<\x85\xf7\"-G\xe5\xa9-\x02\x1cb\u03a2\xaey3\x8eb\xe8\xab#\x98\xb0\x97\xe85\x95RPCk\x1e{d˚\xee\x90 ح6\x93d\xb2\x92]\xa9\xa7\xf1\xf7\x87\x80\xca\xc2\x1c\x01\xaaL\xa5d\x17\xe2Lu鋶\r\xae\xcdL\x13Cz\xabӮ\xf7\xc1IYs\xf4\xb5;\xd0A\x8a\x89@*n\xd4yڢ\xb5\xc4\xe3\x1e\xc1\xceKˏɩ\xb5\xa0\x12\xdeE\xb7\x17\x8d\xe9\xf6W\x83\xfa\xd5\xfbeM\x98\x16\xaa\xbf\x1f\xf5â\xbf\x8ex\xa8[\xfd*u\x1b\f\xa8\xff\xfe\xa2\x04-z\xdf\xc7җ\x85rizH>\x9b\xc9\xe2\xd2\f\x90\xde\xc72$\x95\xa2\f\x9f\xf9\xcc=\xc2_\x85\xeb\xb5\xf6\x9d\xab\x1d\xe7j7\x93{\x1b\xa7!\xe7h7Ύ\xdb\x10|p\xdcfs%9LA\xd3Q,\xae\xc72\xb0\x96WH\x19\x80(EEug\a\x98\xfe&\xd5/\xa1\n$̃\x06cm$0^(K_\xac\vC]D\xa3\xa1\xc6\xf0\x89i\xb9\xa7\x99\x98+\x9f/\x96TR\x12\xd5hOJ?\xa5\x98N\x8c\x15\x0e\xbe\xe8\x88ޛ j\xaa;\x13\xe1\f쁳\xcf#\x94\xdb\x1bISm0Q\x12\x84\x1f4W\xfb\xb2\xbe\xab\x9aՏ\x18\xa4\xab\x1f5_\x05\xfe\xeafd\x00\xa7\x16\x85\f\xda\"0\x14\xa3ԏ\xd0\x1f \xf8\x1a\x88~D}\x9d\xa9R'\x1e\x81\xf0k \xfe\xd1GK1(\xc1\xb4\xb3_/\xc7T\x9e\a\x94F\x99Ȥ8\x1d\xa5\x1d\u007f\xac\x0e>\x91\x93Q\x1a\x008\xaa\xac\x85\xe0\x16m\xcb.m\xf9\xf8\xcb\x0es\xde\xect\xc2Á\x1d\x06\x83\xe5-\x8b\xc1`wZ\xbea\x91\x85\xb1x\xc8\xe9\xffx\xc5\";ͯ\x98\x9d2\xba\x12o2\x89:\x9dh*\x1c4X\xad\xa5\xbb-hW\x963sn\xa0\x96\xe7P,ɞ\n\xba\xec\xae\"ޗ`7\xccNw8ɐ\xe7D\\\xd3\x1b\xab\xd4\t\xd3(,f鄝\xce\t\xcd\xf4I\xdcM\x06\xd5|؟\xf7\x87ն\xef\xdc\xeak\x82\x99ÿl\x8b5\xf9n\xf9v\f\xbd\x00x\x14L/L\xa7\x86M}\xfd\x92ݻ/\xd9Е\xcbum\xa0.\xf4u\x8b\xe3\xabm\xe8d>\xafNh\xab\xaa\xae&k\x8fԵ-h\x83\xbf\xba#\x83\x14\r+\xc1\x94\xa6q\xb8\xfb\xa5\xdds\x9f}v.\xbc\x1c\x1a\x9fL\xd2\xec8\xccc|\xe5P=/2\xfe,\xa0\xaeT\xe8,\x9c\xa0\\f\x91\xd3x\x80\x88\xea\x0fP!:*\x98\xaa\xe9}\xd2\xcbuL\xe5v\xbayj{C\x00\x1c\xe7\v\xea[\xbf\xdb\t\xab\xcb\xeb\xaa^\xed܋\xa4\xaf\xf9\xb0\xe2lV\xdf\xfd͛C\x0f\xee\xb3\x1e\xf0\xd8Z\x9a\xbak\x9a\x1a\xaa\xb0\x8e\x90\xee9\xdd~\xac_\xf6\xf0+\x9b2_\xfdʗ\x1f\x8a\x1a\xa2\xce\xfa\xa87\xda\x13\xb0\x11%\xa9\\~\xecN\x97\x17V\x9cw\xb5|\xf3:$^\xbafH\xfd\xf6\xa6\x8d-\u009cl\u007f6\xd4\xc8[D\xb3\x14\x9a\x9bn\x97\xf9i\x86D\xea\xfa\x9f>\xb5=\xec\xb0\x12}4b\x88\xda=\xfaU{\xb6\x96x\x1c\xd0C\x91\x83u\x93\x80\xd5:\xf6\x86\xc5\xc96ݨ\x8718\x05\xd8\xc1=\xd1Z\x9e\xde%\x8dܓ\x9d\xe1&\xcd\x1f\x18\x98?i*\x8fV\xec\u07fb\"\xa3\xf9z\x89\xe6\x1b,K\xaf\xf3\xf2\xbc=\x97,\x9e5keb \x87PÒ\xad\xb7}aM)d\xf5\xedŐ\".Aǝ\xa72\xe6An\x12\xacK%\n\xbb\xbe\xc6\x0f\x17%7\x00;\x9b\v\x8dQΤx9:\v\x01\x8eJ'\xa4\xe1\xed\x11s\x87\xdf\xe9\xd2\x04\xaf\xba\xde9\xfc\x19\xf4\x00:\x89\x1e(\xbc\xe8w\xde\xf2\x15\u007f̿s\xa9\x93lt\xeeW\xa3\x85\xbf\xa8\xd1\xfdN\xe7~\xf4+lA\xbfڏ\xb3\xefm[w\xe37\xa8\xca\xf07n\\\xb7\xed\xbd\xd7\xff\xfaW<9\xe6\xff\xca-N\xbf߹t\xa7\xfa\xd3i\xa1?\xa8\xef\"\xf7;\xa1i\xa1w\x90[\xfd\xf3;L\xafvP\xa22\xd9z\xae\x8a\xeb\xe2\xa6r\x17\x01\xe4g\x9a\x11k\xaacl;#\xb4\x9dE\xee*\xa4\xa0b\x17\xb4\xc5\xc18\xd3*\xa5<~\x19h!\xe4\xe6\x19\xfb\x99\x87\x93:\x9cQ\xa2\x19@\xb4qӼek\xa0/\xcf\xe1\xbd#\xbd@w\xa2\xf5ꪫ'\x19\x1c\xa6\x9d\xb6\t\xf7\xfd\xe7r\xa7\xf3\x11\xf4*2_\xbc2mp\b\xbepm\x90\xd8\"Oގ\xbc:\x94wFg\x1cR\xb7\xfdۜ\x93\xe8\xea\x1b\xaf\u007f\xae\xe7\xd2\u007f\x9e\xfc\xfd{z\xf2\x1bh?U\x15_3\xd2\xcd\xff\x90\xf0\xf1\x82\xe9\xe5\x8bm3\xa0ؾ)\xbf\xdc[\xd7_\xf7.\xb2\xd9/\xb3\x99d\x87\x8c\rj\xeb\xdd\xef\xc4\xd1G\x13\xf7̨\xcf.\xfc\xc2+{\x1c\x1f\xbc\xfc\x95\xeb7g\xbf|\xa96w6؟>d\xf0\x14\xa4\x105\x96\xfe;{O\"\xc8-\x95\xa5<\x11\xbd\xec\xe0+\xeejaW2\x1b\xdf2\x9a\x8b\xbb\x92\x99p\xa1\x88\xbd\xa3\xfe\x14W\xdfa\x8f\x84\bg\xef\x9c\xd1y\x046&\xd9B\x1fh\x0f\xfa\xa1I2\x1a%\x8b\x9a1\x98\xcd\xe4\x85S\xb9\x9e\x9e\x9a\xfa\xfa\x1a*\xbe[\x17\x0e\x17Ϥ\x8d\xc2F\xaa\xf7\a۷\x15\xc9%nwT\x8f\x18\xe7\xbb\tQ\xb1\u007f\xaa\x10Ķ!=\xd2\xdc\x1e\x01\x96\xbc00!\xdb\u007fdP\xb0\xe7$\x13O\xac\xa2\xfa\xefj!%\x98\a\xf4\x16l\xd5\x1f\x1f6bd\x00\xb7\x88\xbf\x8d\x88\xca[\b6\xe6,6\xfc\xc8`\u007f^\x18H\xe6\xfb\x8f\x14fɖ\x01\x11\x113\x1aV\v߶[\x06\xf4\xd88|\\\xb2\x99M\x97\xe9Q\n\x11\xe4\xd1\xd9lƜYxj\xb0?KO\xb23\xda\x1d\xc5ٲ\xd0%)\xe8\xf9\xdc\xf5\x1c\xe7)JrGƼQ\xa5\xbf̼)\xee\xc7\x15\xe92c\xe2\"\xa3\x84\x1e\xcb\xe4^\xb0\u0096\x80;\x87\x02\xea\x10\x1a@Y5\xaf\x0e\x8eu\xe3!\xe6\xce\xd1'\xe1h\x88\xe6V\aGTi M9\x1c\xb1\xd2\x02#\x91(ן<\xc54\xd8s\xab{\xb3\xbd\xab\x91\xf6\x82\x10\xad\xde@\x96e\xcbfQ`\x18\xcaGy\xed\r\xa18\x80\x02L\xea\x95\x1a\x1f\x18\xfe\"KB3\xe4+\x82\xe7\x9ef\x06O\x04x\x0e\xd0\xeb\x85\x01\xed\xd9_\xa4c`=\vC@\xc5d\xb8-T\xa7Oj\xe6+\xc4\x14Jw\xd8]\b\x88\x9af1\x9a\xce\xd4\U00089826J\x80\x1c\xe5\xc8 \x1c\x05\xb0\x84-\x95\x12\x0eL\x98\xaf[,\xa7Əv\xceu\xd7&\x12}\x13\x86\x98z\xeb)Aԫyz\x9f\x1dX߶\"\xd9\x1f\xefM\xb6Ww\x14\x93P-蒺\x1fMr\x86k\x9d\xd7\xd9\xe8\r4\xd74L\xedZvɎiZ\x19c\x02K\xb9\xf8\xbaU/N\xcc\xccj\xa8a,\x86a\x8b\x9f\x96\x02\xeb\v!\"Y<\xf5\xcd]\xd1K\xbe\xca\xe2\xa9\x1e\xa2\xfa-\xb2\xbd\x94\xa0\xb6\xb3\xa7\xb9{S\xef\x8a\x1d\v\x96&\x82,\xf3\xa8\x10-\xf9\xc8\xfd\vl\x87\x145\x05\x84\x04V\x94(\xc0\x1e\xa6DSJZ\xa1\x87\xa0\x90\xa1\xe6\x11\xba\x11U\xa4\x93\xb8\x0f\xd5+\xfe6\xa3\xefU\xf5Ԥ)\xf6j\x9e\bȀMXju5xk\x8dO\xbcx\uf1e8\xffk\u007fC\x8f\x93f\xf5\xb3\xea\xaf>\xaf\xfb\xe7\xa9\x16\x1dv;\x10o\xe3\xadĂu)O[\xf3\xac\xd8\xc5H\x8b\x1b\xfc\xfa\xb3%\xee\xee\xb3rJ\xc6\xef\xc8r\xa1ZN\x95\xf8\xc3C\xe2Q\xf2n\x89?|\xd6\xed\x9dx\x90\xf1\x87\xcf\xe2\x06\xe3_B\x19\xb4\xac\x14\x14*k\x8c\xe9gY\xa1\x1an\x94\x833:B\xb5\xac4\x1bWͤ\x13u\xa1Q\x9a\xaf\x9a\xde\u007f\x90\xdd\xfa\x97.\xe2R\xdaM\x9cF\xad2\xc3\x1e\xc4\x0f\xa4>\xbd\xab\x138\xaaG\xa73J<\x06Z\u008a\xb2r\xa7\x8c\xb2Vŗ\xc7Y\x9b~P\xc29\xab\x9aw\xb6;\xd5<\r+\xe4i\x18չ+\xe5\x805\xce\x1bD\xbb\xe8D\x83h\x10p,;ʹ\xddj\xce\xee\xa5\xc2fƼ\x01=䵫9\x8f\a\xb1 \x943\xe5\xf5Ƒ,\xea@\x05\xff('h:\xd4\xed\xd4Ƌ&m\xc1\x17\xdfTkP\x12\xe8\x1dq\xd98\x1f\xc3\U000e8d31\xd6!\xdeä.\x98\xe5\x0e\xf2#\xf6\xfaQ\xd0{\xfa=\xb3\x97\x1c\xa6\xf3=\f4\xa6\xcdV\x8d\xbf\xf4#\x8d\xd1m\xab\xb2\x98x\t\xf1_\xf2)If\xedC\xfb#y\x95\xf3F\xc8\xceN\x83\xad\x95\x8a\xb2\xfb\x8c\ru\x93\x04\x92\x01\xb7\xd9Q\xe7R\xa4\xd2\x1dPQ\xdf\xcdy\xf6\xfdQ\r\xe3u\xe4\xf6\xac:\x9d]\xb5g\xcf*\x04O<\xb8j\x0f\x19,0?\xc9\xd3g`O\xf9N\\Z\x06\xe5\xc8\\\xa3F\xedk\xe7rIݝJ%QM\t$%G\x97/-\xabS_hz\xac\xf7t\xbe>U\x87\x16\x80\x8b\xcf֧\xd4c\xc3\xf9\xd5'\xba\xd4\u007f\x16P\xb1\xe2\x00\xfcfՅԭ\x89\x99\xbeں\x10\xda\x0fo\xd4>x\xe9,u\xab\xc8\xdb\xf9\x8a\xc6P^\x0e\x87\xf3\"\x93\xad\xe1\x18\x10\x8d\xbd\xca\x1d\xb9\xb8\xc5yXdc\xaei+\xaeY\xf9_'\xe9z\xad\xb8\x85\xe5\xb9\xf2\xa5\xab6~(+q$\xaf\xd5U\xba;\x1e{S<\xfa^x\xdc\x02Gn}\xc7\xdc\xf2\x16ou\x8bvXt%\xfd&3`\xb8.:gA\xbb\xa6\x85\x15\xb4'\xec%\x1f\xce\xc1\b\xc0O\xe0\xfe\xc1\x010j\x1e\xaa@E\xe5w\x86\x81\xe2:\x9d\x83\x1d\xef\x14м\x05\x8ejd\x9d\xa6\xabq\x84g\xd1\xcae\xd9\xe9\x95\x06\xff\xa7\xc2\x17\xb5\xba4\x12c\xc4&\x0eū\xa8\x86Y3\xd7]\xa4\xf4*\xb0\xf6tI\xda*\x98\nr6% \xda\xdc\x01\xea&A\x00\x13\xa9R\x85^3\xbc\x06\xb4$\x15\xf2p\xb4\xc5,\u007fa2GÇ\xa8}O>W4\xec7\xfc6Ո\x83n\x0e\u007f7[\xb8Y\xcc\xf5\xa5Nq\xa9\xbe\xbe\x94\bO\xfce\xbfcu/=\xcbcm:&\x964\xfc\xed\x1c\xaaC\xddo\xd3\xcc<\xcc\u007f\xfe\x86}\xb9\xdci\x96A\xa0O6\xe7\xb3ă\x8cN\x9dY\x94\u007f\xa2\xd3\xcc\xc8m\xda\x05:\xc1̲f3\x8eJ\x9e\"\x03M\x93\xc4K:\xc2Ek\x90\x99\x92:e-O\xb2\x9b\a7\xcb\r\x8d\v6\x17\xdf\xe4;k\xec\xfah}\x13\x19x\xcb?\xaf1\xe6/\\\xf6\xc2\xf1g^\u007f\x05\xc5\a\x9fy}7\xba|\x804\xd7\a\xd6\xd8\xcd\x06q\xc1\x92\x8b'\x93\x17\x067o^\xd0\xd8 o.\xbeUξ&\x00\x87\x03d\x8e5\xce\xf3\xe3\xa7v\xbf\xfe\xcc \x8a\xbf\xf2\xfa3\xc7_P\x9f\x18 Mp\xc8\xd9\xd7\x18Ĺ\x8bV\xf4jl\x04\xee\x8cU\xca\t\x1f\xc2\f\xd9a^vqǹ\xd3܈\\\x97\xd6?虽쪰\xf3\xe3:\x8f\xa1\x9fOo\xe6\xa7\xc2\xc8\x0fb2AL2\x88\x12\xf9\xb09\xd0zXv\x85\x8a\x03Q\xf1 V\x16Uq\xf6\xc0^\x01\xe5k%@\xab\xec\xff\x9d\xcc$Ǡ\x88\x1c\x82#\xa1o}\x9f\xf6Ts\x16\xfdcFW}\x9b$y\xb6\xcbF\xc3\xf5\x91\x98\xd1$y^2:\x90\xa7\xbe\xe1\x06\xc9l4\xdc/\x19\xbam\x1e\xd3a\x83\xa5\x9cԽ\x83&\xado\xaaL\xaa3Ѥ\xa6N\xab\xc7\bIq\xee!\x93#\xc1\xefĺ~\x8b\xd3\xe9\xb4\xf4\xeb\xf0N>\xe10=\xf4\x90ٞ\xe0\xf9\xee\xb6bD\xa2A\xe4w\xf0\t\xbb\xf9\xa1O\x9b\xbeh\xca\xe8\fC\xc2\x01\x80\xf9Tѡ\xde\xff\r\x83\x8c\xbc\xa1\x86֩F\xbdI\xaa\xdd.\xad\x90M\x1b[\xbcV\xc3#\x06\xd7Œ\xee3\xd5z\x83e\x9e{\x82\xe2EvceR]\xed\r\xd2\n\x87ecsER\x9d\xd1\xd6\xefn\xad\xf7`{ah\xbf\xcdZ]\xb5\xa5\x8a'3W\xbb0v\xad\x9eIx\xf0V[m\x10Q\xe3\xa1\x118\x1c\xb8\x04\xa2f6\xe0\x194\xceSc%\x1f\xfeWr\x95\xe5F\x18.\x1caR\xaf6\x91a\xc3\xcc\x1c\x10Lv\x120\xe1n\x9e\xb1\b\xe8=\b,L\t\xf0\x85Z\x91B\x1aU\\\x8e\x8a\xa1\x00]\xb1a\x80JX\xbb\xd4L\xd0\xcb\xea7\xffe銛\x1f\rljQƀ\xb4c\x81\x88H\b\xdbj\\\x86\x9b\xef}\x19MG\xb7\xa2\xe9\xb8\xf3ޛ\r\xae\x1a[X@\"\xd5W\x84dNS<\xfc\xe8\xcd+\x96\xaa\xff\xf9\xfd\xf6\xda#(\xb6\xf5\x96;<\xb7\x1d\"w\xab\u007f~o\xafmyL\x0f\x94'\x91D\x91\x97\b\x15\xdbpEb\xdeY?\xdd~\xf7{{\xf7\x16\xf6\xee\xf8\xc9,o,\xe2RD\x04\x91\xbc(J\xc4bC\x92>\xb6ܶ\x87_\xb1dՇw\xcc\xed\x9b\xf9f\x19\xeff\xbas\x9dܦ\x11k3\x88ގ&\xd3\xf4~\xbeL\t\xc1\x11\x0e=\xa5$&\xf4\xab\x1b\xc1\x81Cyd\xb0\"\x9dle\xb0\x9f\u0604\xe9 \x8d\xec\xa7tQRʉ\xea\x9c@\x02*\x1a\xad\x99\xa4\xe1\x8f\u038b\xab\x83\x03\xd9\x01\x9f7\xd2\xe0\xce\xf0JՄpC\xd4\x16\b\x98#5-\x9eV\xe1g\xbbo\xcc\v\xb5!G\xcai\r4\xe5&\xe9\x15\xc0N\xbfpO\xf8\x92\x81o\u07b4խ\x0e\xd1\xfd\x139\xc2k\xdb'y=JS4\xb1\xe4\x8e\x19\xad/\xac;\xac٬\xc1\xb9\xc4\xdc\xf6\x1fv\xacY\xed\xbb\xe13M\x9eiB<\x90\n\x85\x1d\x85\x9c(Yuv<\xfb9_\xadm\xf6\x9c@|zU\x97\x1d\xad\n_<'\x18\x9e;\xd5\xe5^;\xf7\xee#\x13\x9bb})\x9cK\xf5yw\xf7\xa5\xaan\xdc\xd3\x18\x99\xb2o\xdb%\x97\x1f\xe6\xca6\x98\x98,i7\xa5-+v\xb4(\x9bk6\x1ei\x8dc\"Y\x04m\xc4\x04\xaa\xe7\x87=t#WRT\x99\x95\x9e\x88\xa5m\x8e\x89\x8dR\x1b[\xe5\xe3\a\xa0\x86na\x92\xab<\xa4\xe5\xf1j\nX\x9d)G\xa8VX\xb3,\xb7\xfbgB\xab\xa7\xa5&b\x0e\x04lц\xf0\x84*\x85ϸ\x1b\"^\x1f\f(\x1a\x88\xcf\xcb\x1d^\xf7Bk(tǒD\xb4>f\xf4ʭ\x1dk\xc3\xea\al\xd0\x02\ueb79W\xae\u07bc\xff\x8b\xa8\x93(\xfaI\xbc\xa6d\xa9r\xa1U\xc8\xdeU5=^\xa7Df\xdbj}\x17-\x9a\x8d\xed:\xab$\x16r\x8ep(\x15\x88\v\xd3%\x12\\\xb3x\xa9+>w\xb7W\x1b\xb7\u0604\tO\xee\x15\xe6\xaeu\xbb\xa6\xce\r\ag\x17q\x82/\x92,\xa3\xc9\x01W:˺/Ɏ\xb5\xde+\f\x9d\xfa\xde\xd9\xe6y+\xd7&\xd5\u007f\x9dLo)\x9b\t\xa3\xd4\xe9@\xd6[\b\x1c\x9b@\x13e\x8ax\xe6\x18\x9b\xc9b\xaei\xea\xc0\xaau;\xd6\xce\xf2:\xba\x1d\xdeYkw\xac[50\xb5\xe9\x9bx:\x9e\xf6r\xee\x9d\xc2\x03\x8es\xd8S&_Xx\xf3\xecf[b\xeeT\xbf\xdb\xed\x9f:7ak\x9e}\xf3\xc2\xe7\xbfYx\x03\xb7\xbc\xfc<5\xaa\xec\x18\xcf\xdcr\x19'\x17\x03\xb0\x97\xc4(>\x17q\xba-\xb8\x12\xd7p\x15\x03\x8ar\x9a\xed\xb8\x96\x94o\xcc\xcaɴ\x1b2\x9c\xc3H\xb0\x9aU&\xa5I-K\x15\xbd\x94\xf7\x81\xa8\xe5m\xbbh\xe0ɠ\\\x18\xa2\x82\x88YF\x98\xe4\xe9\xb5Y`\x80\x0f\xb8|fM0]63\xcf\xea\xdeB\xb6w5\xe6%#\x8e'i\x16H\x1c(\xda8\b\x00\xb2[\x18*\xe9\x01k\xb8.\xb5E\x05tc&a\x0f\xc1\xce\xc7Nm\xedV\x80JQ\xd4K\x89T\xc8M\xc0\xcd\x0eb\xd7X4\xf4\xfd?\xfe\xf1#4c\xeb왓Q\xc7,<\xfb\x8f\av\xdc5\x1b\xff\x91\x90?J\xd6\xce\t[\xd1\xc9J\xd4s'\xfeڛ\xc9iӒ\x89\xe9Ӈ\x9fC\xf7>\xfa䶵\xbd\x85\xfdh\x8f\xe2\bMz\x02__\x89m2\xde7\xb3\x99b\xa42\xf5HC'\xec\f\x9f\xa0\r \x16j\n,J\x18\x05\x94N؋\xc4\x1d\xa5\xf8\xec\xb0\v\r\x01\x86\a\u007f\x18\xe8Luq\x02\xdbM\xa8Z\xe8W7\xfa\x94'./\x9b^L^\xfe\x04\x1eDL\xb4\x83\xd9%S\xff\t\b\xd1\x1a\x93\xbd\x1a\xbd\xa3\xf8n\xfa\x1e\xe64:O\xe5\xbeW\xa6\xbf\xe8^\x1a\x1d\xcf\xfeo\x8df߷Rпl\x85q\xbc{\xbf\x11\x91\\\xcc\x1aPȖ叙y4*x\xfaBa\xabv\xfd\x87\xf7\xbf k\xa2\x8ax@͗\x04qY\u0092\x10.3\xc8H\x16Q\xa1F\x96\x8f\xdd\x02\xd2|\xf4:r\xc4Ɣ\x87\xc2\xe99`P_\xeeSR\x01L\xa7\xa8\xad\x10\n6b\x8a|jAn~<\x10D\xd7\x1f\xdbN\x15\xd9\x19\xcc\"\xd6\x13u\xa8\b\xb3\xc50\xc0\xf4\x1f\x1d\x1f\x14Q\xa2\x90\xad\x80\\\x9c\xd7 W\xa7\x81u\x99ާ\xb2\xeffn6\xbdoH\x01\xf5玤\x82N\tN'\x97S;\xc1\x10\xbb\xf8)̓vG\xc2vejO\xa4\xc8XJUP\xc5\xe8\as\xcep\xc7\xf9\xef\x9c\xe1\xe6\xdcs<\xb7\xf8\x9e\u05f74\xa6\x94\x9a\xae\xa9}\xdb\x1c\x96a\x98\x92m}S\xbbj\x94T\xe3\x96\xd7\xefY\xdc\x16C\x01h\x19eu\x06bm\xf8\x9e\xa7\u007f20\xef\xf9\x8f\x06~\xf2t\xcd\xf3'r3\xef\xdf:_H7\xd4\xcfM\xa4笜\xaeY\x98\x99\xberN:1\xb7\xbe!-\xcc\xdfz\xff\xcc\\\xacM\xe3a\xd2\xcbP}\x85\xce\x02\xa5l\xea\x00\x9e&pq\xee6\xee\x01*_\x1bU\xa8Y\x04\xed\x99IG\x8b~O\x1a\xba\xc1\xde\xcc_KU8\x9c\x19\x1a\x92FT{\xc2\xe5t\x80\x13\xce(\v\xa6\xb7\x16\xd0av\"CBf\x80\x8a\xce_F\xc9\xd0;Q\x98\xe7n\xecqӳ\xc7B$MU\x1b*r\x8c\x85g,\xf1\x92^\x80\x9fG\x00\x1cD\x12\xc4\x16,I\x88H:7FD\xd4\t\xe2Jl\xd4\xf3\xf0k6\x19\xba\xb0\x1bc'\xbe]\xd3u\xf8\xee\xa3\x0e;\x12\xe5\xe4\x84&\x9d\xa7\x1e\vFb\xb4\x88\x8eF\x93\xadiB\xc0\"\xf9&͙\x15Myk\xe4\x99U\xbe\xf6\xfd\xed\xc6P\xbf\\\xe3M\xf9\x9b\xb2]J\b\xd9\x1d\x8f~\x17q\x95\xfb\x05Z JP\xb7$5K\x84\xd7\xe9\b?\x89\xe71/\x10,#\tK:I\x9c)\xf1D\x82\x1fo\xb3Y\xa1\xc5:\x1eMg\xaa!'\x9fS\xff\xbf$\xb1\x99\x92M\x88 }\x9d\xafÊ\x04\xa3N\xe2\xab\xdd~\xbf$\xb6\xb8Ū\xd4\xe53\xe6\xb7w\xcf\x11\xabm6\xbb]r\u05cas\xba\xdb\xe7O^\x96\n\xdb\xf8\xball\r6\xd9H\x12\x19\xf1\x9d\x95{R\xc9vB\x9e\xcd\x1d\xdb\a\xceo\xbf\x8f\x19\xdaLg(\xb8i\xf7\xebZ\x14\xb5hVd\xc1\x9d˂\xdf\xe7]\x97w!\xae\xebr\x17\xfa<3\xe2\xd7H\x85/\xa9\xe4\xe5\x19\x8e\x1a7Cy\a\xccY\xbeN9\x87\x11\xbf\xb6Y\xb3\xda\xda\xf0@\xac\xb4Lc\x80\xa9\xe6eY\xcd֖\xcfY\xe1\f\xc0\xe0$\xeerz\xce2\xd5d\x8a\x0f\xb2k`\xa6\x96\x0f\x84\x15\xd58v1\x91\x0egI1\x9c\"0\x8e\x8c\x13k\x86~\xb4\xb4,\xa3\xc6c\xd3$\x06\xb5\xb4\f\xb4\xe0t\x06\x14y\x97\xc5h2\xe8\f\x06^/\xcfsv\xfe\xa9\xa3骩m{\xa7\f\xec\x9aT\xe5\xf6\xba\xbd\x97UM~{\xf2\x8bW\xdd\xf6\xf3\xed\xb9\xfdÏ\xdd\xfc\x83ɿm\x83\xb0\xd9k\xddU\xe1ٹ\xa5\xf3\x1e\xfd\xf6\xce\xce?\xb6\xcb\xfd΅s\xe0\x044a\x9b\x03\xbf:\xe1\xee\xeaZ\xffD\x9fg\xa5;\xe2@\xfaV\x8fם\x9e4\xfb\xdf\xff\xe3\xb6\xd8`\x83gل\x1aw]x\xe2/\x90\xf3\xeeg\xd5o\x9e\xceL\xa8\xa9\xb9v\xb6w\xb9'v\xa4\xe1ڟ\x9f\xf8ڔ\x8e\xaey\xad\x86\xb5K<+\xc0Ǟ\xa8\x94\x85\xa0\xba~NF\x9b\x02=ΐ7\x8e.'\xbeh\xbc\x88ٖ\xa5}\xc2t\xdb)v\xcfSK4\xd3Yԉ\xa9\x86\x86\x90s\x1a]kW\xaf\xaaN\xf6\xd4-Я\x99\xbbK\xfd`~k\x88\xd4\x1a\x1dR\xa2-^\xb5\xac\xda\"9BF%`%5\x96\xc9S'\x1b$\x17\xea\xff\xee^\\o\xa9\xd6;\xda\xe2\x9dNKM#_5y\x86\xe8r\x8f\xd9֖\x19\r\x9ej\x9f\x97\x10\xa7\x01\xf2K\xa2\x19g\ueedc\xb8M\xb2dn\b7Y\rn\xbf Nl\x9e\x14\xe0ݮ\x83\x93m\xe1\xaa\x06G\xab\xf8Y\xf5\xb5N\xec\x90̂0\xad9E&W\xeeK\x88\xcab\x89K\xe0|\x9fĸ\x8a\xb0\xf6\xb0\x05\xf1\x1a\xa5JﱵW\x17r{\xd8ݷ\x9b\xf7\x14\xedkQ\xfecZ\\2\xf5R\xd4\xff؛\xeaO\xbf\xa0\xfe\xe7ۡ\xa6\xb7_\xb8\xfah]\xd0\xdfԸ\xf9\xe0\xb4y\xbd\xf3&܈V\xbe\xaa;~\xc7\xfe\x81M\x03\x91\xab/\xe1\u05ed\x99n\xf1߮\x16>\xf8_\x9b\x1e\xe0\xf7\xe1[.\x13\x8c\x9e/m\xe3\x152\xe1\xde\xc5\xcb\xfb\x1e\xfa\x8aA\t\xdfq\xfcJ\xd7\xe4\xeb{\f\x8c>\xb8\xf4L\x8e\xfc\v\xe0M\x8c\xff\xcd8\x84A\x12\xa2\xf6f\xec\xda]\x1b\xf9\x97'\x96v\xa2HTUO\x9c\xe1μ\xf1Ń\xc2\xdf\xd4\u007f̚u\\\xfdeA\x8f\xff\x8eb\xbf~\xe9u\x8e\xe9:\x9fy\x8e\xcd\xeb\x12n\x15w\x05\xb7\x81\xbb\x9e\xdb\xc9\xdd\xceݥIٸ\x9c\x9c$j[Q\xb4\x9b\xa7\xd4\x1a\x1c\x98V*b\xdd\f聇nE\xc4C\xd1\x04*\x01\x82Z\x00ɭE\x94o\x04?҃\xd8&\ak=\x95t\xc8\xe5#\xb7\xf2=\xcaK\x8f\xe6\xa4T\xefrf\xe2\x19\x1aW\x12\xdcQ\u007f\xf3\xa7j\x1fJN^yٔ\x86\xf9\x91\x89\xfe\xf5Q\xe5\x92W/\xb1\xa5\xae\xf3O\x8c\xcco\xc8^\xb6rr\xd4\xe0j\xed\x9d\xe2\x91;\x9cN\x97M4I\x92\xbb\xc9`0wϚ\xea\xf6 _\xf5\x9f\xd4ߜ\xb8\x88\x18\f\x84\x18\xf4!Io\x10\xe1\x17\xd6\xebuz\xbd#\xae3\x99tz\xb3i\n\xb1\x01\x8dk\x9dj\xb7\xd9m\xed\xd8f\xe3\x03L\x12\xe8'\xa7\xd5k\xe7\n^\a9\xd8u\xd9Dћ\x9e\xbf\xfb\xa2\xed\xcbVn\xd1Ǽ^\x9f\xcf\x18\x98\xa8߲r\xd9\xf6\x8bn_\x90\xf6\x8a\xe1\xa9\x06CSC \xc6\x13\xbd\xc5\"\b\x866\x8fGi1#\x9eW\xd6\xf2\x0e\xaf0\x17=p\xfa'\xe8\xb2\xe1]\x92@\x048z}\x82Q/\nF\x83\"\x99̒\xe0\v\xeb\x8c&=\xfclF\x81w\xf3\xa2d\xc6F3v\x191\xf1\xeaF\xdduDFY\xa6V\xe8\xa4'F\xdb\xeb\xa1\xd8\x18`.bN\xf1\xc1\x19u\xe8䡁\x91\x8f\f\x00V\xcel\xee\x90|I׀\xda\xe4ɷ\xc5*\xac\x1e~\x83\x9a\xe4)\xf1\xec\x8b\xdfZ\xa9*\xda!+\xf1\xa6\xcbu\xb9\x18\xd4Qv\x87\x9d\xe9C\xd0M/\x93\xa2vԂ.q\x88\xeec\x9a\x92\xadY\x16s\xb2\xd9,\u007f\f\xcf\x01\xc4\xe5\x10\x94\xbb\xbawD\xad\x16\x82\x87\x86\xcc\xf2iN6\xe3\x81\u00a0Y\xa6\xe6\xd2r\x9aL\x8c\xa0\xe9\x00\a\xa9U߲\x06\xb0[cr\xd2c\x84q5)\a\x13V\x9f\xdb!\x94c0\x17\x1e\x8931;\xf4\x9aB0ތeG͝Ua\xecV\xbf\xf9NU\xd0e\xf7\t\x83(\xbc\xe5\xba;\xb1\x19;\x1d\xfe\xfb|\x11d\xfa\xb2\xfa;\xf5\x96_T\x85\x9c\x0e\x1fA\"\xfa?/}\xf3M\xa4i\t\xab\xdf\xf3;]\xc1\xaaw\xd0t7\x0eW\xddY㰛\xef\xbcn\x8b\xfa\xd6\xd3\xd5Ng\xa8\xea\x17h7\xaa\xf9\xb2\x19E\xaa\xee\x03B\xc9\xfc\xe67_R\x83E=S\xaex\xb7V\xc75P\f\x87\x1bs\xbf\xe6\x19\xfbm\x99`\xc9\xfcržYa\xad\x96\xb7\xb5\xf4\xb6\xb4\xf4\xa2\x16\xf6z\xaaRa\xf9t\x9c\u007f\xfc\t\xdek\x19\xfe\x8b\xc5\xcb\xf3_\xd2F\xda\xf6=\xfb\xaa\f\xb1dVٿgC\x97\xf5j\xd9\xe8߇%\x83\xcbT\xd5\xfb}\xf4[\xb3\xddn.\xdcZ$\x91\xb3Uq\xbc:\xd5ۛ*<\x1dgg\xc0n\xc6Gh\xe6\x92\f\x1a(U\b?.b\x81=Ђ\xe0\x98\xb6 z\xae\xa73ek\xe7\x01\n4\xc4\xce\tv^\xccQVJ\u007fR\xbdT\xdd\xd6\xde\xcb+N\xd11\xa9E\xa9y\xf6\v\xcd\xd2D\xb9\x9a\x18\xec;Y\x9dC\xe8+\xe8\xf5d\u007fN\xbdA݇n$9\xc6\xf7M\xf6\xa3\x95Ay\xf5\x86hpJ\xa2\xa3\xa1\xb6=^\xdd蹭\xf3\x86%[ҫ{\xa9\x8d\xd1\\\u007fr8L^R\u007fڠ\xfe\xa5\x91\xf1\x9d\xb2g8\x91ޥ\x19\x01~\xa7\x00a\x9ed8U=\xa5gP\x90\xb3'\x9b\x011\xc0.\x1b#l\xd8\a\n\xe8\x10\xd3=ΑѬzR6\x92\x83np\xe4~[\xc7E\x81\xabf\x17n\x10\x9c\xeaG\xad+\x1ey\xe9\x91\x15\xad|\x1e:\x92\x85\x05\xa6f\x93\xfd\xf1E˻\xa2\u007f~E\u05f6\xa0M\xf7ʟ\xa3]\xcb\x17\xbd\x10\xb8\xa8\xc3f\x9b}\x15jE\x13\xb03\xb1qMOϚ\x8d\x89\xc2{\xea\xc9d?]u\xfd\xc9\xc6U\a?\xf7\x97\xbb\x0f#\xc1/;\xe9\xf2s\xca~\xf5\xf4\xe1\xbb\xff\U000b90ebؚǀK\xaa\xc2-\x8c6\x03\xcaB\xb4\xb2'\x15闘̵\xc4L\xac\xd3g\x0fc\xa1\xd2g&\xad=\xeb\x98\xd5G\xfa\xf4\xb8\xb5'\xcd\r\xf9\x85\x81}\xb5\x06S\xec唩\xae\xa6\xe1\xa5VC\x83I\xaas\xdey\xa7\xbf\xb1\xc1\xd0\xfaRCM\x9d)\xf5r\xccd\xa8\xdd7&UC͝w\xd64\x8cN\x83sc\xb2a7\xcdfl\x18\xc9\xd6\xe8\x1f]t\x83\xc1Tw\xf7ݵFè4\xe5o\x92\xd1u\x9e\xe2֍\xe5\xa72\xa9B\xaa>#\x15o7(\x83\x10\xf6\xbdJ~j\x89E(\x16\x19\xaaEM\xde\x12\xae\xd1-P<\x93\xd7n}\x82en\xaapt^\xbc\x90\xaf\r\xd7^<\xd3\xdb\xeb5\xc7fͬ\x9d>3\x10\x98\xf5\xca\xf7\x16\x1e/rQQ\x1f@\xe2\xc3W\x1fヌ\x93\xfa\x99\xe3\x9f\xed(\xb2Q\x03\x06\x8f\xd7Um\xf1\xe2)!s\xac\xbe\xa5G\xb9\xe5\x197\xba\xa1\x92\x99ꜜZ\xdc4\xb5\xeb\xee\t\xae\xec\u0085U\x93\v\xb9l\xb6\x92\x89ڟ\xba\xfap\xf7d\x8d\x83:\xbdCc\x04\xeae\xbb\xdf\xea's2\xaeE\xdd\xd9\xd0\x1d;\xa7u\x1e\xe6*\xc6'\x05\xbb\xe0\x16\x8e\x8b$\xec\x9a]\"\xf6\x9f\x9a\fc4\x81\x8b}\xac\rv\x0f\x8azyDz\xdfɨ\xf7n4\x86\x8cbTF\x0f\xd2.b4R#\x11\xd4P\x17*\x8e\xe7\xa9\x15\x19~6\x10\b\x84\xa6t\xc6jt\xfc\xac\x98ŋd\x87ۥ\x9by1\fW!\x1f\x9fןD}\x1ag\x95\xbflْW_A\xeb4R\xab/\xa5\x0eu|\xf6\x95]\xf7\xbe\x80P\x17\t\xf2Ǯ~\xf8\xf0:t\x83\xfb\x99[\x94\x9e\x96\xfa\x9894\x05{-\xd5.\xafǀ\x02\xa9\xbe\x1c\xcey\xe3\x8dA\xbd\xb00\xeb\x06\xc2 \xa8x\xba\xa66-NMv\xceM$\xfb\x19c50g\xb6\xcd\x1b\xb8hQ6\xab\x14\a\xb6\x00\xe3\xd41\xfd\xb1\xfdB\xff\x95n\xd7\xe4\xee\xc3W_u\xb8s\xda\xce;B\xd9\xeeE\xae\xcc\x1c\x02\xe3g\x97\xf5}\\\xa5\xfd\xff\"\\\xf1\xa5a\xa0\xa6\x1a\x9aQ=\xbb#\x96\xec\xdaͧ\x9d\x99\xefվv\xc7\xfe\xb3\xa3\x8d1\xeaŊS\xafY(R.i\xed[\x81\x8c9\x02\xf8\v\xc5\xfaJd\xe7\xd1QӜ<\v\x120@B\x8eNya\xfc)\xbfj\x040Vh\x9f2쬄\xc7s\x01\xed\xd2O\x00\x9deP\x1e5>I\xae\x93~\xaf\x91\xea\xa91!\x00\xc6\xfb\xa1\xff-\xbc\x06A8ag\xc4j\xcaNq^7\xac6\xea\xc3e\xab\x13\xb0/\x89쾇ݳRuԢ\xc1Z&\xfdU\xa1EJ\xa9\xb8l\xb6p\x9eYo\x9e<2\xe9\xb9\"\x15_\x9c\xec\xf4\x14:\xd9\xe997\xde9f\xb2\xd9\xda阎\xb3\x00\x88\xb3.\x04\xb5!\rhI\x17\x1b\xda\xc24\rRk\xa5\xf3Cj\x11\xaeG\xd3Bu\f+b\xfa\x98\x99tQ\xf5P\x12\x9du\b\xd1/\fА1\xfa\x99T\x18Z5\x1c\x97\xe5\x95\xf4\xdb\x01\x87V:\x1c+\xd1zp\x82\xe38\xfa\x88j\x84\x8e\xa7\xb1y\\ST\xa4\xe9!\xa9z\br\x81\xe3\xf8\xf9u8Y۸$\xfd\xf8\x13Յ\x84F\x95uFY\x13\xdd\xf1\f\xcaTj\x1c\n\x02+[k\x8cj`\x18\xe2GŦ\xa2\xf5+\x91yl\xd3֦Y닍\xf1\x8d4\x14R\xab\xe7\xd4\xd3,\xb6+\xaa\xe9h\"\xad)=\xa8\xacU\xcb>\xce\x10\x1e\xad\xafyV\xcf˕!\xcb\xd8V]\xc9Z\xeb8G_\n\x17jW\v\x1b\xae\xb2p\xa8\xa6H\xea\xf4 ֬Q6P\xa8\x1e\xe98=w\xb0Q9\xbb]W\x8c\xcc\xf280\xc0\x9d9\x9f\x1e\x9c\x11\xfd\x12{\xb9\xd1z\x0f\x16$\xc55\xeb\xcep\xbe+\x94\x8d҃D%ꔒ\x8a\x18-\x91\xe4\xf5\x16\x14R`5CbJi\xa5\x95h\x82EI@\xa7\xb9\xdc\xf4x\xa0Q@\x87\xb9-\xd8J\xb3\xc3\u007f\x89\xfeh\xean\x94\xa2א!7\x93\xfb\x87#ם\x8e\xbaY\nѣX\x10\xad\xa1\x9e\x16\x99\xa6\x052\xec\xcfM\x8d\xe9\x89n\x89\xd2Ɣ\x18\xa4\xd2\xcdi&\x82#i\x85x2n\x8fB\x85\x02\x80~\x8c\xd2#\x9d\xf2}2n)Ͱ\x13\xda.w\x06\xb6\x14\xc9\x03o\xb1\xc8\x14B\xe0\xa1\xc6\x1e\x19\x1f(\x93\xd6\fY\xc7k\xa1\"\x16\x1b\x8a\xbb5n\x11\xb3\xf7G\x19\rPTF\x8b\xa3\x84\xb8;\x93N\x89Q@\xf7(\xe3\x9a奣$\xba\xea\xe9%l7Q\x18?\x8e\xcalR\x1a\xbe\x1b\xb1P\xe4fB\x12!w\x9aҤJƝa\x95îG\xdbٍ\x00\xf1J\xa6 \x83vK\x1b\x8dg\xea\x01WOӬ\x94\xbbL_\xe9$\x9b\x90t\x88\xb1\x9ba\x8c\xe8[!i&\xfe\x1eM\x17\xed>J\x16\xe2\xa1LBf\xddR\x81\x04\x16\x9e\xba\xa0%\xb5\fۣ6!\xe1o\xac\x06\v\x99\x86\xad\"\x16\x04$\xda,J\xbd\x1d{\b\xf1\x12l2\"Qo\xc1\x06\x83\x88\xb0\x15#B\x04Q'!\"\x12\x11\x13#\xb1\xda\f\xa2\x9eH\x02\xb2:\x89.\to\t\x99\xfd<\xf1\x019*a$\n<1ʔ/-\n᪠(J&\x82\x89\x1e\x99$\x12\xb2\nf^o\x90\x05\vћ\xf4}\xd5\x1d\x8b6\xdf,\xf6\xed\xe8\x98\xda+\xf0\xb9\x037\x0e\x1f\xba\xf1\x80\xe4\n\xa4g\xac\xed2\xf4.\xb8\xe3\xae;\x16\xf4\x1a\xba\xd6\xceH\a\\Ұf\x97\x8f,-Jǒ\xe0\xe6Ew\\\xf5\xf4B\xa1wjǎ>\xf1fM\xf8\x11\x03\x14.\x9c\x87.kl\xf2Dj\xee.Xv\xdc}\xf7\x8e\xd4\xdamW\\:5֔j\x82\xbf\xd8\xd4K\xafضV\x883\xd9B\xb5\xae\xf8\xa9\xec\xc2S\xf3\x16\xde$l\xbb\xbb&\xe2ijD\xebYdIO\xed~q\xb3\xf0!\x17\xe4\xa6rW\x17\xad\xa5\x00)\\\xcb3\xb2\rH\xb1\x11\xc3.iT2\xfcR\n˔D\x83\x88'\xcdi\x9a\xf8\xda>\x13-\xda\x00(*\x8fQ\x1e\x8b\x87\xb9\x84\x17\xfco\xf8c\x8d\xb5$`\x94\xa5\xb6\x98\xb5\xcag\xaa#A\xff\x89ꆘ\xff\xa0\xbf0\xc5\u007f\xc2\x1f\x8b\xd6\x1c\xf4\xfbߨn\x18\x9b\x8a\xec\xba\xe8\xe0\xe2\x1d7.>\xb1x\xf9\xf2\xa5;w,yc\xc9\x18?\xcaƠ\xf4\x00\xa93\xf9\xaa\xac\xb16I6\x82\xbb1\xe6\xffq\xb5\xef\x80\x1f\xff\t\x1c\xfe\xea\x03\xfe($\xaa\xae\x1b\x9d\xa8\xf0\xf6\x87\x8b\x0f,\xbe\xe8Njwܴt\xf9r(y\xb4\xb7h\xe32\xc7l{s\x1a\\p\xd4@\v5\xa9H?\x88\xa5]\xc3J\xb5Hʽ\xfd\xd4\xe9\xb0g\xd1\x1aIhh\xbah\xef\x03{\x16\xaf\x91 \xa5\xee\x1a\xfce\x8b\xddf\xce\xd5\n\xc4\u007fzUs|\xe1\xaa+\xe6D\xb5W\xf3\xc2xst\xce\x15\xab\xb4\x17\xb2\f\x04-\xf3}\xc4\"\x00\x9e\xf4\x8b\x01<\x04;\xe6\xa0\x1ep>\v\xef#\x03\xb9\xc2?\xbe\x84\x8dX;$}\xeau\xcepȖ\x05\x94ow/\x8f&\xb5ν'\xb5dޒ\x9b\xfa\xefM-\xa93\xebg\xcf֛떤\xee\xed\xef\xd8\x18\x9d\xbf$y\xef\xdc\xd6I\x88\xefE\xbbuR\xd6\x16\n;\xf75\xeeIt\x84\xe9\xa3Б\xd8\xd3\x18f\x0f<\xd8n\f;u->b\x03\xb4\b\xfd{\x00g\xb3\xea\xc2-\x03:\xcc\xf36ާ\xe6\xb3\xe8\xf0>\xc2k\xf70ڹQ\xc7\xd5s\x11.A\xbf,1\xea\x1e\xa6xB\x96\xb4U\\\xf6tBBA=\n\xca\xf4\x10)~\xa23\x99.{\xc4\xc1ҍPa\x88~\x11\x02\xd1OBP\xbb\x02\xd3:s\xea\xcfQS\x81=\xbf\x8b:Uf\x99\x00s1\xf2K\xcdɗM\n\xa0@\xf1\xdb\x13\x90\x19\xcaP\xbf\x1e\xfb\xb9\xfas\xfcy\xf5\xe7\xeagQ'\xd5)\xa2_\xad@\\l`\xf8\x1f|N\xf31\x9e6\u007ff\x8fp\xb3p3\xb3\x02\xed,Y\xd5\xd0,w\x14\x05\xf4\x8bZ\x1b\x881\x9b\x92\x15~ט\xf4\xc2\xcdOn\xbb\xf3\x8a\xe1\xbfoy\xeb\xa9'\xafǗ\x18\xbalfC\xe1\xe9\xf9W\xae?\xd0Ot=\x8b\xb2Kz\n\xdf\xf4\xd5\xd7(U\xe8QC\xb7\xcddP\xaf\xec\xb9n\xd1\xf2.<\xfd\x8a\x87\xb7=y\x05\xd1]\xff\xf8S\xff\xb6\xa5\xf0\xb4\xc1d\xeb2\xe0K\xe7\x1eZ\u007fu\xff\xf0\xdf{\x96d\x17\xf5\xe0\xe9^\xa5&P\xad^\tq\xdd\x06\xf4h\xd7\xf2E\xd7AakF\xc9\xf6Q\x1d\xed\xe9\xda7>\x98<\x1f\xfb~̈^\xbf=Qby\x8d\xd5A\x1d\xabs\xe7\xa1X\x1a\xfd \x10Gr9\xa7A\xfd\xa3\xa1ժ\xdd\xc8\xe5`\xb8\t\f\xb7\x9a\xab\xd0\fΕ\xbfMʆ\xdf돱\x8f\x13\xe5,\x93\f\xa8\xca\xe0,)\xf6\x9f\xe64K\x11\x98\xab\xb8ݑ\x87Y\xac\xc0\xbeZ\xaa\xfe\xc9?0J\xf7d\\;|\x95\xd7\xeb\xfc\xc0h\xb5\x15\xed~\x8e\xddki\xf6\x8e?\xb5e\xef\xd1v\xfe\xce宰\xde\xfd\x87\xf1\x9c\xec\x8c\xcfK\xd4\x0e\x83v\xbf\x16\xe52\x14\xa3)i\xb09J\xb7\x86cj\xe7\xce\x11~\xb6Uivo\xa8\xfd\t\x1fV\u07b4\x9dʍ\x13X\xe9~\x83eC\xf7k\x06\x86\aˆ\x94\xc9\xefƆ\xa0\x11K\xd3ڰZ\x99n\xe9߹ZX\xf1\xfd\xb0ko\xe4n\x86퀭\x82\x8c\xb6:\xa4h7Τ\xea\xc5\x10\xfb\x90\x15\x9cG\xb2+Ș\xae\xda}I\xb4\x9b]\x0eSfn\"u\xb6!\xf2`*\x91\xa4ئ(E3\t\xfb\x05\a\xe1\x96M\v\xd7\xf7N\x9e4\xb9\xa6\xe9j\x9fnRX\xb6M\xb1\xadGs/Mtb\xf5\x90\xd8\xd2\xdb\xdbRS\xd5\x1c\xba\xc8{i\xfb\xec+\xa6-\x9a\x8ev\t\u007f\xd6\xc6\xc1a\xd1\x06J\xfd\xd2\x06\x84u\x8d3\xefZ/\xbcW\x19S9ZK\x16\xac\xea]>\xb1Ɵյ\x19\xa668\x10N\x1d^~\xbdi\x0e\xce>\x15v$\x96$\x9b&x\xaa\xaa\xdb;\x12\x93\x17ό/n\xceTu\xaa\xdf\xd2\xc6\xcc\xe2\x90\xc9\r\x97_\xdep\xa4\xc1d\x8f\xf4\xefR7\xaa\xb7\x94#ƌ\xeb\xc8]\x8a\x95Kqk\xd9^:J\xb81\xa2)Ǥ5\xa3\xb0\xda\a$\xa82\r;\xd8ʗ\x03$X\xb4\x96[\xba\x8d\xd3\x14Z(ޜ\xcah\xd2J\x9e\xa2\xad7*\xfd%2E叙\x14#\xfa\x8e\xdf\xd3z\xc7g\x10\x1f\xdf\xd6{\xad\xc1h\x11LK,\xf1\xd4\xf2\x9d\xd7M\x9b\xda\xdb\xfb\xf3\xe9\xeb\xda#\xef\xa1Ǥ\x06Okdւ\xd9\vn\xban\xe1\xfe\xc9V\x1d\xa5\x1b\xaf\xb4\xd6Z\x85\xd0Ħ\xee\x8e\xd9پ\xb9\x13[\x16\xd6\xe3\xdcȷ\xf7\xb2\xa1\x89kV\xbc\x98\xdb%\x9b\xc2ʂ\x9b:\x1d\xd5@S>Զ\xb2\xa3}\xf9\xec\xa9S\xbb\x9d\xcd~\xef\x19.\x9a\xbavm[k\xa8\xb9\xd5\xe1\xf2\xc4l&\x9dż\xb1\xb5V\x89L\xc0\xf5s\x14\xdd\xe4H\xd8\xe5\xae\xf6uvM[2\xbb\xa6\x82/z9ն\x97\x95\x16\xcd\x10.\xebS<#y\\\xa26 n\x97G\xae\xe8\xad\xd6\xe3fmȬ\b@\xcb\xe3\xcexʃEӻe\xf7\xc8\xc8iwX\xb0\xe1D\x95\xb1v\r[#:b\xae\xeeL\xee\xa9_\xbahkm[-\u009d\xd9Nٌ\x90E\x9c\x18\xeaZ~\xf1\xbaemM\xad\xf6\xb0\xdd%Y\x81\xe6\x96뛮\xb0\xe0%\xaf\xf7\xef\x00Z\u007fbt\xb6h%:\x8b\xe8\xb2\xfa\x949}\x1b6\x1dxn\xdb\xf6\xce.\xb7\xcd^%,uXF>\xa3.\x041^\x8ex\x89\x00\x8do\xc9\xea\xf5U\x96\x1b\xccQ\xf1\x1d\xf5O7\xcf\xeb\b\xb6\xf8\x1d\xc1\xb0\xbf\xad}\xf6\xe3\xf3\xd7\x1c\\\xda1\xd5\x15B\x98,5\x103V̒ׄ\x8c\xa2\xd5'Ō\xb2z\xe7w6\xf57Oi\x9f\x1c\b6\xb7\xf4\xf5o_\xf0\x04\x9a\xfbrU\xf8\xd4\xed\xa5\xb9qp\x9c\xa1,\xc31\xf6\x9b\x02\xf7qOi\x16#*\xfbn\x1f\xe3\x1f;6\xff\xd3\xfe\xb1\xf5\x8d\xfdF(\xfdNy\xc5'\xea+ܣcT\xee\xdcq\x9f\x88\xb5\xb3\xbb\xb3\xbb3\xb3\xb33\xcf3\xcf\xf3\xfc~x\xa4h\x03\xe04[\xe6\x87 \xb8A\xfe=,\x13O\x9e\x14c⋢\xc8rx{\xf2\x95\x95+=\x1e\xf4\a.z\xfe\xf9\xe6f\xf4G\xffA=\x92\xbeSM\xd0ϒk߉\xe1kѥ1|\xad\xf8\xe2u\xe4\xa4g\xa5\xbd\\=\x02=j\x82\xac=$\xb2\xf2\xbf\x99rR3\xf2,\xec\x18\v\x1a\xabxٰ\x1c\x8bU`B\x01\xc5!\x82\xfc\"\x01LQ\xfc\x90 \xd3Jc@(\x02\x8f\x11\xc9\x05{˯\x82\xe4\x9dF\xed/\xb5\xac\xe2\xda\x0f\xba4\x92\xe03\x84i\xac\x94bM6A\x87\r>A\xd2 \xc5\x1d0Z\xc9\xf8\xa2\xd4\xe6\xee\x0f\xb9\x18\xa4\xc9(\xb1\x00\x10\t\x8b\xe8zc\xfa\xc7d\x97I\rQ&\x87\xa0\xa5\x01\xc0\xbe\x12\xf8\x0f\x00Z+8L\x18\xd3T\x13\xb3W\xbb\xfd\xe8&\xae\x94\x02 \x90\x93a\xa6Q\x19\x1c\x06<\x10a\xd5\x1e\x87\x18\x11\x90\"\x1a\xc7\xff*F\b\x95\x05S\x11)1\x87^T\x8d}uМ\x03\xe35`\xeb\x0e\x87-q'6nh\x92\xb4\x95־\x96\v\u007fڻ\xe3O\u05ec\u007f\xf2\xe2%\xe5\xdd3<\x1ah\x80\x9c%r\xe2\xc1\x9b\x1eܿ\xa1e\x9a\xa0\t:b\xb5\xad\v\nVY\x98\xd7\xe5\fz\xe8l\xb2N\xeb]6\xc5\xff\x93p\xc3\xfe/\x0foyiOc\xcf\xee\x1f\xb4\xf7\xde\xe95x\xf9\xf1\x9c\xc3\xdar\xd6M\xef\xdd{\xe9\x8f>_\xd8\x12ؾ\xb8\xb8v\xe2\x96\xf9\x9d5\xf2\xf2\xc9\x1b\x96\x80\x8b>9\xa1X\x81ru\xebʓ\xfb3\xb5\x13\x15r0\xb5rd\xf0\xfd\xce\xcae\xf0\xa6\x94\xf8\xe1t\xf9|\x87\xb6¶\xbe\xf9\x89\xbfL\xde\xf5d_\xef\x13\xbb\xcf*\x9f5\xc3hct,g\xa9}\xe3\xfe\x1b\xaf\x19W\xce\x1e\xadi\x99\xef\\\xe9\xb4<\x95\x1fc\xbcs\x91\xff\xe1p=\b\xffi\xde\x1d\x17v6\xf4\xec\xbal\xe2\xda۽\xacN\xa8\xb08\xa4\xd6E\x87߹\xfb\x92\a\xfe\xbe\xb0ٿ}aq̈́\xcds\xa7\xd6\xc8+Wߚ\rD\xceٶ\xdcD^\xc3؉>[DP\xe1\x04j\x1dq\\j3\x16t\x82\x91h \x8ad\x1c[\xc4\x16\x19)\xa1\xd27r\xf2\xe1\xf7h\xf7\xf8\xf9\xb1UW]\xb5jiK\xef97\xf6\x0f\f\xf4\xdf\xf7\nX|\xee\xb9\xe7\xa1\xff\x80\x98/\xc3\xc2\x1d\xae\xd0>g],p\xcdK\xd74\xadY\x8dW_\xdeځ\xb3\x9d\a/\x1b&\xdd\xe2\xf9\xef\x1e-\xc5.S\xb1\x80\xad0\x8f\x14\xdb\xeb\xe0\x89+\xb7\x95\xf40:\xee\x8b\xfa\xecA\x1b\x16\xc3\x02\xd1H4bc\xef\xf8\xb1\xfc\xd37o\x94\xbf|~۶\xe7\x81\xf9F\xe0y\xedW\xdb\x1f\xdeub\xe7\xce\x13\xbb\xe6^yV{1\x87\xf4\xaa\xc7\r\xf4\xaa\x13o\x9d8\xf1\x16\xdc\xf8\xa6\xfc\xecS8#(\x03\xe6緥~\xb6\xf9\xa2w\x86\u07b9\xa8jҢ\x99\x81\xa1\xb66\x9c\xe7ĉ\xec\x1a\"\xc6h0P\x85T\x05\xd1\x04\tu)\xef\x88\xe1 \xa3\x12$\xea\xf9\xab`]+\xacE:\x85E\xf9\x82q؎\xcdW7jD\xc7\xd1\xf3\xc9-7\xcc(3\xe2uŲ\x19{\x0e\xef\x99Q\xa6l`Y\xdf\xe1\xc1$\xfe\xee\x98\xe4\xe1OC\xaeoɊ\x03\x8f\x01\x85\x93= \xb5\xbf;h\x95\a>\xbe\xea\xe0E3g^tP\xd9\xc8e\x90\xc2\x17\xc8\xe4\x97N\xe4\xf8\x82B*\xd6\x00\x83\xf4\x1bʘ\x89\x92!x\x06\xa8\x18\f%\xc9\t\x8c֙\x90\bY\x12}\x16IK %\xd5ep\x1e\x90\xdaH\xd1\t\xe5ZR\x05\x15\x01\x01\x03\x90\f\x11́\x14\xc6\x1cH\x01\xe2+!)\x0e\xf9ʵ\t*\t1B\x801ˬ\xabB\x1b`\xcd>\xf7 &\x91\u007f\x1f)ç\x9c\x84\t&\xaf\xcc\n\x90\xa0\x03\xc0\x04)\xb3\xf2,\x1c~\x93)|H}\xee\xf0ؚ\"\x8a\x8a\xf8\x88od\x10\xf3A\x8e\x9e[\xfbaO:)\xb1禓\xb0G\xa1\xce\xce\xcewLr\xb0\xdf(y\x99\x9e\xc1\xa4ļ\x96\xcfC\x82\xfbg\x8aQ\xb0\xe7\xdc#[U\x1c\xd1N\xc3\xdb84\xa2\xd9~\x97\xd7\x12c\xb4!y\x0ez\xdc\x19\xdfݰ\x1b\xa9\xd7ҔZ\xc63\xbc;z\xe4ss\xf1\xc4.\x8cF\x92\xfb\xee\xed\x0e\xc6\xe1\x81M\x90ؾ\x831\f\x1dF\xf1\x02S\x0eI`A\t\xb1\xe2\xaa4Q\xcaByE\x03軼a\xca\xf9\x11\x00\"\xe7Oi\xf8\x11\x98\xdaP\xbe\xb2S\xbeb\xa9nByḰ\xa6\xe7XK\xf9\x04\xdd\x12\xf9G\xfe\xd6\xf3\xe6\xce`S\x13VЍC\x1f\x13/|WM\xe8߫ʪkj\xaa\xcbv\xfd!\f\x16\xcc:\x18\x91\a\x13|uQ\x89(\x96\x14U\xf3\x89Ϝe\u05f7\xcd\xec]N\xde\xf9#h<;\x87\xc4\xfd\x95\xab\xf8\x16v\xc5U\x17{\x13\x92\x15}\x85\xa2\xdef\xf1\x89\xe6j\xe0\xb3\x05H\x88%X&?\tV\x80u\xf3\xe0\x9c\xd5\xeb~\xb8\x9a\xb9V~j\xf6\x82\xb6\xf96\xbd\xfc\x14\x12\xfbA'\xb4\x96MY\xd7v\xf4M\xfa\xda!\x1f\xfdGP۹re紳\xcf\x1e\xfa \xfd\x12\x14\xd7\xef\x98\x14\xf1D\xd2\xef\x82k\xc1\x97\xe3\xc7\x1f\xf4\x8e\xaf/\xfes\xe6\xbd)\xe3k\x1d\x99\x13q8vI8\x84\xc3\xff#x\xd5\r\xfb\xf4\x90\xb9\x83\xe3G,\xf3c\x80?\x06\xa9\xe6;_\x97?\xba\xfd!\xf9\xe5sy\xa0ٯ3\x99\xf9ηw\xf4>w`\xf6\xec\x03\xcf\xf5\xae||\xf2\xfe\xbc\x95\xf9\xbd\x1b\x80t\xfd\xed\xa0\xf0u\xbaP~I\xfe\xe8\xf5\x9d\xd7\xed\xd3\x15h\x0eh\xa1nE/\xca\xfe&\xbaj\xca\xc4\x03y+\xf7\x97\xacٸ\xf3uT\xc6\xd2S6\xeeo\xeco\xb1O\x9bo\x18h-\x0eN\xf5p8ޗU\x8f\xb52$\x1c\x9au\xa8]\xa8\x8a\xc3\xc8\x01\xac\xbav$0$\xb4\x84\rc\xec\xdb\f\x16\xec߂\x1b\b\xef\ue361\xf2S\xd4\x1e\xa1T\x806\xc6\xcch\xe8Bڭw\x89.ci\xa1\xdc[\xa8\xd5\xda\xf5\x1e\xda\x13ҙ-:\vg\x85\x82\x00\x96\x8e\x95\x15\xdc\x02\xf6\xb8*\x05\xb7K\xde\xcb\xceh\x9eq\xa0\xb4{F\xf3\x16A\xc9\xf1\n\xd9lW\xf2\xa5\xe4\xc1?\x14\x15}\x00\xb8'\xf1M\xae\xf9R~<3.(\x98[v<\xffQHPC\xb2\x0f\x86\xa4\xe7c\n\x1a}I\xcc\x1cbr`\\\x18~`8\x1a\x17\x01\x89\xee\x92{\xe5;N\\\xbbw\xa1\xdbYu\xf3\xae\xf2\x86I-\xaf\x82U'N\x80\xd9y\x18]\xac\xc99\n\xa4\xebKp;\xf8+\xb8\x9dI^\xf9\xf7\xfd\x9b^\x99V۳dv\xdb9!Ns\xe5߁\xf8\xf7_倻l\x961p\xbb~\f\xc2G\x8f\xe6\xd6 p\xecF#\xb5:\xbf\x16\xd9:ԅ\xf0[\xf8\x0e\x14\x05\xf0\xdd\xf8\tH\xfc\xa3\x17˯\xcb\xff\xbe\xa3\xaf\xe7쀿\xb0\":s\xfa-@w\xc7\x1d\xe9;1n\xc2\xf13\xa0+\xb0\x8d\xdf\vU\xe1\x1a&\xd9\xfb\xe8\xda97\xd7\xd7ϳJ\xc5:\xa1\xf7\xd1W\x1f\xfd\xeb\xfe\xbf\x9f\x01ja\xf0\x9b3\xa3,\xec\xba\xe0\x04\x1a\x1f\xc0)\x8a\xbe\b\x8da>\xc5\x0e\xab\x18 \xe2\x12\xab\x18'Tgx4J\xd0A\x1c\xf0\xb2]ԧ?2\x161:\x8b\x85yA\xeec4\xa2Qd\u007f\xcd8\xcd`\xaa\xe4b\x8f\x82\xab4\x8cD\xbflu\x0e\xee*\x80l\xa1\x99.]\x03\xf4&'\xdd \x88\x05\x16\x8dN\xaeY\t\xf3\xb9?\xe6\x0f_\x0fEJ\x0f\x92OG\x92#\x8fy\x8c\x18n\x03\xb9\t^\xc1\xf3\xb1\xf9T\x14A\x9e\xaa/UB\n{d\x8a\xacȎ\xb9\xd7U\a\x95}\x12xX\xda\x031r_i}~8b*\x95\xc9=\xc6^]W*s->\x9a\xea\xaaK\xd5\xe7d\x93\x14\xd2fgQ\x8bU\xb9(\xe3\xf0\x8e\x91s,\xb1Ze\x95\x11\xabM\\\xc6\x14\x84\xbd\xc9\xc0\x88]2\x99)\xb8\x041\n\xcf\x1a\xd8$\x04l!?OnG'o~\xf3\xe6P]h\xe6꙾V\xda'\x19\xf5\x86\x9aE\x8d\x1d\x17\x94\xf36Fo\x11\xf5\x8c\x8d/\xdfq\xc5\x0e\xb2+Z\xc8\xee\x05\x1d\x8d\x8bj\fz\xa3\x04*\xa9S`\xfeO\xaf\x02Ɓ\xfb| M\x95U\x94a\xdf\xdf\xe7\xd3\xc7{o\xbe\xb9\x17\x8b0\xb53g\xd6\xc2\x0e}\xc8(骪\xa65\xebJ8\x8b\x85+\xd15O\xcbOWU\xe9$#\v\x9f\x02\x96+\xba\xaf\xff\xf3\x01\b\xdfZ\t\xe1J,\x942Y\xbb\x8a\x06i\xc4n\xac\x81\xb0>Ŗ\xe2\x1b\xb5X\xe2\xcb\xc6p\xb7\f'E!\xab\xf74\x92l\U0007aedc\xc4\xec\x8ci\xb2\x9a\tS\xa8\x0e\x14(\x97߁T\xce\xd8R_ʠ\x94̈́\xe7\x82$^\xca\a\xfd\xc0\x9bŊM\x9f\x8b\xf2\xcfO\x93wޯ,\xd3cӊф惞\xac\\I\xb8`\xccT)\xb5\x94\xd8&IX\xb9\xaa3\xa1\xe6W\xa3\x1a\xac\nSv$F\xf4ݸ\x15{\xb8e\xa11\xb0fH\x02\xb6ț\xcb\xfcaw\xf2(Q\x1d \x1c\x90\\\xd29u\xb8\\\xb5\xab\xa6\xf7O\xdax\xf9\x81\xcb7N\xeaЍ\xd3%\x8d\x1f\x19\x93hۑ\\W\xd9\xd4\xccT\x17\x14T\x1a۪\xac\xdd˻\xadUm\xc6ʂ\x82j\xa6\xb9\xa9r\xdd\xe2\xeb\x9e\xfa\xe9S\xd7-\xa6\xc9\xcakU-\xba\x9b\xb7\xabn\xeaE\xb3*+g]4u\xcd,}\x85\xfe\x96뮻\x05mf\xad\xb9msM\xd7\xd6\xda\xc2X\xd0\xed\x0e\xd6\x159\x9cU\xb5\x15uu\x15\xb5UNGQ\x1d>\x16+\xac\xdd\xdaU\xb3\xf9\xb6UG7O\x98\xb0\xf9(\x19\xff\x15\xecY\x17\x89A!\xcb\xd49ې\xc2#I\xdc%\xccy\xb8\x94\xa1\\\xa0\xba\x02gf<\xd9/\x19\r\x06\xf9\xe7Z-H\x10\xaa\xc8\x1eL\x86HP&O\xf6\x13\x94\xdf\x1e\x05E\x12\xf4\xa0Z\xa0\u007f:\x94\x0f3.&0B\xa4\x04}\x19\xb0H\xb2\xb4\x9c\x85\x84\xcc`\x04\x12n\xa2(\x89\x01.\xcfY\x802\xb6,L\x10\xc8~\x87]\x99\xa5Da\x80\xdcx\x00\x93Q\xf6`2\xca\x15:\x98\xb16_u>\xb66\xdf\x0e\xe8\xa6)+\xfa\x0e\x8f\xdb{?\xec\x11D\xd0C\xec<\xfd\x84\x01\xb3\x1fUk\x85\xe1mb\x83\xde\xfb~\xdcc|\x1bT\xfc\xf8`\xebᾮ\xd6\xe2\x13\xa3\xcb\x18&\x8e\xcb\n>E\xd6\x0f7\xa2\"B\x9c\xb6\x8c\xf81\xa8\x15\xee\xd2\xe5\x15\xf6;\xca\xd8/\xe0\x9a\xa0\xfc\x06\x83 ʤ\x8dA\x8f$\u007fv\x9aBf\xfa\xbb\x1a\xff\xb5\x88\xea\xc9Ytج\xaf\x06\x1dG_)\x01)P@\tp\x14\xa67\x8e:\x00\xfez3hfa2\x1c\r\xdb\x0f\x85\xeb\xb0\x0f\xa6\x87\xc9:v(\xa6^&\xa4\xb8m胍\xbd\x1d\xf6\xc6ɛ\xfa7Mi(\xd8\a&\xef+\xe8;\xec\xad\xef\xae\xf7v\xf5v\x91\xed\xa4&\x00\x18\x9d\xa6\xa3\xb71\xa8\x97S\xaa\x1b\xc7\xef\x88\t{\xf7\x85\a\x0e\\ر\xe7\xf0\xd6%\xa6\xba\x8eW\xac\xab[\xba7m\xeanYm}\xa5\xb5\xb8\xb7\xb7\xb85q\xb8oqQ\x19\xfe\xb8ˊ\x16c\xbc\x8c\xdc^\xc7\x0e\xbfnBq]\x99dZ\xb2\xf5\xf0\x1e\xfa\xb7\xaaCG6\xb6\\i\x8b\x199I/\x8e\xd4\x1f\x8b\x95\xf1\x96`\xc2\x12\x95b\x94\x98}\xc8\x17\x81ޥ7\xa6\xf8\xe2\x935!\xe5\xed\xe1pa\x9br\x86H\x12\xb5ٰ\x85)\r\n|\xf4\xbd\xef\x87\\\x9c\xce\xd2\x1c\xc0n\xef\xbe\xe2\xe3@s\xbc؇Ӂf\x8b\x8es\x85\u07bf\x17\x1fj\x98\x82Z\x87V\x9c\x0e\x12\xad+m\xf2\xf6#\x1f~xd\x9f\xf5\xb7\a\t\xa4\x86\xa7\x04Iq\xa2|\x1eY\xbd;$\xa2\x9d\x12\x0f\xc4\xfc`\a\u007fk\xddG\x0e^i[ي\x9aF\xe5\xfaT\xec\xaaX\x9b\r*\xbeQl\x0e\x1e\x1d\xe9N\x91\xac+\x94\x8a\xa1\x1e\xc9xD\xc9\xfd\x04Ց\xe9\x1f\xa2\x92\x8a\v\x14\xa4\xf6-M\xa0\x83L\x12\x83\xc6\xed[J\xa3\xf4 \x92\xb7\x14ϧ\x81\xa1\xd4\xd2},\xb5\x0f\xb5i.F,2\"B\xec\xfbG\x85щ\xef\x19\b\xf6\xbd\x02\xbf\x14\xd90\xa1\xca\xf6~\xf2\xa6Ie\x81O\xe9\xf4\xa8Ö\x8f\xe0[咛\xba\x13\x89\xeeo\xbf\xe4\xa9\xc3}\x83T\xdfa>\xf1\xe1\x91ľ\xa5\x18\xed\x12/\xc2\x1c\xa1\xc7\xf7o\x92\x93\xe9\x14z>\xa3E}ʋ\xdb\v\x0e`v\xae\x1c\x16z%5Q\x91\x06\xf8l\x84\xa9ҥH\x97\xb1+\xd8+\xc3\xd3l6g\x9e\xb4\x03\x93S\x1a\b\xf0\u007fÔ|\x18\x05\x1c\xc5B\x91\xe3h\x988\xbe\x0f\xbbڱ\xa9t\x12}\x16C_Ꮐ֣\x0f\x05*\xf0\xb0=\xc4\x19\xaf\u007fd\xfa[\u0099\x01\xd1\xe8M{\xf7\x1dW\xec\xbeJ\xfc\x8a\x84f\x03\x05\x03w.a4\xb0\x8d4\xb2\xf3\x16\x1f\xe6D\x05\xea\fo\xc9\x01\xe4*\xf9\xd8\x11V\xc0\x91VA\xf68\xf6sP-\xef\xc9Ҟ\xc2}\xe0\x02\x9dA\xfe\x95\x01\xac\"\xee\r\x14\x06\x1d\xce@\xce\b\"\x1cȤ\xf2\x8f\x8a\x02\xb3\xaf\xb0\xa7t0\x89\xef\xc2\x11+|\x87|E\x91\x014\x18N\x8a\f\x85Ł\x93\x14ݓ1\x1a\t\xfd9\xeb\xde)*\x97\xc6\x11\xdfY\xfc\xfaѶ\xa4\x87\xa9\x9fQoP\u007f\xa4\xbe@\x12\x94\t\x14\x83J\xd02\x9a\xb7::b\x9f\x1d\xb1?2\xffH\xde\xea\x91\xe7ϴ\xff\xff\xfa\xfa3\xe5\x1fY_\x8c\bn\xc9x[\x8e\xc2b¼\xd2Y1-\x87\xd7M\xe5ҧ\xf2\xd2\xf4i\x8e\x9f.\xfd\u007f#?<\xcd\xf1\xe1e\xc6\xf8\xa9\xb8n\x04\x18\x8b\xcag\u007f\x1f\xc8\xd6\xf4_\xa3+\x9ew,\xfd\xaf1\x0e\x8e\x95\xfa?\x95Q\x1e\xeb`\xee\xe7\xe4\xf5\x18tt@\x11\xe0\xf2܁\xf1\n\xe4w|3OQ\xbf\xa7\xbe\xfa\u007f\xff\x95\xfcozi\xd6/#\xaf\xbf\x16\x80\f\xdf@ :\xdcۨ\x05Dl\xa3\xf1\xed#\xbe\xac\x06\xf3\u007f\xa5w\u007f\xdf\xdew\nk\xc2h\x1c\xc4i\xa5\x17\x92Sy\xe5I\xaa\xf7\xcb\xf4M\x90@\xa3$\xe6\xc1I\xfc\x1f\xeb\xa3g\xe8QC\xd73I/\x1e\xb0\xbd\x83Iү\xe8\x94RО\x9e\xacc\x95\x92\xae\xcc}>\x80\\!\x0f\x84\x90Б\xc8\xf2\x98c\xdbk3F\x06ʷ\xbe\x12\b\u05cc8'\x91חe\x8f\bd($lٷY\x1bS\x00 \x86\x19hC\xc4:\x1bSl\xb3\xd9i\x98,\xbbɯ\x80䝂\xe6\x97F\xf6i\xef\xa8\xfb\xe0$\xac\xc2柌\xe5\x16\xfbt\xf6\xbb\x12\xe8n\xc4_=\x94\xc1\x96Pp\xeb\xc3T\r\xfa\x16;\x95(\xca3V\xfd{I\x85D{\x1a\xa3\x8aiEZL\x12\xe9\x87I\r\xa6\xfasҢ\x17\x1d\x04\xfdc\xd7\xe6\xf3\xef\x14\"3\xf8\x1c\x04\x17\x1e[*8#\xe0\x03\x8a\b^NG#\x96\x00\x1f\bc\xab`4\x1c\x8dcCf4\x1eq\xa0\xa3\xd1&\xa8\xf8\xfa\x82\x88\x83E\xda:\x9f\x04\xf2\x87r\xff@B\xfe\xfd$\xdc\xfc=\xfd\x89D\u007f\xaa\xc7\xebM\xa6RI\xaf\xb7'\x85\xf7\x8904\t\x04\x13\x03\xa0'yP\x03\x13^\xf4?R\xc3\x04\xad\x17\xf4\x0fxS^\x8d3\xe9Ԡ\xed\x00\xe8\xf7j\xb1\"\x98\xf0\x16\x8e\xd7\x11\xfd!\xa1\xfa\x9fp\xa8\x17\x12\xeb\x04\x16sm\xbeh\x9c\xb4g8\xee\x8b\xfb\x90\x98\x84\xf1\xb6\xa7G\x1941$\x93G>Lx\xc1\x80\x97Ny\x138\xde\xe2\x14\x15\x9d.'R\xa9ԇG@\"\x91L\xa6\xbcC\x03\xc38S1\xf3I\x8e.u\x84ߣ\x02\x0fB\xf0\x0fG\xe1\x00\x11?>\x99\xca\xf1\xd6\xc2\fsj\xbe\xed6\xa5خ0\x05FƆ\x85\a\x04\x19{\x01\xd0\xff1\xc27qD\xb9\xbe\x0f\x97\xebX\xe5\x92SJ\xd9Rʳ\x94R%F\x96L!sM(\xa5\x1b~\x01l\x1c^0\x88\xe4\xec\x19\xf4\xbf\x98\b\x92\xe2\xc6a\x8dv$\x17.\xaf\x05\xccX\a\xe1V]\xadΥ\x93\xabt:\xf0\x16J\xd4\xeat\xf2\x0e\xb0\x1f\x1c\x18\xf3\xf01\x92\"GЏ\x92e\x87\xbcC7\xf6aR.#*\xd7\u007ff\xcaE\xe5|[r\x9c\xba\xccX\a\xe1\\\xfcp\xe5\xbe\xfb\xd1\x13\xc8M\xc1[\xa8\\c\x1d\x863\x94\xb2\x92\xbd\xfd`\xbfZ\xe2*\xdd؇q\xb9fPW3\x11f\xee\xb0\xf6\x1a\xce\x0f!\x8eu\x90\x89\x9c\xa9\xd6\xc3\x0e\u007f6\xaa\xa8\xf8\xf9\xe0\xfc1\x0fSJ\xb9\x8e\xa1rm\xcdo\xaf\x11\x1c\x13\xe2X\aQ\xb9N[\xdd1\x0e\xc3c\xa3_.ʁ\v6\xc6a<\x16\xa1\xfe\x05\xb7\x92\xf7\x88K\xa5\x05#\xe9\x96QGRs\x0f\xeb7\xf4gc7\x16\x19\xdfP߀s\xb3\xf7\xfcޝ\xe0to\x9b\xdcs\x0602\x11z\xaer\xcf\xff\xc1\v\x04\xe7\x9e\xee\x9d\xe0{V\xa2{n͕\xf3{6>]y\x9a\xe6T\xedЊ\xdcX\xad\xe0\xa5\xe6\xa3\xf4(\xb6|\xab'\xab\x91\u05f5\x82h\xde\x18\x82\x97\x1a\xbf%\"\x02\x97 \xb6\xfd\xf4\x80\u05eb\x90\xa4{\xbdi\x02\x91\xc4\xe1`./Md\x8a!\x9c\x95\x9e\x81]Ђ\xb3[\x8cx\f\x11\x9a\xbbC9w\xb4<\x1f\x10\x13\x89X\xc7c\xdbpKC\x00\xe4a\xcf\xe1\xb2b\x11P\x95\x19#lm\x1d\x1a\x01\xad\x11Пur\x9b8\xd8/\x19\x19\xf2\xf8\xc1\x14^\b\xedW`\x9b\xfa\xe9Mfs\xbf\xd9\f(\x05=TA\xbf\xa5{r\v\xdc\xd2\xd0\\\xb2X݃f\xa9\xac?8\xa3\xc8:\x0e4\xb3g\xe5\x9c\xe0\x98\xad\x96\xbfd\xa0\xe0<\xfcPm\x01#\xad4V\x0e\vo-Y@\x18PV\x94\x87p\t\xe8׆9\xea1J\x01Ⱥ\x89C\xf1F?\xdd\xd3!i\x82&0\x92\xc2\x00\xbcI\x00\x91\xa8SH\xaa\xa3H\x1d\xd1o\n7A?\x18\xdfU'S\xca\xeaC]\xd7\n\x057\x894\x81\xb2\xdeO\xcf\xf0z\xbdC$\x03\x83\u007f\xf3\xe7\x1f=*\x0fE\xa9L\xb5\xad@1NfY\x9eoȒ\xd2\x1e:4\x8a\x96\x96\xe9\xcf#\xad}n,\xac\auN\xf7\x11\xf6\x9f\\}Za\x13\xc8\x10\x1dgi\xc8\xf2\xe9~\xc6\xce@S\x9b\xba\xe5d\xf7&l\xe2'\xb3Y\xa2\xefp}\xe9@\xf7&:y\x9a\x130\x81\x0fo\xea\x86)\xec\x1a@\xa6\xbe\xc3}H\xf8U\xb2\x8fq\x9c\x1a\xb3\xdc\x02\xccSs\x90\xacG\xe6\xe9|\x9a\xa2\xef\xce@S\xa3\n\xb6\xa9\x1b$q\xb9Os\x82I\xa5\x13#K\fH\x89Os\x1c\x17Y\x83d\xf9\x04Y/\xd4R\x16\x82\x8a\x86\xbf\xbf&5\xd6@\xc1ѩ\xcdF\ff\xa2\v\xac\xca\xf2k.\xde`\xec\x1c\x8a\xd7\x1e\x14\xa6G뺦\xf7\xc1\x16Ÿ~%\xd90iB\x15\xd07}\xa8y\xf9\xbe\xe5\xcb\xf71_\xaa\xa6w\x05\xd0lᆬ\x98\xf5q\xe9\xbe_\xf6M\xc7\x19\xe5\xffR\xa4uŐ\x9e\xbe\x06\xdfp\xfat\xfa\x1f\xf8\xd2\xe5\xe9{\x94\x93JH\x82\xbcE\xb92#\xc7f\xfb,\x95\x8ft\xc1\x8dD%Q}\x1b\xf3:\xe30\xfeZ`\xa51\xa4\x82\nb\x8a\xfd\xc1\xd9\xf2\xe1\xfeW6K\xc4+\xa1\xd1\xf1b\xdad\xe0\rf\x93\x85e\x03\xad+7\xdfr\xdbJLZ+S\x12\xd6!\xd1\a\x0f\u007f}w\x14\xf4\xffP\xfe3\xefwi-V\x936\xc0u\xc4\xd7\xf4o\x9f\x1f+6\xe0\x98]\x92\r\xff`\x14W\xf9\xdc\x1fd\xb1d)\xf2\xdd\xd5P\x8b\xf0L \x00\u007f\x15\xa8#,{yi\x87\x82*\xe5\x0f+\xfe\x91\x1e\x1aӕђ\x95\x17\x98\x80\xbf\x8a\tg,cʺ9^V'\x8b\xbf0Y\xd02\xaf\xa5\x00\xff\xc0[\xb2\xc9g\x0e\x9c?\xee\xd6)\x0fM\xb9\xb9\xfc\xfc\x03\x89\x95\x87~0\xe7\x819?8\xb421\xd0\x12\xba\xfc\xfa\x9f\x1f^:3y\xff\x81+\xfa|\xadW\xb8#\xe7ܻ\xe1\xfa\xbboط\xfe\xde\r\x11\xf7\x15\xa0\xb7{^GǼ\xe1?\x17]\xf0\x80M\xaf\xb7=p\xc1\xa2K\xa7W\nB\xe5\xf4K\x81捋flj\x0eh9i\\\xeb\xea\t\xbb\xde\xfc\xecȜE\xdb\xd6Κ\x17\xf0Ι\xb9v\xdb\xc2\xd9\xfdÿ+\a~\v긇\xbf\x9a\xef\x1c}\x15\xb6$\xa4\x8a\xa7\x139\xf33&\x8d\x1dE\xa04\x00ɹD\x16R\x10\xfeu$\xa3\x92\xc2c\xb9\x9d\xc5<\x96a\x1c!\x05\xea\x14\x10;\xd4\xc2\x04\xb4\x17Ă\xbe\xe8Ȃ!ŕ\xcd1/嗋X\xcc\x1dv\xee\xab\xe8`\xaat\x89K\xfe\x9d\x18e\x12\xa5K\v@H\x1c\xbc\x92\xa62\u0605\xb8Ѐ\xaa8\xc86T\xc9\xef\x95\x1fj\x1fLeˍ4\xbbT\xec,\xbb\t.\v\x94\x17\xcb7:́\x8ab\xb0\xc1\xfex\u007f\xae*GASt\xd2=\xad\x8d\xf2\x8d\xd1I\xb9\xca,\xed\xaf\xa9\"\xf3\x1a\x9b\xc7G^H\x95Pu\x84e\x88\x98PC\x04n\x84\xe0A\xb7\x02\x0f\x18\t\xeaG\x99\xab\xa0W\x80f\x0fD#\xbf\x98OR~^\xf0e\xf9\xe5\xa0\xc6\xe9*\xa8\xd6\x14\\\xfe\xc0\xe5\x05\x9a\xf1\xb5NY\xa7\xf8\xd2LW|i\xa6\xaf=\xfa\x99<\xf4\xd9ѵh\v\x98ώ~<\x92h\xfd\xb5\vo\xb8\xe1Bt\x03t\x9b\xeeU\xab\xba]Ns5x\xa3O\xb9\x9a|\xfa2\xbelm\xee6h\xb8\x1e\xf1ݎ]7;\x81\xf1S\xec\xfd\xd8\xe3\x02\u007f.\xff\x83\xbai\x9c\xb5\xe3\xd5ZU\x17\xb8\x9c\x1a\\W9\xfe?\xab[\xa4\xa0ڜ\xa9\x96\x06\xdd\x06U\x15j\xff\xb7u\xd3\x13\xdf\xfdrl\xe5\xcf\xf8!\xe2.\xf6\xfd\xab\x94\f\xb9\xd2D߄I\x97\x1c\xfa\x9f\xd5D1\n\x82'\xfeG\x85W\xe5<\xb4Qf\x99\xf6\xef\xb7B\u008c\xf0\xef*1S\x01\u007f8\xc0)\x10\x10\xbeZ:!\n)QH\n\xa2\x12\xf1\x90I\u0084Z\x19u#\xbf\xfdv\xea\xd0\xfb\x87Ro\xcbo\x83\x8a\xb7\xe9\xe4\xdb 5\xea\x1a\x9c\\G\xaa\xa3zx\x11\x9c\xf2d\x12T\x80\a\x00f17e\xd7E\xf0X\x8c\xfd\xa8\xf1\\9\x97ZAm\xa0vP\x97\x92\x95\xd7{\xa8Lj\x15\x1f\xd5\t\r\a\xa8\x1e\xf1\xbct8/\x8d\xf2\xa0\xf7\x86Ҩ\x16\xc1\xd3\xe79\xe3\xf1ӥ\xd9\xfc\xb4%\x9b\x8e\xe2}\x89\xb0\x93\x8d\xb4\t\x98{\xcc\xe8_\xd2<`F\xff\xd4=\x862\x0f!\x81\x91\xee1\xa7\xb3\xe7\xc9\x06\x8c\xbd\x9b\xd9ʔ\xba\x9fۢ\xdbn\xc2\x17|\x8b\xa6\xd5\xe9\xd1o\tv&F\xd0\x04\x9bH\x8e/\xf3~\xd3_\x8e:$\x8f\xb1\xa3n\x80\xb2Q\xff\xc9\xfd$\x9f\x19ǟ\x0e%\xf1\x1f~\x10\x8d\u007f\x15\x91:\xa1\xae\xd5٩2j\x01\x96\xd62\xbeA\xbc\x85\xf0\x84\x10l\x000\xc2l\xa8Z\a3\xd1q\xd8єɢGĉ\xdbk&b\f\r\xee\xc9\a\xf7\xcfi[\xfd\xc0\xf2c\x1f\u007fu<~\xf6\xaax\xbc\xb0\xa2\xe1\x82\xc1s\x03E\xc4\xdeU\x14@}\x8bM\x05t\xfc\xefnZ4\xb901yS\xe3Z\xf9\xab\x15&\xd1l\xf6\x16\a\x16^}o\xe7\xa6_l\nEv\x1e\xb7k\x8b\x8b\x8b\xc1\xdf`\xef\x12oM\xfc\xe2\xf4\x83\x9bM\xc1\x02\xb7`\xa77\a\x1a-\x83\x02\xb1\xbf\xfd\xd3҈\x8d\xda\xdb\xd3lXd\x99m\x01\xc1\xe7)\\Ԩ\xd5HA\xf8q\xc0j+o\t\xb5ƥM\x06\xd6,Zq\xecO\xa6\xee,\xea\xc1eT-5\x99ڂ\xbfC\x8e\xb7\xc5$\xf2\x8b\xd2\xe1(\x1a*\xb5\xa89l\xa4R\x0e\x1b\xaa\x17:\x89\xeaj\xb3\xff\xffj\x16:\xf1\xc4+\xaf=\xf6\xd0\xdb\xefҟ\xfc\xedF\xab\xc4\xd6\x1bk\xa5*WE\xa0\xc2\xeepIk\x9f\xd8 Y\xcbj.8\xf6\xe0\xfeJ\xdf\r\x83\x0f\xfd\xaf\xda\n:S\xe65\xcf\xf4\x80G^М\xff\xdcF\xb9\xfe\xe9m\x95\x03\x9c\x96.䜼\xc4\xe9\x19\x86\xfeCcT\xcb\x1d\xb7@\xfe\xb9%\x9a\xe7\xcb\xc0\xe7\xff\xbb\x86\xc4kKH.!\xeb\a%\n\x1b\xe7\x88\xf5\x03\xbbud\xfc)\xec\x1ckAA\xc7T\x8a\xc2\x101\x84\xd2x\xd4\x1a7\xf6*\x8a\\\x99\x17y\x87\xfbp\xe5\xa9\xeb\xf9\xb9\xccg\xe4\xf9\r*\xc7\xe8\xf0\xe55\xbbU\x8bftL\x92\x86\x03\xe91\x84\xf5\x98ń\xeb\xc7Zm\xd3\xc1I\xf2\x95\x8c\xc3\xd0j42`\xbb\x92\x80W\x8fY\x81\xfdc\xafD1\xbe\x93_\xa1\x8b-\x8c\xc3\xc8\xea\x95D\xbaw\xec\xca\xe5|㟥l\x18S\a\xd82\xf04\xb8B\x18\xb7\x92\x00\xd6a\"\n\xc5OR\xc4\xeez#2\xd9\xd0\x13\x90(K\x10l\x14q\xbbh\\X\xde*I\x9c\xd1_\x1e-\xe44V\x8e.\x80\xe57&\u07b9kx\x1ep\xdb\xf1\a\xc1\x8b\x931\xba\x8a*{cG\xf0I\xf2\x16\x1c\t0\xa3\xf1\xa6ݻ\xeb\r\x16\xa0q\x81\x83\xf7M\x99e\x1c\x1c\x91O>Y\xf8\xf3c\x8a\xac\nO\x1d\xe3\xf6\xb0\x03\x94\x8e*Eu\xa8DmO[\x1c,\x1d\xd6\x02\x89\xe0\xb7\x06\t\xe7\x11f<\x8aa\xc2#$\x81K\xac\a0w\x03 \xdf>\xd1s\xa4\t\xb46\x1b\xc0W\xf2\x8d\vX\xbb\xc3\xe2\x90\xdb\xe46\xb4\xb1\xb3\v\xe4\x1b\xbcb%\xf8\xf7\x87֢Bۇ\xe0ߕ\"l?Y\xa7k\x06\x13\x87Z\x8a\x1f\x00\xab&\x82\xa8|\xa7l\xf0\x05\r\u007f\xff\xbb!\xe8\xc3\\I\xde8\x8f\xa9\x92\xc6\xc9\r\x9d|\x9c\xca`\xef&\x89\x8f1\x95\x03\xd5\xf7\xf91\xe0\x1bP\xb0/\xd8\v\xd3IK)\xab\xb3\xbb\xd3){@'ZY\xcahv\x8b&\x9e\xb9g\x90\n@6`\x87\twE\xa9\x0e&yI\x18\x97\xc1\xdaIJ9D\xa3I=A\xf0\xd7\x02\x9fb\x01̚\xf9|\xaa/\x85\xa2\xe8\xe6H\xa8\xe3\xa8\xf7\xe1u<\xe2\xf4R\t禓\xe8\xef\x18\x93̘*\x86\xfa\x87Y.\xe8\xb9\xffF\xfdE\xab\xfd\x9a\x18vP\xd6ߡ\xbf\x9e<\xeb\x06ݓg\xe1\xf8Z\xabE\xb9\xff=tL\xa4T\xfe\"&ǣ2=\xb7\x8e\"\x8e\xf0\x19ǾG\nGL\x11 \v`D\u074bg\xc69\x1b\x1e\xfb\x90X\xccF\xd5\x03\x00\xfbMe\xfe\xc1\xa7\xc9\xe6\xe6\xba\n8\xd0~ErnE\x1d\xd2F\xeb*\xd4Mlu|BWY\xd8Bv\x9d\xe4\x12\xe6i\xb2\x99J~{\xea\x16\x17\xc8\x1f^\x1c*/m\x9d\xe4*X\\\x87\x15wt\x88\xae˥e\x93\xab\xd8R\x10,k\x9e\xa5\x1eT\xb0\xee\x93$\x96ӈ\xb4\xf7 \x92t\x97R\xbd\xd46j\xaf\xca\x10\xac\xae<ڭ\x0e\xc5'\x96\xf8\xb8\x84\xf2\xe4E6\x1b\xa3\x10\xc6\xe0ZhP\xc0\xce\xffq;\x1a\x19\x00\x9f\x05\xcbq\x00>D\x9c\x11\xdb\xd4@\x04&\xef\x16 \xef\xd6찇\x82\xa7NQz\xa7^\xab\x05\x14~y\xfd\n\xd3\xd2@^,,\v\x15\b\x1c\xf9Q\x9b\xed\v`q\xcfq__X(\u007f.\x06l\xa0{^\xfa\xa6/\xe4/T8\x1d \xa2c\xf2#*b\x0e\x98i\x83\xd7\xe4\xdd&\xfdO\xe5\xd6\xe0\xa6a\x0f\x04\xdaS\x14\xe9\t\x80l\"y\xe1\xb8\x03$\u007f\xff\x05\x18&\a̲\x05D\xf9s7P\xc0u\x80\xf4\x85\r=j\x01\\.\x02Q\x05ܑ?\xff҆\x8a\xb4\xe0|r\x81\xfc\x13\xdbz\x854\x8aʻ\xe5}\xc3\x1e\x86ǃ\x1e\xf4\x91\f\x91u\xcdfůs\x98\xe5\x1b\x8ffB\xfeQ\xe2\xe8\xae\xc2B\x93\xb9\x14\xc4E\x1fv^M9\x914\xe3$?\xa0\xb98<\xa5\"<.\x8e\xf6L\xb6\xbd3\x9bj\x97\xb5L(\x0fL5\x8a\x06\xe3\xbdFV\xd3\x0f\xc6w\u07fdw\x0epf.p©\xb1\xe5M\xcdn\xbbc^\x81\xa58(Uν>\xe0n\xac.K\x14\x15\x9ce\xd6\xec\xd6y\x8c@\xd7\xda{SF׆\xf8{\xf6`\x1e\xad|\xe4\v\x85\xa673\x91\xd9\xf07K\x8f\x9cݒ\xca\x1apȕHd\xa8\xb0Q\"\xa9p\xd1(@dY\xd8\v\x90T\rc\xe9T\x88YK\fKJ\xe0+\xa4V\xa2\x1fO\x96wd\xc4C$Zѧ\xc3tH\x8d\xe1ο\xbd\xa7\x10\x84\xf1n\x18\x14\x82 \xb6\xcc\x06\x81w\x00\x9f\xc4?\f\x97&\x19i\x02\x88\x86G,\x8a\x95\xd9\r蛙\x86\xeb\x1a\xc0\xd1\xfd\x84\xe2\xd0\x04|шD\a\xa2>\x02y\x10\x89\xb5A\x9f-@K\xc0\xe6#\xee\xc4L\xe6\x1d\x85\x15\x0e\x1b\x12\xa9\x13\x89җ|sĩ\xa1i@3@g\xbaM\x96\x93/<\xb3\x1fX\xaf\x846t\x90\xd6\x14\\\x05\xc0\xee\xa7_\x85\x9f\xa6e\x9a\xa9\x9by\xd6̺\xa6q\x91*\xc1\xbe\xde\x15\x9c\xbb\xfe\xbc+j\xa6/\xea\x8a\xd3\u007f\xbd\xff\xfe\xa12\xad\x81\xe6\xb5\xd0\xea\xe7\xbc+&\xadZ=\x8d9s\xd5\xde{\xdd]\tF\xd7l\xe2\xfa\xf6Ǝp7\xa9\x17@\xba\xd7Ŭ\x827G\x05\xb1\x0f\xbb\x1d/Ð\x1e\x11\"\xf3\x18^9M\x82\xee4%?\xc2}e\xd2\x17\f%C\x8di*\xd4fFi\x1a\xa5i\x94&8{L\xd4?\xbdp\x88\xaa\x18\xe7G[\x06m\x95\xf5\xbe\xf7\xc9Xګ`d\x11\xf4l\x8c'k\xf3\xf3\x98\x14&\x14\xad\xcb\xc5\x1ecb\x1f5n\xa0\x1a\xf8\xc3\xfe\xa8\x05cd`A\x17\a0g\x02\x96\t-\x12\xa6\x8a\xb1\xe1\xe6\xc7X\x1b\n\x01\x10R\x10\x16\xcf\x1a\xd7Y\xd9\x11<\xcf\v\xecz\xffŽU-\xf3\x02\xe3\x02\xe7̞w\xbe'\xe8\xa9\nv\xaf8\xac\rj\x8d\x00BX\x1c\xa4\x0f\xaf\xe8\x0eV\xa1\xe3\xe7\xcf\xef>\a\xe5\x9aג\xf8k5`Y\xe0\fTT\xda\x1bj\xba\xcb\xe7,\x01O\xceƧ.\n\xdf\x1cf\x91ء\x8b6\x04;*;\xc7\xcdZ\xbcdNywM\x83\xbd\xb2\"\xe0\x84\f\x84\x000ԈKՒ4D=#\x9e\xa6\xcaeL\x92p\xd9E\xc8\xf7H\xf16_\x86-\x9d8\xa0\x87(\xfcu\x92\x95wʫ\xa6\xf1\x94\xe0%S\x82\xd7\xce$\xe5\xf7\xde#0\x84\xeaz\x03\xa0ޓ\xdf\xc3\xcb\a\x04d\x11%NQ\xc7\xe5o\x8ec\xff[:\x91\xfc@~ƹOq\xae\xdc\xe7\x04S>P\x86\f\x05\xbf\x91\xa0䬕\xa9}Ǐ\xef\x83\xf8\x17{\xd7\"\xb9f+\xf1wm\xc73;\xbaa\xb68Z\xa0x\xd1\xf3\xa8\xd1\xf3\n9\xaa\x02a>\x1f\xf3\xc0n\r\x02\x05\x04\x1d\x98\xd6\xe0\x10\rf\xbd|\xd3\xf1}\xf1X\xcf\xd9\xe7\xbbϓѸ?G\xa7c\xde\"[yg\xfa\xfa\xe3\xfb\xd6\xde\ag\xadY\xb7Q\xa9@\x14z䛒\xfb\x8eK=\x11\xb5\"\xaeaU5v\xc8:t\xa5\v\xdf\x02o\xd1\x1dp\r\xcf\xcf\xfaI+\xbf\x9c\xe3'\x9d\xe7\x04\x8a\t/N\x12\xb6\xc5\xe4\xf2\x89\x98AO٠#HzK\x01/\x01\xd1 \xf2]^z\xe6 1Q\xb18\x92\x880\xe7)\xbf]\xa4\xddh\"\xf3\x0e \xb9\xaf+\xe7_\x1eTa\x1d\x83U8\xd4i\xb8cm<\x8a\x91\a\xd4\xcf\x1aǥe\x1d\xa4}\xe8d\x90\xc0\xc5@ų\x9c\xfe\xa1Ac`h9\xa1\x17NQ\x1b\xafS&\xbfݫ\xbcM\x9b\xa6\xb4X\x19K\xa9\xd9\xe8\xb0\x18X\xa9~\xc2\xfa\xfa\x82\xe5\xfb\x96\v\xa0JЃ\x14͠\xabX\xe5\x9d\xf7\xc8)\xb3\x96\a=Pԯu<\xb2u\x88LU\xb4\xb7\xefA\xcf\xc6\xea\xa6i>M\x807\xd4:u\xde\xe9\x13&\x89e\x15\xb8V\xbeb\xbd\b{\x00\xaf\xc5u+9\xe5\xe5\x14\xbbde\xaen\xc0\x8a\xa5W\x1a\xb3\xf0\x11\x04\x1f\xa4jdS\xb8\xfc\xf1X\t6>\xf5\x13A\x158ozt\xf6\x16+\x14\xe4$\xaf5\xe8\x13Fv\xbe\xfc_\xf2\xdfiN\xd0&,\x86\x01\x9d\x19\xec\xea\xe9>\x0e\xe6\x01V\xb02\x8a\xc4\n\x92\xdf\xca7>\xd6\xdd#_f\xd6\r0Z\xfcҬ\xa0`>\xd0&$+H\nкe\xf6\xb3\xd7H\x19\xff!\ue122o\x00ڇ\xb9\x92\xca\xf1և\xfeh\x1f\xc1\xb7\xe6N\xdc+?\xfa\xa8\xb1\xd0]\xff\xe0\xab\xf2\xa3\xaf\xca\u007f¿\xb70Ck~\xd2\xd4\\\x06\a\xd3,\x9d\xa8\xf7\xfa\x86\xa6\xd0\xcf\xe0?0evg\xe7φ\xfb\xc1\xe0\x01\x87\n\xc6cuH\xc3\xca`\xd5s$\x1a%\xdf\xd4C_\xbdV\x92\xe4\xd7@D\x92\xd6b\x8d\xaeQ\x92\xc0\x8bR\x1d\xfc\xc1\x88Uͫ\xf1Y\x10A\xf9\xea$|E\xa3\x92\x19\xbe{Z|u\xe5\xf9\xe8\xd1a\x15\x90ޡU\xc1\xdf\xf3\x9f\x0f_C\x8fSn\x87n\v\"\xf2k\xa4 \xf4\xe4\x91\xcfǥ\xc2ES\x8a\xf9\x1aʇ\xaf8\xd3\xf3A<\x96\x89vQ \xf0\xb5#\x9e\xcf\\\x9dW\x1b)WI0\xb2\x01\x80\xd2\x02#\v\vF\x16`\x8cw\x90i~m\xa6!F\xbe\x83\xcaQ\xf5R^\xc2ȥ\xe5\xcfH#\x8c|ap\xc7\x18m\x90 \xb1#\x16\xd2\xc3\xe2\xa8gaH\x9a\x80\xc4F\xa2A\xc9\x17\x06>\x9a\r2}桫\xaa\xe1j\xfb\v\xcf\x1b\x1f\xb6\x83>\x06\xac\xabM_d\x92\xeb\xd9d2\xfd\xd3\xf4/\xe8\xa3\x0f\xa7?\xfd(\x1a\xbdJ\xfet5X\x05\xbdO\x80wN\xae\xbc\xfbn\xd2\u007f\r\xa7\x12\xdc\u007f\xab\x18r>-\x94|<\x8b\xee+\xf9\xe2> \xb1\x1f\xca\xff\x1ez?=y\n\x18W\x04~\b>\xee\x18\x9c\xda\xc8<\x13\x1a\x9c\x8a\x86\xb7W䯀\x1e\xac\xbe\xfe\xae\xbb\xc0\\0\xeegj[\x99y\x85\xb3c~\u07b7\xaa\x8cCՀC\xad\x14\x1e\x85C\xeb\x01\x8e<\xb59O\x01\xb5E2VnK+\x88g\xc0j\xe9\x942*\xad\xb5j\x18\x83~\xd9\x0ey\xb3\\'oޱL+0\x1a+\x1a1{\xec\x1a\x8diu\xfbW7*\xc2v\xe3\xe4\xc3o\x1f\x9eܨ\xec\xdc\xf8U\xfbj\x93Fc\a=\x82\xc8|LƦ\xa1~\xb9߮\x81\xdae\xd7\xde\u007f\xff\xb5˴P9i\x95̫\x97\xec\xb6\xc2ˉ\xf4~\x8f\u007f\xfbd\xec\r9y\xbb\xff\x1er }\xa1u\xf7\x92\xd5f\xc9**\xdf?\x91\x1b\x02\xa38\xb6\xb0?'a\"U\x91\x04\b[/\xe3͑zyU\xc9@\xa5\xfbʙ\xc4\b\x16p\x82\xf0y=\x83K\x8e\x9f.\xa7\x86۳\x14\x1d\x9fH+9\xa4ې\x973۽\x94\x99R\xffNg\x13Q l\x81]\x8d}\x02g+D\xa5d\xf9\xff\xa13\x18E\xe0\xa7\nd\xed٠\xf5C|=\x9c\x97\xbd\xb4\"\xbd猖\x1d\xb2\x9e\x82D\xf7$\x9d\xc1\xd3\x1a\xa51\x8e\xf4\x9d\x1e\xe5K\x9d\xac/%\xed\x94\xc2\x1e\xa0c\xa7io&5\xe6O\xd6\xe7\x05\xe4p\xbdF\x95\xc3r\x86\xfd\xfcr\x8c\xf5\x03re\x00\xbf\x1d+\x99\xcf9\xcdSn*\x8a\xad\xaeY\xdf\x17L\xb4I\xecD\x84#\x01\x10\xd9#\x04\xab@\tfq \xc7패\x9c\x18\xcd\xd0\b\x15\x97a\xf0#\xa3\xfc\xcc'\x82\xd5b\xbc\xf5}=\x10\x8dI\xa3\x15\\̮\xfd\xc9'\xf2\x87\xb7\nZ\x9dh|\x15,=\xc1\x93\x13:=(\xce\xf7\x8cT\"\xfa\xfd\x9f\x80)F`E\xe7E\xa0\u007f\xffV\xa3\xc5j\xbc\x15\x14\u007f\xf2\x93\xb5,\xd0\xe9\xc8Q\xfe\x84|\xef\xabFQ\xa7\xa5_\x1b\xe9/\x99\xb3\xe1a\x9c\x93|\x06\f2\x94\x13r\x1e\xa2K\x8cbIx\x14\xbbX\x15\xfb\xbc^\xb3\xd9b\x1a\x85\x9c\x9f\xbeI\x9c&\x82\x84$J\xc1t2(i\xb4\xe8]\xc6NE\xb9Wؗ\x89,\x87ޥ\x96\xcd\xcd\x16x\x90V\x96\x84c\xa8m\xf9pF\x02&+a\x0e\xbb\x15)\n\xcd\xe9\xe7\xe5\xe7\xc1z؇\x06d\xcc=\x92>\x8c\xc6\xed>1F_9\xb4=\xb8!\xb8\xa7~S\u007f\xfd\xee`\x90\xbe\x12\xed\xec\xc6;{\x82L\xb3\xfc|\x1ac\xad\xe2\xab\xeapn|U\x1d\xbe\x1e^;\xb4-\x88.\xea߄\xf2m\b\xd2\a\x82\xe8\"\xb4\xb3;\xb8aX\xbb(\xba\xffȐ\xe51|Y\x15\x87Yz\x94_-\xf1^U\x96\x18\x86{\xab\xe6\xf8\xf7\xf2\xfa\xf6\xb0\x15\x863\xf8u\xe1\x05\xca!\xb2\xe6C+Hn9\x87\xaed>\xef)\x1cȮ\xd7˵\x84\x16U\xc9I\xefͧ@E\xe3$*\x11}\x92\xbd\x98*\xc4~\xd6\xe5 \aV\x8e\xbd\xc1\x039\xfa_\xfa\xa4X\x9a\xc2AW6\x8d\xc6Я5\x83D\xaaT\xb4\xb8@BlE\xaf\xdcM\xdf\x17\xc4+\xa6\xa2Ք\xd2\xc3d0X\f\x92v\xbb\x9c\xf4\x92\xb9\f\xc9\xc1\xe8\x19\x14\xeemRf\xfdFu%\xc4T\x82\x16\x1f\x91\x10c^\xec\xfe\x95*-q\xcb)tS9岠G\xca)A\xdfo\xd4jYJ\x12\x86\xee\x9a\xe6\x95\xd1}A\xb28\x14\x84I}J\xb0J\xc3e\x81\x92\xd2r(\x9f\xc4Z`Y~Ir\xe5\b\xe2Ximf\xd0)\x02~\x81U\x96(\xe2\xb10\xc4$\xc6\xca\xde(\x84\xb2\xcf@\x0fz)\xfd\x9ep\xe9\x8e_\\zv\xbdOw\xbf^\xe09;]\xd1W\xf5\xc0U\xa5\x06\x83\v\x86\x865\xd7c(?\x1a\tz\xb0\xb9\xa4?ܶ\xa2g\xe7\x9a\xe6'\xfeh\xa0\xb5N\xb0rG]u\u007f\x99\x85\x85\xa9a\x8d\x95\x1b\xff!z\xb3\"\xe5!\xf6\x14`\x01\x164y\x03\xd5\xf3p\x18\r\x15\x0e\xe4\xc0A72E{\xf3\\\fG9 \x82T2\tf\xa5\xfft\x8aB\x1a\xf9\a\xc4IQ\xc9\rW\x8c\x98\x92sxn\x18\xf1\xaaR\xc5\xebP>\x1a\xd4\f#G\x8a\x91\xad\xc4\\(:\xe4\x944Q\x92S\x0e\xd1R\n\x93\xa57\xab~\x9eF\xec\xf39\xfc\xcd\xd1\xcb\x02\xc5r\xc2\xed\x06\xa9\xe2@ \xed\x1d\xe6\x14:b\xfc\x1aQ&e\xb8P\a\x893\x97\xc9R\x9aN\x96ZD\a\x9a%&J \xe1\xd8~\xfa2\x81{\x02\x81@1H\xb9\xddr\xa2X\xfe\xdd\xf7/\x13\xf1SV\xec\xbf1\a8c\x99\x12\xf8\xfe\x01\xe5Y\xbfϷ\x85\x8e\xe8\xdcw\xe55\xa5\x05\xb7m\xfa\xef4\x19\x89\xc9\x15\xf4\xeb\xc3y\x8e\xb1 \xf3/T\xa6\x1e4\"9\xec\x9c\t\b|\xc0O\x85\xb3\"u(\x9eM\xc6(\xc2֍\x84nb.e1\b\x88\"\x84\xa3\x82r\x0e%\x89\x17\x9e\t\xc6\x14ӆ\x8d\x8d\xf4\x9b\x01ڠg\x19\xa3\xe4t\xa3\x17 }*\xdfݶ\x027\xd0DH\xb7\xe3B\xadl\ag\x0f\xac]\xaa\xd7rt9m72\x8c\xc9Z\xe0.\x16\xf6\xbcT\v\xde6ku\xb4\x93u\xcbN\x9a\x06\xaf\x98\x90\x84\xe0\x84\xa2^\xde=\xfe\x95\x8bŒ\xe2B\x9b\x99a\x8dF\xc3_\x8e\x18l\x98\xa6\x85cY\x96\x81\x80\xfd@2n6J\r\xe3Ea\x8b \xbe\x05(\az\xbe\xf1\b6\xcf\x02\x9a\xa1i\x98\xdcd0\b[\\\xc1\x0e\x83\xc1\xb4Ioھ\x9ffЅ\x00\xb2<\xaf\xea\xe3\xf4\x10j\x8f\xb6\x9cW\xed\xf0\x95}\x05\xe5\x05\x1b\x02q\xf8\x16G\xa8\xb09\xd5aM\x81\\WWr\xe8!\xd4\xe4\x1d\x82(\x19\xcf^\x81k\xba\xe2\xeb\x9f=s\x18\xa9\b\xeb\xb4F\xa3\x8e-멜\xdf\vjH \xd9\x1b\xe0NQ\xb8\x1b\xbd\xc8k\xe5\xebp\xceè\x8b],\x19/\x15\xc4?\x1e\xfd\xc3nM\x81\xeeb=\x80Z\xb6\xb0dy\u05fb\xa2p\xa9Q\x92/{B\x015\x06T\xdd)\x8a~\v\xe9\x0f+\x15\x9e\xf5\xac\x88\x89\xbd\x18\xdb0\xf0\x93c\xbc\x02ы\xd7[\xe9p\x95\x06\x1b\xea\xb2kM\x98\xa5[\xad\x86J%\x89\xa1\x85\xe8\xb7~uD\x14.7J\x13wuw\x14\xb0\x16\xd3:\xdel\xd2\xc2\xcd{\x83\xc1ٻ<\xc1\xee\xbaX\xb8rf\xf5\xc4qU\x05\x96\xe7\uf40c\x97\vbÆ\xf6f\x91\xb3\x18fkL\x82\x91v\xc4[\x17\x96\xad\xb8\xc0R\x16\x9c^U\x1d\xad\xef\x89O\n\xba\xc0\x8a[>p=\x8c[\xe3amEeĉ\x9eu\xb9\x0eB=\\\xe5\xd2,\x98UX\xeb\x1f簙ŀ\xbbb\\CӴq\a\xde\xf4<\x8ea\xa2\x1f\xe1\xfc\xbe23'Z\x0f\x99\x00\xad\xa3\xc5@\x91cA\x87\xab\"\xec\x0eH\xa2\xd5Q\x1dj\x9d\xb0H}g{\xd1;k\xcd\xc8\xe0\x02\xe0\xed*Sp\x98\ng\x9d\x87\xe3Y\x01&\x94\x91\xc33\xa1\xe0\xe5\xc0\xee\xc0֚\xbd\xa2\xf0\x80\xe3\xed\x1f\xdd\x0fJ\x04\x9d\xc6\xf6K\xb3V~\x1dc}l\xdaw\x97]\x9eO\xd6\xd4\xeeh\xf8\xcf\xebp\xd1h\xf2\xfd}Rm9\x8a\xb4\xc1\xb2\xb5\x82x\xf0q\xeb\xa3\xf2\xadfQ4\x80\x8d\xafj\x8d\x17\x1b\xa5\x05sD\x01\x9d\xd8,\x19/\xc3yQ\xb2e\xaeH@\r\x91\xa8\x81ʋ\xa4u_@\x05\xf2WaJ\xb2\xddM\x119j1\xc22R_%\x92F\xe3j$\xd3\xcdl\xb9\x0eg\xe5\xe0\x92\x87P\xa7 1\x8a\xc0\xabl\u007f#\xffL\xa3щ\xbf\x90t\xefJA\xdd8\xfeg\x1a\xdb\xcf,:\xadF\xfeջ\xa4\xcf\xfd\x01\xf8\x95-\xaa\n\x98&\n\xeb\x8c\xd2|Q\xe85Jp\xa2\xd9l\x16兡\x85\xceE\x16p\xafd\x16,\xe9\xe7$c\xaf Η\x8c\xeb\x04Q~\xd2(\xa9\xbc\xf7\x8a\xdeQOtu\xdc\xf11WJ~ɲ\x9d1\xf7\xe9dSʨ\xc6H{\xfbpTW\x1fؘ~I~\b|K\x16,y\xc9x\u007f\xc6D\x9d\xb1[C\xf7K\xf4\xba\x97.\x92\x13\xe0.y\xcf\u007f\x9f?ґ\r\x1d\xb8\x11\x95}\xbb \xe6\xf1\x0fi(\x03\x92v\n\xd0h{\x1e\xea\x19R@\xb2[\x1du1)\xees\xf8\"\xe1\x00>\x80\x94 倢#Ҥ\xc7\xd0\x01Za\x92\xa6\xb3\xa5͍\x87t\xe6\xbd\xf8\xa4a[;Og\x17\x1cxl\xab\x87\xb3\x8fL\a\x00l\v\xc8\xef{\xc1]W\x06&\x83#3\uf78d\x8el\xf4\xc9\xef\x12\xfc\xeew\xee\xe5\x9dG\x9c\xfc\x0fO\u070f\xb6z\v\xec\u007f\x13\xd7\xe7a\xdf5xs\xeebV\xa73\xefw\xb1g\x81ug\xf3\xce=N~%8w\x19\xeb\xdao\xd6\xe9\xd8%\x1bq\x96\xeb\xfc\x8f\xa11c>(G\xea3\x83\x19\xbe\x1eJ&\x93i\xa4J\xcb\xef\xa0\x1dt\xe8X2\xe9E\xbd4}\xb3\xd3\t{ѯ\xa0\x83\xbdD\xd6VV\x96\xc1\"\x93\xd1\xe0\x94o\x06\xbdN\xe5\xd7`4\xc9\x0f\xa8\x19\xb0~[\u007f\x8ab\xfe\x8a\xda1BM%\x98CvL|\"0\xbc-\x10\xf5\x87m\x01\x8b\x1f}Fq$\x05Y\"\xa1\x80\x05;(:j\xe3ш-\x86\x81P=4]W\xc5\xf8\t\bim+\x87w\xd0ԀvZ9\xe6Z\xf1\xc6\xedی|d涋\xe7\xdc\xda]v\xab8Uz\xa9xc\xad\xc6\xcc\xe9\x8c]\x1b\xdfN\xf8n\x9dSz묝\xbd-'<\x15S\x9a\x17\xd5\xce\xd2h\x1aC\x1d5\x13\xaaj<Ҕ\x82\x92\xe6\xda\xce\xf2\t<\xdb\xe4\x9fX\xd1\x14*\x11\xe9\xe4\x93]\x85\x87\xaf\x9cr\xce\xe4j;sj\x10\fQ\xa7\xc0S\x11p\b\x80\xe2\x8e{\x01\x18\xfa\x1a~5\xc4\x177\x9d\x9d\xbe\xa3\xa4\xbe\xa4\xc0\xc0A\xf9ǀf\rf\x97\xbf\n|\xe3\x8b\xf8\x1c:\x0e\x00\xf954=h\x04Gq\x95\x82\x8bA\xb0%\xd4xIl\xe4w\xb0J\xcc`ޔ\xccPv\x01\xdc,\b\xe9\a\xeaK\xa17\v\x11\xe1E\xea\xe0o\x05A\xee\x15\xec\xde\xd2\xfa\xc1\x81\f\xe2\x83\xc2瑽o)\xfan\xa6\xe26u\xf8,\x18T~x\x8c\xb6\xd5.\x9d\x01\xa6{\xe4>{\x1c=\xb3\xd4.t\xe4\x17\xa5\xfe\xa5\xb1\xa0(F\xa6\x99\x12\xc1\x8e\x8b\x9c~>WZ\x8cY\x95\xf6fu3 \x8c\x95\xc4\xf2\xa7\x1f\xd5i7\x87Q\xceK\xa8\x89\xd4\x1cT\xa3\b\xa6\x06\n\xf0h2\x02\n\x0eSF}R&\x1d\xa2U\xb1\x98\xe8*\xd6\x060\x85\x01\xf6\x82\xc1,\x06\x00\t\x1f6\x9c1*a\x86\x82p\x80\x8f\xe0\xad\x14\x91\x98\xfb\u007f2Հ\xa9\xf0\x98\xf4\x97:\xf9\xe7:\xa3A/\xa7\xf0J\\\x8a\xf8\xb2`\xb7\x97\x8e\xf4\xd3`\xb3A\x8bI\xd3\f\xe2_/\x80q\xf9ZΤ\x17\xb4\xb6oޒ\a\xa6W\xff\xabz\xba\xfc\xe1\xe4\x8f\xef\xfe\x98\xe9\xfd]\xb5\x99\xb1\x02\xbfaГ\x01\x812KV\x96@o\x9c\xec\x17/\xfb\xe4,h\x11\xb5Z\x1a\xd0[\xff\xb28\xfd\xb9F\xd4C\bwЗ\xf4\xf5\x1d<\xd8\xd7\a\x0f\xa7\xfb\x14\xdbO~\xbd\xebp\xbd\x83\xb9z\xb3\xa7\xad7\x18Q3\xfa;\xdb\xe1{\xd4\xfb\x8ea\xb5\x93N\xdb\n\xd9j\xffi\xacZ\xcbC\xb9\xea1\x17\x8fj\x02\x1d\x92\xbfv\xa0\xfe\xebWqӰ^\xd6@ub\f\xb9\xe0w\xbc\xe2\xe1+\x06#\x1d!δ\x0f\aƮ2\xe3\xcd_Y\xc0\xaa~\x92t\xe4$ّI\xe7\x04)\xb2s\x8a\";\xe8\xb7g\xacZ\xe7A\xbf\xff\xf3\fIe\xba\xcb\xd4ߔ\xab\xff\xc8Z\x9e\xbe=F\xad\xa0\x9ca\x9f\x19V\x01\xd9;vk\xc0\xfe\x11u\x1e\xd6\x1a\xb9v\xf2f\xab\xb2e\xac\xa6\x00[\xce\xdc\x00\xa4ϳ\xaf\xab}\xbe\x1d{\x04\a\x89\x91\x9fX\xeeO\xdf\xe7\x83V\f\xed\x1d\x0e\x85\xe3\x8a\x1c\x1a\x0f`^B5\xea\t\u007f\x00\x18\xc0\x00\xc9\b\xd8\xed\x02\xf3\x91\xb0\x13\x175յvv\xd4NN\xdfy\x9aJ\u007f\xee\xaa\xef\xde>\xa9\xb5\xca)\x86M\xe6`h\xde\x1a3\xb4ͮ\xe8\xfb\xc1\xc1sw\xdd\xeb\x91\xcb\xef\a\x90\u05c8\xadsR\xbb\xfe\xd8\xd67mKWl\xc1Xu\x8e\xb7\xee8wN\x8dY\xc3o\xe6\x19\xe3\xf6\x85\x8e\xc2k\u05ec?\xf4\x1c\xac\u07b2\x05<\xc2;Y\xb3\xc1(6.x&\xbd\x85\x1aU\xf78\xf1\x86\xce\xd5\xfd\xbbǹ\x11Փ\xbe\xab9\xbeG\xdd\xdf̯\xdf/\xbf\xa3!\x18\xb5\xf2\x83?\x1a\xab\xf6C#\xab\xc9F\xc6l\x8f\fndB]\x87]\x9ay\xeb\x8a\xc3\xc6\xc8u?\x16\xa3\f\xday;\xe1\x12\xe3x\x8c\xcd\f\bm/1\x1b\x13HB\f\xc7\n\x15D_\x9b\x15\x93\x82A\x1e//Q!\x97;\x18t\xbbB\xfd!\x97Ll\xbc\xc0\xeb\n1\xfdq\x13]e\xb1\x98\xc2\xda\xc6\xc4e%]\x96\x89\xb7/\x9c\xb1+\xe0\n\x95\x148{k:|\xa2K\xab\xe5\xf5\x85V\xc9U\xd5Y\xed3i\x81$\x89\xb4\xa0a\x80m\xe6\x16b\xb5A\xf7\x84\xeel\x00\a\xfa]\xd0V\xe1\xedj\xa9oi\bn\x9a\xd4\x05\x8bݮr\x00\x82.xIA\x10\xc2-\x89\x85>\xb19X\x16\xaeh\xb6J\xb6\xe2\xda\xd2f\x8f3\xd4U\xe1\xe7\x9cVa\x8b\xba\xe6\x8f\xc6\xfd\x04\x891s\xab8\x8cٗ7R\x83\x0f\xdamD\x1b\x86\x0e\xec\x04C\xe0\x8c1\xf9/Th\x8c\xd5&\xc1\xed\xd1Dc\x0e5\xf2\xc7[O\xd7\x10\xeb\xe3`\xf3L\xf9o\x8cF\xa0E\xd1\n\xb4&_ug\x95K\xb2\x16\xeay\xad\xd6%\xfa:jz\x9d\x05%!W`\u05cc\x85\xb7O\xb4t\x95\\\x96hԆM\x16K\x15MgZ\"\xfd\x17\xa5\rH{<ܲh\xe6\x16\xc1\xea䂥3BNOsim\xb1M\xb26W\x84˂͢oab\v\x84\xc1\x02x\x89+\b@\xb9\xcb]\f\xbb&m\n6\xa0\x86\xeb\xf2b\x14\xfa\xccZ\x86\x96ؑʩ\x16\xd4\x1a\xab\xa9\x8b\xa9\xab\xa8;\xa9G\xa9_\x10^\x13\xec\x19\x8fW\xc9\"\x18Z-\x88\x04F\xf4\u007f\x94E\u007f\xaa\x11/\xa2.\xdf[X\xd5G\be\xc1\xe2#^e\xb0Y3,1h@$N\xb0E `\xb3\xa2\xdcu\xb1:\xcci\x84\x834jA\x1d\xa1\xa5\xf3y\t:\xa9\n~\xe9%\xfd\f\x89\xf7|8@\xc00m\x11LtJ<\xb6\x90\xb8\xa4,\xdca \x0e\x8bZ\x8e\x80Z\x8eQ\vx7\x15Y\xccfK\xd1\xd3\x13'\xa6_\xe8\x9e6\x13\xfc\xa4=\x1c\xf4i\xb9\x89\x00\bV;h\xe3\r\xe3\x02\xbe\xf6vo\xc98\x03?\bi\x83;ZWd\xb3\x16\xadu\xdb.\xf3;9 _\x92H@\x9b\xa4\x9bX~\x85\xfcw\xf9\xb3+*&\xe8\xacV݄\xf2\xfd0\xb4\xbf\x1c\xa5\xd3Ƴ\xa6G\xa23y\xaf&\xa0\x9f\x06|\xb6\xa2\x9a\x88\xdbfsGj\x8alO\xb4\xb7\x138\xebvN\x8f\xee\x0e\xbe\xce_\xe0\xf9\xe4\x8eZ\xf3\x80\xf9\xa8?\x12\xf9\xebdy1\xb8\u007f\xf2\x1e\xf9\xba\xd2\xcaBK\x10\xf8\xe5\u007f:\xa1\xa9\x1887\x1e\xaa\xb3\x95\x8d+\x01\x9f\xddUZf{R[$\xd8\xc5Ґ\xbb\xe9\x92&w(T\xd4\xd05!\xe2\x02\x06\x9b\x9e\xae\xbf=\x12\xb9\xbd.M\xffdnE\x13k2\xb1M\x15\v\x8f=2\xaf\xbc\x19\xa7\x9b\xcb\xe7\xd1M\xa0\xf4\x97\xbft,u\xac\x8b\xff\xfa\x82\xbd\x8dE\xe8\xdaF\xb2q7\x83-\xf2_\x8a\xcd\xd0\t\xcc\xf2\uf0e2\xbb\x12h\x86\xaf\u18af\x03\x8d\x97\u007f!\xf1\xb2\x99\xfe\xb1\x84ZE\xed\xa6\xf6S\xb7Q\x0f\x13=\x1d\xa3\x14\xa2w\xcd\"\xa1\xa7\xae6\x18\xc1x\xba\x96\x88o\x8cגyyQ\xd4;\xa2\xe4\xe5\x05\xa3\x01\xd2aZ@dԋ\x8dc\x86\x1b?ڭ%\f\xb8<\xe7%]\x04C\x86\xa3^\xe1%=\x04Dhtw\f\x9e\x1c\x912}O\xe9g\xb8\xef\x05\xc7\xe8\xa1\xf4+a\x87\xdd\xee\b\x839g\x9d5ԸA~i\xfdj\xe0]\xbc\xd8\xe3\x16i\xb0Xc\xa8\x1a\x1f\x03Ǵ\x96Xm\xf9\xe2ŕ\xe3c\x16-\x98\xb3\x04\rkU\x8f\xb9\xc3\xed\x1d\xe1¢\xf0\xa4\xa9HQ\x81\xe9\xfe\x05\v\xe0\x1b.aQ\xe3\xd3i\xd7Ӎ\x8b\x8d.\x94nz\n~L\xd2C\xae\xb5\x17\xae\x16\xaa\x83\x85}S\xc0\x93\x85\xa1\x8e\xf6Paa\xa8\xbd#T\bf-\x89\xd6V\x195K\x00-\xba=\xa0\xe4?\xdb\xed\xa0\xd2\xdeQU\xd5qx\xf9\xf2\xf4\xaf\xc0\xe7\xf2\x0f\xcal\xb4\x17\x9c#_X\xe3\f\xb6,\u007f\xa1\xd3U\x1f{/\xbd~|<\xee\x9ek\x8c\xe8J&-\\7+\x18\x89\x04g\x1dC\x9b\xa8ۭ\xa5\u007f\xf1֤IoMN/\xfct[S7g\xb3q\xddM\x9b>\xc7i\xdej\xe5Q\x9a\x11\xe4\xcd\xf2?\x80iځu\xf3\xe4o'?<\x1b]\x1d\xea~\xb8\x1b\xdfd\x8el\x8c\xb7\x06\x9d\x11p@\xbe\xce\a\xed\xe5`\xb7\xe2K\x89ys\xffMI8\xfa\x1fp\x8a\x06\x1d\x97j\xc3\x19\x85\x19\xaf\n\xdb2\x8b2 \x06\xf0A8_\xf7\xb5;\xf4\x85ͪK\x03p\x97A\xafu|Q\xea\xa2_\xd6\xeb\xd3_\x82n\xbdNg\xff\xa2\xcc)\x1f\x13!(\b\xff\xc3N\xaf\x11\xe5iU~\xcc[\x80^\xa1\xc9T\tV\x9bmCg\x81\xf4-V\x8b\xa9\x12\x9e祯\xa9̌\xd1\xca\xd8$e\xf9E\xf0z\x0f\xb6 \xd8h\u0381\xbd\xb0\xe2\x80\x1c\x01v@\xf6ba\x80\xc4p\xc7(\xe3\xcb\x1e[\xf1Ӣ\x86\xd7\xec~^\xab\u0558\x9f)\x96\xe88oy\xd6#\xc9k\x90\xbam\xf5>-\xf2\x1a\xad<\x04n\xd1\xfc~\xd8\"5\r>\xf0\xeb\r\x96\xdf\x02\xf9\x87\x82`,\xa1g\x1b\x02\xe90\x94}\x01\xa4`\x83\xf7\x01\xfcO\xf3\x15\xa31k(\x1dO1\xffF\xa9N\xb2\x86/\xd52\xc5\x00\x83\xde+l\xf6E\x00Ss\x9a\x80\x80\xf4\x04_\xa8\xa4\x1a*3\t\xea\xd9- D\xf8\xe6[\xb9H\f\xfe\n|$\x17>\xf3\x00h\xe8\xec\x04^\xc1\xe7\xf4z\x04N\n\xa3R\x02 \xf1%\x82 x\xbcN\x1f\x1a!\x06\xe5+ސ\xdf\x18_SR\x12\x9c\xe0\x1c\x9dC\xf0\x82Ap\xf3\xc94X\xa7e\x19\x9a\xe6tf\x87\x89+X\x1aO\\7\xae\xf4\x8a뮋/F\x13\xb2ä\xe3hZ\xc2,\xd5\f\xab\xf3\x16\x8c:o\xc6\xe7EJ\xc1\xc1\xe2R\xec\x01b[\xc5\f\xc8\xc5hX`l\xc0\x16\xe6\xa3 \xea@\xff\xe26\xad\x01)\xec\x9f\xcb?\x92\xedl\x85lG\xfa\xb8\xe3z\xb0\x00\x00\xb00=\x1b,\x90E\xf9\xc7l\x15\x98#;\xe4\a\xc1B\xf0\x89\xfccY\xa4[\xe47\xe4?\x836\xf9\xa3s\xe4\xdf\x13>\xf6\xe09=\xa0\x10\xb3\xa5\xc9\x1f1\xbf\x95\xff,\xbf\t\x04\xf9\x9f\xf2?䟃\"z\x8f\xfcs\xf9\x9f`<\x12\xde\xf5h\\\xfa\x8a\xf8\x98\xe8\xd1Ȥ\x94\a\xe3?\a,\xe8/\x18gyLI\x8a\xffh\xc0k\xb1\xe7\x1b\xab\x1d\xbc\xbb\x9f\xbd\xb3\u007fh\x8e\x8f6\xf9ҋ\xda\xe1;\xed\xe9\xff^\v\u05ee}\x0f|\x90\x94\x03\xe9Gio\x0f\x18H'a\xb2\xe2\x8e\xfbn\x87\xaeC\xf2\xb1\xeb\xe0\x93\xbbҧvѻ\xd2\x17\xf7\xc0KN\xdeu\xe4\xc8\x18\xbe\x17\xb3\xa8u9/\x97\f\x18m\x06\xe7\xb6\xc4\x1fBr\x11\x96\x8eh\xbb\x95S\xfa\x80\x87\x8e\xd5ڱ\xf4\x04\xe2\xadt\x88\xa0\xd8b9\x82\xa6\xccy\xe3\x9c97\xcce\xdc4\xbc\x1f\xcbO\u007f\xfc1\x98\n\xe6ĺb\xb1.y\x8ap\xe5\xd4\v\xe7\x17\xd5vY\xf5&\x16\xb7\x1ck\xd2[\xbbj\x8b\xe6_8\xf5\xcaӟ\x82籺\x8f\xde\\$\xc7\x16\xbd\xf9\x91\x8e%i\xf02NC;q\xe8\x00\xf7*O\xf9\x98<$\x96\xfc\x9e\xb7\x1d~J>o\xf4\xfdIz\xd8wm\"8\x1f#\xfde\"\xd9\xc8\xd7L\xb4\n\xa1:R\xbe4p\xebE\x8f\\t\xd1#\xf0\x11\xb2\xc9\xf0\x18)_\xe0\xd0\x03\xf8\x98\xfa/\xff9\x10\xcd^\x98\a\\\xf2\xb1\x11-\x88\xc4}\xc3\\\xb5\xa8_\xcb\xe7\xc1\xd8r9*G\x97\xf7B\x1d\x18\x1c\x89\x94pH~}\x00>\x96\x9e\xd1\x0fjƊO\xeef/a\xefA\xfa\x04\x8e\xael\xc7}\x01ع0\x8e3\x8a\xa1wW\x85\xc9r\xd1KDoSB﹄E\xbd\x01;N#iQ\"\xf1\x10H\x86\xa4\xd1\xfc\xd5\x06\x90\xb8\xe3\x01\x9c\xc4\x11܅ :\xcc\xe03\x983#^\xc2b\xdf\x0f\xbaZ\xb3=\x1a.*\f\x95t\xc67\n/\xael\x9bN3\xd7/]\xb2\xf3#\xebԊ\x1a\xf9\x03\xf9\xb3\xf2\xaa\x84\xe8Y\x1ao\xfe\xe8\xfd\xb6\xe8\xd2\x05\x1a\x93\xb1\xa2d\xc1\x1b/\xac\xab\x9a2'a-\xf0r\xe2\x1fa|\xc0ƙ\x9fp\xcdg+\xca}C\xf2\xad\xdf\x1c2ٌ,\x0f\xb5\x01\x9bKK\x17\xf9\xebK<\xbb\x8f\x83]`\xdcm\xcdf\x00\xefk\xeb\xf2Z\xe6̱\x88\x86&ˆ-\x15\x85\x17NZ\x92\xd4hn\x86;\xdd\x01\xad\xa6\xba\x86\xd7\xf9]\x85\x01-_T\xa8\xd1\x04\x86Dך\xf6N\xeb\xf8jڢ\xb1\xfa\xa3\x81\x9e\xe7\xcd\xda\x1bn\xe0\xfc\xf5\xf4\xd3\xf7\xcbNO]\xa1eOȽ\xc9P4\xce]\xa7\xad}i\xd7CS]\x95\x1e\x8fI_%\x06\x17VuY[\t\x0e\xac\xf2\xae4d\xb4oD:9a\xb7\x0e\x11*\xe2X\x9c\x84\xb3\x93P}\t\xb7\x0f\x1e3\xb1\xf2\x81FU\xa9.\x16\n\xa3\x8f\xc6\x04\b\x87!n\xd8\x18\xe6S`9^ik\x0f\x8d\x8e3XW\x11G\t\x86\xddsJ\xcaAyx\xde4͢}}4\x8cWN\xbe\xf6Ik{\xb8\xe2\xb6\a+B\xed6c\x95\xdf\xf3\xe2[\xbe\x92\xdaz=k\xbaK\xee\xbd\xdb\xc0\xbaL\xd5w|\xfb\x98\xdfc\xba\\k)\xdf\xf4[\xf9\x1f\xfb\x96\x87\xca#\x8c\xc6^\xc2\x01\r'\x1a\xd7?\x06\xe8'\x9c\xc5\xc5\xccxP:̚wky\x95ݺ^t\xc4Z&\x9egX\xda^\xb3\xc8Z<\a4\xda\\\x1ck\xb5r|\x81Ur\xf2H\xb1`\xf9\x824͇\v\x98\xbe>\xcepk\xfdlw\xd5*iB\x1f\xfcU\xd4\x1e\xf7\xb5\xb9\r~\x93u\xbc\xa7㪗K\xd8:\xab_\xdfm-\\b\xb4\x86l@\x0fjG\xccC\x80\xea\xc01`\xa8Y\xfd\xd8\x1e\x88\x87\x95*\x1aIbQԟ\b\u00a0\xcf\xe6\xb3X=\xa8\x05\xe9G\xba\x1d\x8f,\xee=\xb6i\xa6\uf069[:\xc6[Y\xc03\xff\rfȏ\x1a\xbd\xed\xe3g\xbe\xf1Y\xa0\x15\xc0\xfa\xa5\x17\\\xd0\b\xbd\xef\xba\x16.۸\xb0\x92\xe5\xe5EC铞\xba\xa8\a\xc0|;\xbf\xc2 \x1bFS[\x15\x8cZ|Q\xecЁ\x06>\x1e\t\x84\xf8Y\xad`\x94-tSkESI]\x81\x0e\x80S\xd4q\r`\v\xa2k:\xf6\x96/\xbcmդ\xcb\xc1\xdd\xf9\xed7\xfd);p\x94\x8es\x80k~\x01&\xeb*\x16\xf4.(\xb8O^ް\xado\x02\x04\xe3\x99\xea\xe1\xb6P\xfaT\x02\xa6Q\xdd1j\x8f}l\x95\x1e~e6\xcaw댂N\xbeè\xd1ZU\xbc@\xa4\xb4\x99\xe5\xa4N\a\x92fIb\x88\xcdb0\xe3SB\xc14\x9b\xc2\xf7T\xfdV\xb2\xb0\xc9q5H\f\xa6\xb3\xf7\xb1\x99\x8d`9\xbe;Xed$i\x908p3\x03!3@7\x97\x93f\xe5\x1d%\x00\xcdSt\x9a\xdc3\x83\x82\x9f\xc1\xc0w(\xe0\x19<\x85K0\xa2Pp`\xf83V\n\xa4\x06\x8a\x1f2\xa0\xb9\x94zO\xc5.=\x1c=\x1f\xb3\xea\xa4p\x11F\x94\n^\x8a\x9a\xe2NA\x93_\x05\xd4@Y\u007f\xfcͨ=C$\xeaQU簰\x1e\xf0\xd30\xaaJ\xdbXf'\x1a\x9f\xc2\x11\n2ܪ\nѝ\xc3jg7\x87\xe7]\x92\xacY\xb2`B\xcb\xecّ\x9bo\xbc~\xf3\xe6\xa3S\xd7\xf7\xfa+W\xae\x9d\xb2cy]ݬ\xc0\x84\x03\xf2\x87E\x9e\xb6X,\xd8NO\x9f\xf6\b\xa0\xd1\f3a\xf7\xee\xe7\xbd^\x9f\x1f\xed\xb0\xff\xfc\xe8\xd0A\x8f\xc7\xef\x9fP\x92h\x8f,\xdf|ы\xccΖ\xe9\xd3\xdbb\xa2\x9e\xbb\xf1\x9c\r\xe3h3\xcd\x18\xb2\xfe\xfc\x04\x8b\\\x91\x0e(`\tZ\b\x9b\x93\xba\x85?J/\xc0\u007f\\rh;v\xed\x82bz\xfbrX\t\xff+}.\x8c\xa6w\f}\xbe\x1b\xdeH\x9f7\xf41\xbc\x03\xbbu+\xb8\xb3\xec\x1e2\xdf\x17\"It\x06ҁ(\xaa6F\xe6'Fݲ\xca,\xa6tn\x05ʒ\x04T\xb6`u\x97,.\x84\x89\x8d\x10\aZb\xefz\xec\xc9Z\x8c\xdd\x18p\xa08O\xbe\f\xf5è\xb5\x83\x0f\xbc\x0e\x87\xd7\x0e\x8e{\xedv\xafch\xb0\xac\xb9iAs33+Q9\xbdyA\xf3\x81\xe6\xf2\xb2f0\xad*\x01\u007f\xbc!9\xb4*y\xce\x14\xde`䧮x{\xc5T\xdeh\xe0\xc1a|\xbe\xb9\xac\xbc\x99)r\xe0\xfb(\xff\xdeh.\x93\xe7\x9477\x97\x83\x1f\x975K\xe9\xb5U\x89?\xe3\xbd?+\xbf\x89*x+\xb81\xfe\xc2\xf6\xed/\xc4/5\xf2\x9ca_Y\xd9>\x03\xc7\x1b\xd37f\xae*ojB\xf3(\x96\xbb\xbe%\x9c\x1b&\xca\x0f4H\x15\b\x82\b\xe8\x04\xff x*\x01L\xe9T\xeb\xe0B<\xaa\x14\b\xe1q\x87\xe7\xf0\xf8\xddJ7\x83\x10\x12\xe0\xb1\xc0\xa3\xc8;x\x99\x04\x9dĒ\x0f\x99\xe9B1u9\x05\x0f\xf2hԏ\xc7\xea\xa2\xe80\xe7\xb0\x06\xaaP7\xc6\xc4\xf4\x1c\xe6@\u009a!O\x02\xa0\x1c\xb5v\x8e\x04\xaf\x92)\x96\xc6c?\x8d\xa7\x04\xa0p\x9c\xa0Y\"\xa4\xcc\bh\xfa\xc4\xc1#\x02^\xb1\xc1ކV\x01\x92!ю\xb3\xe0\xf7@JI\xbc+\xc9\xd5\x1eh\x8b\xa1\x19\x06\rX\xe8j\x12ȏ3\x10\x03n\f\xcfA\x91V\xa4p\xe0\x02\xd9\xec\x8eZ\x9eC\xba/\xae\x12\xa3LU\xe1:4\xe7\xfbq\xd2aE\x17\xd7aa. `\xb1\x1fM\xfb\xf8\x0e\xb51\xe0\x81\xb88\x80@\xb3\xd0\x04\xbc\b\r\x93a\xa5)\xf0\x03p#`\xe9\x10DI\x11q\xe1hފ\x1a\x92\x94\x10\xaf\xbb\x91ո\x10>I\xd6\xe1P\xbd\xe3\xca\xfc\x18!`6\xbc\x9a\xd7N$Or[\xd4F\xb8Y\xd5\x1b\xab-\xeda\xe1Mz-\xc3J\xecRƤsjh\xf96\xa4\x05\xd04\xaf\xd32\x16\x06@\b =?\xce\xf04\ry\xa0\x05\xbai\x01\xa7o\xa1O\x1f.6\x01\xbd\xd6&\x1a\x8d@\xf0\x17\xd8\x19ƪ\x0f\x9b\x9a8\rg/\b\x16\xea\xf4\"\x92*,\x05v\xf3\x06\x11h\xc7\x15\xd0\xc0_\xe8.\x82@k\xe1u\x1c\xa3\xe7-\x00X\x9d\x16+\x00v\xad&\f\x8c\xacN\xb0\xeb\xdc\xf6\xea8,s{Y\xad\x9e\xa5\xb5\x06k\xa7\xb6\xc2U\x10Cӂ\xb9\xa0\xcc\x12\xf2\xfb\xdcv#\x84\x1c\xa7\xe7\x8dtᬘ\xddVf\xa7\x81\xa7\xc8(:fi \xe046/\x039\x86\x85\xb0\xa4\x8a-e\xac\x0fh\xcdt\xb1GS&T\x85\x19#\ah\xab\xae\xea\x82\xcb*\x1cz\x03D\xcf\xe4l\xb4\x03B\v\xb4\x9bJ@\xfb\xcc\xf4]\xb4\x9e\xd3BZG\xd3z\x1a\xdc\x03\xb5\x16\x8eղ\x1c\xa4\x852Q\xab\u007f\\g\xa09\x86\xa1\x05F\x03c\xac\x916i\xb5,\r\x81\x0e2\x8cF\xd0\x00\xb3\x00\xe3V;䝎\xa0+\xa4\t\xad(\xb4\xac\r\x89\x0e\x9d\xdfS\xb1@\xea\xb2VL)\x89\x14\x16ݛ\x90\x12%\xe5NV\xe7\a\x00\r\xe1:a\x81\xc5\xe3\xb4E\xbd\x11\xbf\xd6(B\x03\xcb\x00?M\xfb\xad\x97\x04\x9c\xab'8\xca\xcbiѪ\xbbp|G\xa5\x9eA\x83\x9f\xe8\xe15A{\xc8z\x9e```]wxB\xb4\xaf\xa4a\x12\x8b\xe4\x84U\xf1\xc5&$n\xe8unw\xcc/\xbaE\xad\x00\xed!\xd1l\x95t\xf5g\x956\xb5tF\xc7\xeb\xc3^\x9f\x8f\x16\x80`r\x99\xdd\xcc\x1a \x01\u0380vM\xb4\xde\xc8\xc9s\x80\xc6²\x1a=j_\x1d\xad\xc1/\x1cʷ\x8aNS\x81\xdb\\\xa4\xf3\xf3\xe5\xec\xf8\xf3\xacֶ\xbb\xb7\x95B\xa6rgU\xb8\xb9X4\x80\xd69\x9e\x12\xbbm\x82_C{\x00\xa8\xad\x03\xf4\xc4\x02\xc9\xc43\t\xd6Sj\xd3Қ=&\xa4@\xf2\r\x13\x01h(6U\x14CZ\xaf\x05E\x92\xdd\x03\xcaJ\x18\x93`p\x00\xc1\xc5j\x1c&=\x80\x16`\xd0Z\xb4\x02\x87JBsŌ\xc4 \t\x94aL\x0e\x00\ffɤe\xb4\x90e\x19\x8e\xe6\x81\xd0\xec2\xe8[\x8b\xb54_\xd06\xbe\xa3\x88{\xa0A\\\xabqڊ\xdb\n\v%\x00\x98\tk\f^\xc6q\xb9\xd6TUJ\x9b\x9aj\xaa\x9c\x1d\x1a\xb3\x06\xb2Z\xbe\xcel\x9a\x1a\xd2pU\x05\xedHݖ\xb6ym\xeb\x17\xbbĠWO\x97Y\\\x10jY`\xb2\xfeB\xc3\xd3\f\xad\xe3x\x00\xcdq\x06\x88\x03z\x8b\x060\f`\xdc4\v?\x85\x9c\x06\x9a\x80\xd1\xc81F\x96\xa3Q\xbb\x01\xe6\xe4K\x86\x02\x87\xddn\xb1\x1aEF\x9a\xe66\xf3\xa2\xb6Ȏz2zK\x85\xde\x02\x00\x9a\x8d\xa8g\x1b,z\xc7B\xbdy|\xb0Dk`t\xa2\xdf\xdf鳲\xb4\xd1T\xc69\rv\xbd\xa9C\xb0h\xb9\x02\r\xe7\x15h\xae\xa2nB\xd8\xf2Ӻi~\xad\xd3l/\xc2t\xdekc\x1d\xd6k\xeb6\xbdx֮r\x1b(r\x97\x1d\xe9X\xb1c\xf3\xfa\xa67\x17\xd6L)\x85\xd0\x1fD\xad\xae\x91\fElP\x98\x17\x9f\xbc{\xc2\x14\xd6W\x13(@\xd5*\xd0\xeb\xa7M1\x14G\xbf3Q\x19_\\Uܶ\xb1\xb3eIsP(\xb1\v\xd6\xd2p\xc4[Y\xe9m\xae\\zip\xf2\xf6\x83G>\xec6o|\x0e\xb0\xd7v\xce\xe8ݫ\xecȃx\x87\xe8\xe7\x15Hwx\x85IJ\xb4Q\x1d$\xe2*c\x0f\x89\x13|\xf2ZBS\x1cʳr\xc6\xe2\x9c\x0e\xbb\x94\x10\a_\x80\t\xed\xb2\xf0\xa9t\xcc\x05\xe8\xbf\x06\xd9B[\xba\xdeQ́\x80\xc3\xe3\xfb\xc2\ue85dF\xa6\xd8&\xff\x0e\xafF\x83\xb3D\xffǦ\x19\xad\f\xc7\xd9ݵ>\xf9\x1fF\xadF^n\xef4Ļ\xe6\xd0\x17\xacH\xd8\xefdZg03\u007f\xe1\xf0\xfb\xad\x83\x8f\xa1\a\xf4\xb8LE\xa6\xbd-6tmYQ\xd0\xfdy\xa7\xbc[\xfe\x95\xc5n\xab\xb0[uZ\xd9]\xc0k\xed]\xec\xde\xf8\x8a\xbe\xbe\xa1O-\xa0\x01\\J\x8dXwP4\x95Q\x9e\x9ag\xc08\xc5vi\"3\x83\x01\xd5b\x9b\xdd\xeb\x0f\xb9N\x12\x93\f\x8b~S\f\xb1\xf7\x0eQ\x84\x98\x1c\x12K.\xb1\xe7\xd2B.S(\x13W\x86\xfd\xaf\x06\b\xff\xa3b\x85\n\xd3\x01\x9bd'~L\xc3\xc8Y\xea\xe2R4@\xablm$\xf6\x1b\xc9\xf2\x99\x98\x1f\x96\xaa/\x8d\x14\xfd\xb9\xf2kmȕ\x9aX\xd5_51\xe5\ni\xbf\xae\xfcsQ\xa4\xb4\xde\f\xa8\xceu \xb9\xae\x13Pf\xb9\xe7\xd2\xff\xb8\xf4\xd2\xff\x00\x03\xa5\xf5\xe5`\xfe>y\x8dIt\x85\xe4/\xab&N\xac\x02\xe6\x90K4\x81\xdb\xf6\xc9G\xcb\xebK\x8b\x9c \xb9a\x83\x9ct\xd2=\xf8\x82K\x95\xb22\xb8\xacA≫\n\xbb\x81\xd3l\x956\xcb\xe2\xb3Q\xf5\xdd\xf5\x89\x89K'\x92?\x94\xde\xd4\r\x93ݛ\xe4\x01R\x1a:!+\vt\xcf³\xeaBGw\x9c\x90\xea$Iz\x815\x8f\xf3\xba08\x9c;\x1c6\no\xd8\xccb\xd4\xfa\xe7-\xfd\xb8b!\xe5B\xe56\xf2\xef uٳϢ\x0f\xfc\xd4)\n\xf0\xbb\x99)\xd4e\xc4g\x10\xaf\xa7\xe1\xa5K\xacY@\xa4\xea\xb1\\\b͍4\x1a\xf5\x1dVB\x81\x81\x97}\xf0\x11\xa4f\x11\xe0\x1c$\xb2\xe09\x12\xffz\xe8\xdax+C\xb0#\x88\u0085{\n\xd2i\xac\x04\x0f\x86\xac\x8a\xe3\xd5<\xc5\xfe\x01\x1dA\xa4\xc3\xf0\xbb\x1dǜ\xe3J=żT\xe5g\xc0յ4\xcfk\xcaB\xa7(g\xc2j\xf5t7Lp\xd2:\xa7d\x02<È\x81\xadS\x0eo^\xe6,\xd0\x05\xce齺\x99\xa3\x19S\x19\x10\rv\x965k\xacu&sQ\xac\xbc\xb4\xd0\b9Q\xabc\xa1\xc0s\x05\xcdF\xd1l\x8f\xfeǜ\xa8\xd5-\xf0\x10\t\xf4\x9cEЈ\xfe\xb2\xd6`s5\x83Dr\xc8Yu\xc0\x1b\xae\xe5\xe8o\x12\x1f{\xa3\x91\xb2\x06w\x19\x12i\xe1\xa5g\xb1\xa6\x90\xa7\x80a\xad\x06\x83m\xc1\xa4j\r`\x9d\x81I\xe5\xa6\x02\x8e\x95hf܄v\xa7SWzM?\xe0\xae6\xdbYNB\xb2&C\xebm\xb5\x1b\n\x8b\x9a\x17\xd5\x14\xb2@S\xd2\xd8\xdbY:\xd1h\xf0k\xa1]һ 0\xb0\x96b_c\xdd\u243e\xd5_]\xac\x85\x8c\xab|Ik\xef\x85:\x13\x06\x1f\xa1\x01dMZ\xc2\x15\xfc#\xeekv:\xa5##^55\x9fZO]\x8c\xbeƬN\x8cgc\x92D\xfa\xa7#\x83\xf7\x89\x1a5X\x05Jx\x8e\xc1\x1fb[\xa2ZB\x0fP\x01CcH\xbbTT\xca 9F\x0e\xa1\x13Xe\xc7*:\xbc\a\x9b~g\xda\xecb\xc7\xecm\x1a\xadQ(\xe2-\x1e\xc1\xf3D\xe5\x9f6n\x98]]}\xa2o\xe3\n\xa4#\xf6˧\x0e\xfdQ\xfe\xbd\xa0\xed\a\xe0\xd0\x1fA\x10\x84\xa6\x1d\xfc\xb9\x9c\x96?\x96\xff\xfb\x9d\xbdW&\x1f\x04\x8b\xa7M\xa8d8\xc1\xc4qW\xfe\xa6\xaa\xb2\x12\xb2\x82\xceа\xb4cۼ\x02IS\xee@\x05\xb3.js\x961\xac\xcb\xd9\f\xe6/\x8c\x84\xb5\xb51\x97\xa6\xb0\xa4\xb5\xf5\xa1\x85\x85\xe3\rŅ\xbb\xfe9\xe4\x9fl\x12\\>\xff$\xaf\xfb6\xa3\x9be\xf5\xc6b\x81\xd5/_\xdbS\xe2\u007ffŲ\xa5\xee\xa2'\x9a{n\x98,8>;\xa4l\xae\xe9\xb8\xf6\xd2\xde\xd6\xf6\x1dO\x9d\xb3\x150\xc9\a\u007f0-q\x9d`@\xbd\x006\xb5\xb4m5\nzԡ\x1a\xd7\xc3\x15\xcbwգ\xa7\xa32\xb4\xf5\x18\xd1ӝ\xe3X㬞\xf4V\xb7K\xacu\xcfy\xbccRT\xe4\x8a\xeb\xab9\xd7\xf4|\xd9b\v\xa5\xa5$\xcc\x17O\xf8m\x91\xa6\xed\xc1k\x9e\x90Ǥ\xcc%\xc0̣\x81\xd2bgD\xe6ܣ/<\u007f\xf4\xc0/\xfd\x81_ʷ\xa5_}\xe2~P\xc2D\x9fx5\xfd\x18(\xb9\u07ff|\xf9\xc2o\x0e\x1e\xfc\x86m\x91\xddC\xf2٫\xde\x05\xceg\xc1\xa4ߤ\xcb俾\xbb\n\x1c\x19\x02\u007f\xf1\xfcF~VY\xebC\xb2\xc3N$\xa7m\xc0k/4\x16U9\x8a'(\x1fh,\x16 6\x1f\x00\xf4q\xc5p\x9a\xc5i\xb6\x18ĢU,\xd2\xfb\x19\x01i8hx\xc2k#\x02\xfe\x909\x9cdwz\x17-\xef]\xb5|V\xb3ٲY>\xf2\xa6\xe4rI\xc7@\xf9ڒ\xa9\xcb\x17\xad\\0\u05f7\xe5\xa5˷\xb4\x15D]\xbc}JNJ9\v\x12\x95\xdc\xe4\x8bW.h\x89\xf8\xec,cи\xa7\xd4\xd7\t\xa1H\xe7\xb9\xcd%,g\x155\x92\xbf\x05\xaeP\x01x\xe7\xb8 j\x8c\x15\xd3\xf6̭\xb6\x06fvU\\\xda\x0fhH[\x8a\xea\xa7m\x9d\\h\x91\xc65\xb5\xb5\u0558\xcc;;9\xeb\xa4i\x9b6_\xddQ\xd0\xd9}֢\xb9\x93c&\x13\xb3\xd4\xc5;ڢ\x8d\xc5\xd01\xf3\xe29-\x1e\x11}>\xf4\xf5W\xf0\x8e\xa6\xaa\x10\xacAb\x8b\r\xc9.\u007fc)\xe2In%\xf1UD\xc2\x02\x8a\xcf>\xb0\xf9,\xf8/h\xcb021\u007f\xdb:\xbbA\x1eJ\u007f1{+\xf3\x9b\xc1\xb2\xcc\xdf\xd6\xd9\xf4\xcc\xd9[\x81{\xe2\xfc\x1d\xf2\xbf\x80q\xc7\xfc\x89`\xf2)\xea\x14\x98\x8a~\xaejo\x9f\xb7cG\x9e\x9c\x89\x11\xcaj\xd4\xf8\xa01iL\xed\xa7\t\xeeb\x92*\x91i\x86dS!2}\xf0\xbb\x02\xbd\xe05c\xf0\x99\x1e\xfd\xae\x80\xafa2\xb1Z\xd6\xe1l\xac\xf9d\xac\xe2iˊ9Kq\x01sT\xac\x98ɴ\xff;\v;\xa0\x16\x11\xb4afT\x85\x91U>\xf5\x9d\xa5\x1d%\xbf+k\xa6\xb9b\x8e\x94\xdfGY\x1b\xa8\x90\xcbjQ\xc2\xce,V\x1cC\xfb\x1d\x01j)\xec[eP\xc3\xc6\f\xa1\xa1\x17\xbfG<\x18\x8f\xbe\xfd\xe2\\\x1c\xbex\x1a\xc6\x00՞[\xf6]\xbc\x01jt=\xf0~'}\x80\xea\xe3\xbe\f\xc9\xe46*\x86#A\x898\x86\xa5\xb1\xb8\x03ϭT\x04\v\xa5\x0e2\x1a\xd1\n\x90X\x9c\x90\x8bbK\x83\xe4\xb3\xf9p\xb4\x97D\x9fZ\xdb(\xbf\xf9\xec\xed\xf2\u05f7\x9d\xf8\x91e\xe7!\xc0?\xb3\xe7\x9d\xed\xd0\xddx\x8a2\x9aK-_ȥ\xce \xdd\x035\u0082\xd8\xc4\xe5\xbd\x1dAp\xbf\xbc\xde\f~Uj\xf9\b,{\xf5\xb1?\xdc\x06\xb4\xb7?\x01\xcaZ/\x8d\xfd\xf1\xb2g\xe4o\xf7~\xe0ڒ\xe4\x03\xe0\x03\x9f\x93\xd6[\n\"m\xcb'N:\x9b\x97\xff\x98L\x06\xe4\x86a:\xb6\xc2\xeb\x13\v\x87h\xf4\xfax\xec>\xa9,j\xe2\xa5Q\x87\x12\x9b\x85\xed\n\x928\xca;Ѡ;\xfa_\xb3+B\xf3\xf5\xccU\x81\xf2\xb0\xd1\xeb\xd9۴\xde}\x8e\xbb\xaeK\xdfPkj6u\xf4\xdc\xf1\xa7\xf7O\x0e{\x9f{\u007f\xcbi\xe4\u007fI=\r\xef?\x18\xfb\xf5s\x06~\x99\xb3\xc7\xd9^\xf7X\xfc\xf7\xf1\xc7@\b\xb8\xc1\xc5\xc3,h*\x9e\x03*#\xd6\u007f\xad\x90Q\u0530\xac\x83Q\x1b\x88\xe6\xa73aXHp)Br\x1fk\xcb$,1J=\xc9$\x9f\x93\x8f\xff\xac_\x10ߥ9\x9d\xd6\xe8\xf8$\xb3\x15\x05t\x10\xec0\xb9\x1c\xf2\x0eus\x1c0\xe4(L\xfdL>\xfe\x9c(\xc0U\x13\x01\xa73'\x1d\x9a)˲\xa9\x93X\xab|b\x1bk\xc5{\x17.\xcb$\xe4\x02#\xb0\xfe\x14{\xfa\xe6b\xbf\x03*\xfa\xb4M\r3R*\x93\x1d\x8c\xb2V\xb1\xef\x19\x0f.+\xac\x96r?Q~{\x94\x18\x94\x9e3F\x87\x8f\xcaO\xee\xf4]\xd1\xe2j\\\xac\x06\xe3x\x86\t\xe3_\xb7b}\x8b*Jp\x15Ph\x8d\xb1\x8f=\xea->\"\xc1\x10WT\xc0\xc7\xd1\xe4\xe6\xc0\x91\xbe>\x8e\xf7#\xf1\x14\b\xa0\x1cБZ: a\x88^\xe0a\"\xac/\x04\xcf9\xef\xce$\xfa\xa4\xf9\xc6\x193\x1ayɘH\xdey\x1e\xb3\xb8\xec\x12\xf3❕\x95;\x17\x9b/)\xe3\xa2\xd1\xd9\x1d\x1d\x83\xf3\xe9\xaf\xdf\xfb\xa2a\x93\xbbP\x1ep-\xae\xecYVt\xc7\x1dE\xcbz\xaa\x16\xb9\x80\x97\x11\xaak;K\xc0KC\xdam\xa0?\x91\xa8\xf69\v\xa0\xc5i\x81\x05N_u\"\xc1\xdbiS\xa4\xa2\xa4\"b\xa2\xed\xfcPɦ\x12\xcf\xf8\x1b\xc6˿\t\x95\x8dw:\xb1W(x\x13\f\x807\xb1\x87(c\xf4\x15غ\x13\xea\xf7\x81\xb1D\xe6\x10\xffd\xfc\xb1b\rQ\xb1\"!\xa52\x97\xcc\x104\xb4\x01:\x97\f\xabn\xacH\xc3\xcc%Ux;\xd4\x10R<\x06\x824\xcb~\xd1:w\xd9C\xf5\xfc\xbc\xa6\xea\x19\xa6\xb8\xfcr\\3\xaf\xb9\xba\xcb\x14\xbf\xa5\xc8\xd62;^q\xfb\xfa\xdb]\xf6\xe69\xf1\x8a;\xa2ʉ\x18\x88\xc54\xf3q\xe6\xe8\xdd6{\xf3\xfc\xe6\x8a;\xd6\xdf\xeb\x1c\x1a\x02\xb1\xf5\xf2\xcb\xf0\x9b\xd9-g\xfb\x9a\uedf9\x9a\x16\xc4*\xef\xeb\xbb\xd7\xe9\xc0\x89{\xa2\xda\xee\x16t\xed\xffG\xdbw\xc0GUe\xff\xbf{\xdf{\xf3\xa6\xb77\xbdf\xfa\xa4'3\x99\x99\xf4N\x80\x90\x84\x10zh\xa1w\t \x1dahb\x03\x15\xa5\xa8(Q\x11\x1bv,(\xbaY\xfbZP\x17\xb7\xe0ς\xbb\xb8\xbb\xb6\xb5\x17 s\xf9\xdf\xfb\xdeL\b\xc8\xfet?\xff\xff?0\xef\xdd\xfa\xca}\xb7\x9cs\xcf9\xdf\x13\x03eq\xe9\br\x95\xd8>\x8b\xb9rt<\xbfgn\x0f)\x92Ȼ=!\x19^\x91?T\x13G/\x96J\xd1鹠b\xfe\x85{5ق&\xd5\x05:\"@\x97vd_\x06Ү\xecC\xe9\x1e\x9b\xe9\xc0i\xbc\fI\xa4\x9aM\x04\xaa\xc1@%\x12\xfa\x84\xdb\xe3})6\xad\xbe~Z\xe1s\x85\xca\x1cyi\x98\xae\r\x97&\xb2\xfbzåU\x81\xc2\xc7C\xb4C\xed\xe0-F\x83\xd1\xc2\xe3\x10\r\x14\xbe\x9a\xf3uMΜ\x00\x87|\x06\xd3:\xff\xa0AY\xab\xb2\xa4A)j!\xce\x14ff\x97\x97\x86\x03íYKl\x90\x97\xe9dD\xe9\x05\x9fx\xf8\xa0y8\x95\x91%\n\xb6\a,\xee̓\xa9\x11\xd4Tj1E\xf1x\x05\vB\x01!\x93\x16D?A\x8d\xb8\xa7Ax'\xbe?\xc9\x1b\xf4\xc5\xfdą\xb7h≩}\x967\x99\x855\x10\u007f[\xc8\xf1\xf1X\t\x95\xc5\xe0\xa5\x1a\x12\x90\x9d ^n\xe2T\x96?\x8e\xe3A\xe2\x03\x04\xc7M\xeb\x1b\xc0\xa2\x17\xff\xcdJY\x8d\xd4δ\xa0\xcf\nrx5Ͽ9l\xbdR'\xa15\xca\xf6\x95\xf7\xa0\u007f\xa5Ӹ,\xf9\\0\xf2\xe5\x1b\x80b\xae<\xd1\xcc0J\x89\x1e\xf7\xe6\x1a$\xf9\x120\xeb6tϥ\xd7Ly\xfb\xa1\xcf+\xfa\xee\x00\v@\xcb\xd7۷\u007f\x8d\x0e\xa1\x1b\xd1!\x12\x02\xa3A'\xa8\xfa\xe4\x8a+>A/\xa0\x03\xe8\x05\x12\x82\xc9;w\xf5\xf1S\xc0\xa5@ʇ*\x1d\x9d\xaa\xb3\x14]N\xb3\xd0\xe3\x04r \x03J=\xaf\x06R\xf4\x14\x92ҵ\x99Ԟg\xe6u\x8dH(-\xbc]\xe3R\xfa\xd9\xf9\xc7R\xab$l^\x16\xd3\xf1\xe0\v\xef\xa0}\xb3\xe0\x81{\xe7\xe7\xc0\x92\xf3n\xdc\"<̩'\xaf\xf8\x04T]\xf0\f\x99\xb5Gh\u007f=\xd1\x17\x03:6\xe8'cğ0J\x18\xa3\x811\xeb\x00\x1fH\x04C1\xc6\xccT\xa3\xafO\xa2k\xfe\xfc\a0\xe9\xf8q\xf4)\x88}F?\x10H}wÊہ\xf1\r\xe2\xa24i؟\xdaq\xcdO\xfbm\a\x83'\xae\xdd\xf3\x0f\x17ێj\xd0\xea%#\x9b\x9c\a=k3:\xe6\x82\xdf)%\x15\xa4\x8a\b\xf2\x80ї\xee¾\x18\xf0袺\x01\xbfs\xd8ql&\x18\xa5{\xe9\xded\xb6\xe3\xb4ܑ\x9d\x04xMJf\xfeW8\xb2O\xe1\x8c\n\t\x0e\xfc\x8c\x03\x12\n%E\x04\x90\xb3T\n\xdf\xf8\xdcO\x84'%\x1e\xed\x92\x19_\xd1I\x99h\xbbN\xe8\x05\xde$t\x94\x04Ϛ\"\x89\xb4\xbf\xad\x00\xb1\xba5\x1a8>\xad\xe3\x89s\xc9d\x1bO\x042~\xbd$\xff\xd63\aџ\xd1~\xf4烌\x1eV\x9bJLL\xbb\xe9L\x0f\xa3dR\x97\xe6\x96Jj\xcaˡ\\\xa6\xe9\xd5\xc8䰼\xbcN1\x16=f21]8\x9b\xe9\x82GЋ\x83\x96\x0f\xc2\xffA\xe5\xe3\x1c\a\xb5\x05R\x84yã\xde[f\xfa\x87\x0e\n\xa2\xe1j\x05\xfeS\x83G\x82\x83\x86\x06\xdfZ3GZ \x05]\x00\xa0\x1e\xfc\xfe\v\xcf&\xd9\x1bD\x9d\x16\xc0\x13\x01\x05\x1f\xa4 \x91g`6Ko\xae\xa6\x13$XL\x00\xed\xe8\t\xaa\xea\xdc\xecZU\x18\x9d}xRy$\xaf\xa1f\xdb\xefs\x02\xd7w\xae,\x8c\xc7J\xcb\x1d\xb5\xbe6\xf9\x0eؐ\xaaR(\xe0\v\x83\xc0K |\xb5F\xb3\xe8K\xfcdU\x9f\xde\xf0\xe6X\xb5:4\xbd\xfcr\xdd\xcfi\x9f8\xec\xc7\xc2\x1aJ\x01\x0f\x19e\xe2~\x17\x1eY\xfeh\x96\x99\xc3O!\x10y\x98\u03a2\x13\x1e\x9a\x82\u007fR>\x81\x1ez\xefVt\xf2\xe8\xaaUG\x81\xe3V\x90\xf7\x97w\xd6<\xb9\xe1\u007f\x92\xc9\xff\xd90v\xc7\xe4&\x8f\x04\xb5\xc0\u007f7T\x1dG\xf7\xf7\x92\x02\xa0\x1c8\x8e\xae\xfa\xc3\x1fVl\xfc\b\xfd\xfc\xd1Ƣ!\x13;\x02\xa2^\x998O\x10\xbbW/\xd5&H#LD90((ѓ\xfd\xb5\x88?\r\xd8\x1ca\xd3\x14\xa7)A\x80m\x82!\xdeL<|\vئ\x98\x9e\xa2%\\\xda\xd0Ì\x0fL4⏕`n\xd0?`\x96\xc0\xb3\x83\x89\x19\xac\xd5V\xa3\u007fWk\xb5\x12\xbd\xa4h\xd5\xcab\x89\x1e\x1d+i\x8eŚ\xc1\xefb\xcd%8t\xa6i\x86\u007f\xe3\xe35\xaf\x92\xc4@\xdc\xf6\x01/\x19th\x83\xaf$\xd2\x14pK\x80套\x81\x85s\xf9\xc1\xac\x8b\x8cG\xb0X\xab\xa9\xae\xd6h%\x92\xe2bɻ\xf8b\xb8/u\x06\xc85K:\x8a\x9b\xfc\x9d\x12`\xcf\x0f\x94Ěc\x91b\u0588^\xe5:\x03Mžr\x8dݹ\xfd\xb5\u05f6gY5e\xcf\\pA\x1c:\x1f\aK#xs\"\xf3\xa9\xd0N\xdet;\x91f\nd\x9a\xc9\xc4\xf6\x87\x12B\xe3\x04C\t3\xf9v\xff\xa1\xa9Dk\xfb\xd0/\xf5\x96\xe8\xfbU\xaa\xd8\x171\x95\x8aղ9GsX-B\x05\xd5\x05\xf9\xb5\xf9\xa0C<\xff\xa527ǽ\xf8\xe6\xf8\xfd \xdfM\xe4.E\xc6guL\xe5͋\\y\xb9\x95Y6\xf6\xeb{\xef\xfbZbu\x83\xe8y\xf8\x13\xbb\xf1E\xf15%\x92\x9c\x1c\xc9.wA\x81P3}\x1e\x9cS\xe9nc\xbe\ve\xe5\xe1\xab\xe7\xe6\xb0z\xf4\xbd\xa45\xab2\xc7\x15QYͫ\x1fx`\xb5բ*\x06'/Η\xb8\xf0\xecC\x10\x99\x13i\xf0\xb1~\xb5\x14\xe1\x05E\x95\x13'`ciE\x95*\xc0\x85\x8c\xa4\x03\x9d\xa7&9\xad\xf3ҞK\x1dA\xfb\xee\xa5\x1d#\x96\xda\r\xbc\x1d\\\xb9\x8b\x9c:+/\xbdc)\x18q!\xffr\xd8^=\xbc{\xd1p\xf4\x89\xc1n7\xac\\ݱdq;\xc0\x8b\xa9\x83\x8f\u007f\xb4z\x9d\xc1\xee\xe0\xd7\xd8\x1ckڗ,\x01\x0f\\\xc8Ր9\xeaN.\xc9N\x12\x9e[\xc0E\x12\x1fZ4\xb1\xefw^/<4\xc7z29愘\xc5\x04+GU\xf6=\xf2\xe8\x190\x04\aR\x0f=\xdc\xf7\x02\xb8\x16\f9\xf3\xe8#}\x9b^\xc0)t\xe9r\xa2\x1e\x93\xda\xfb\xd0\xcfg\x1e\x05rt:\xb7\xa2\"\x17.\xb8\xff\xdb\xef\x0f^Q~;\xfa\xf1\xd13\xa7\x1e\x06ʪr\xf4mNEE\xce@~\x85\xe0}P\x01\xe2f\\t\x8fz\x11\xfa\x98\xedMբ\xacI\x9b`/81iS\xed\xc0\xef\xdb\x03N\xc0\xdeM\x93PV\xaav\x13\xe3<_aO\x8a\u007f6)\xc5\xfc\x03\xf7h\x19\xbe\x8fN\xb0v\x0f\b\xb89dy\xf0X\x81O\a\xf0JA\x1b\xa31\x9e`S\xe0\u007f\x01\x1dN\x1b\x18\x1e\xf2F\xea\v0d\r\xb8\xe9\xcd7\xdf\xec\x80\xc6\xd4\xe7`\bz\x8a$\xdc\f\r8g0:\f\x06\xafa\xfeї\r\x0f\xe3\xbc\xc5\xe8Z\\f0<\f\\o\xbc\x81\xfe\xd6\xd7qg\xc7~1\xb1?8`|\xc9\x04l\xd4\"\xe2[\x88\x12\xd8nb\xf31 \xa4M\x03ys\xba\x04\xb1\xed\x80B\xdc'F~\xc1\x88\x9bZb\xb9vGN\f\xfd\x90\x0e\xc0u\x0f_f\xe0͉\xb1k\x8fE\xeb/\xbb\xfb\x91˚\x1b\x9e>\x96\xa8\xba\x8c6\x9f\xa7D٘\xec\xd4\x00\xa3\x0e\x8cHN \xe7T1P>G\xb7\x95O\x91\xa46g\x1f\xe5\xe1\\\x1c\xf5\xf7=\x85\x83\xe0\xe7\xf3\xdbWNe\x9f\x95qo\xe2\xf9t#u\x84z\x8d:J\xbdO\xfd\x9d\xfa'\xf5)\xf5%\xf5\x15\xe1A]4Q\xd0WC\xae\x80\xf5\x11MR\x17\xe7\x06&\x1c\r\x8a\x06$%\x89j\x88\xa7\a¢\n\x9a7\x8cHl\x93%\x11\xcf\xfb\x02Gm\xceP\xd8P\x92F\xe9 \x82\x92\x10\x99@\x04\x1b9sBM\x9b\x13\x05\\\xa8\x00\xe6\x10\xd7+\x98,u\xc1\x1a`4c\xe2NZ#\xea,\x11\x85U̥\xd1\xe4\x82\xf8\x89\x04\xca.a\xe6\x80\bL\x1d\xaa\x86Q<4I&\x1fũ1\xa3\x06\xd4@\xe6\xe5aWN\x9f]\x97\xeb\x99P9\xa8h\xd5^\u007f^\xa5=T0}\xa8\\\xc2\xc8$y\x9c\x9b\xd5\xd3\x12\x00\x00'\xd5Ѿ\xcdY!\x0f\xa4aE\x02\x8fD\xff\xee*\xeb\xccn\x87Ĉ\\n\xadE\xa7\x06\xff\x90*\x8c\xbc\x9de\xcc\x12\x8d\x8d\xbbS\xa6\xb3\xea4O\x00p\x97\xa9\xf0\xba\xc2D\xa1\xbc1\x97\xed\xa8\xceK\xe4\x18\x8cr\x8b2B\x87\xf3}\xa0\x8a\xd5qj\x89\x9c\x931\x9cƦ/T\xaf\x9b\xa0\r7\xd68\aK\x95YY&\xa5駵\x8e\xbcl\xabW\xedS\xe4J9\x98=\xbc\uf43a4OG\xe7\xfe\x14:\x1c\x97ٝf+\\\xb5\xa6\xaa\x16\x9d*Z8\x14\xdcN\xfbʢ\xa5\fg\x1c^\xe7@\x83\xba$\xf2|%\u007f\xcc-ϦW\x01H\xfeM\xa1\v\x9bVL\x1dR:/Q\xe5J\xd4h\x03{\x1f8\xb2s*dX\x19\x1b\xe0\x9cJ\x975`\xf2\xd8j\xb2[p\x9f\x90k\xdd\xcd&UY\x95\x11\xdab\x93\xd6\xddd`l\xdd&\xad\xc6L\xcfS\x9bTr\x86\x85@\x95\xa5\v\x98t\x1a\x13\x1d\xd6ڞ\xec)\xf6{i\x83E\xab\xe7\xf3\x86ڲ\xb4\xb4Z\xe5w\xd7:\xac\xe10Th\xfe\xcc\x1a\xa5\x1a\t&\xe0!̀\\\x97\xc7V`\x1f)\x93\xe5;\x00^\x81\xa6L1\xfaC\xe6|]\x19ߢ\x91\xc5\xc6\xdc\xf5r.-\x93\xcb\xf88\xa7\xe8\x1be\xcbu\xc7\vJ\xd9|\x05\xedW>R\x84\xde\xd6\x00N\xa3\x90r \x17\xaa8x\xa9A\a\x94\xa9\xb5#\x95\x92b\x00\x84+\x8b<\xae\x1e\x8f\xb1\u007fSfL\x93M\xa26\xe1e-\x98\xde\r!\xfa\xb3d#_\xb0\xb6\x14Ԛ\xc5Q&\xa8\xd4q\xb8\x93\b\xba\xe5qPB\xd0k\x88\xfa\x1d\x91\xc7\x00A\x99\x8d(#\bZq\x82Ɨ!\xbd\xd6\xc7Jp\xbf\x13\xbal\"\xcd\x1f1ײ\xbckI\xf3\x86ZV\xaa\xd0p@\xea\x9d?-\x92=6\x97S\xe6\xf1\x06s\xac\xd0\xe2,\xb6\xa9e:3\xad\x91\xa8eZ5\xaf\xb0\xfb\x14R9+7\x83N\xb99\xdf\xe5In\xf4ۇ\x0e\x1fםX\xba\x1f\xc2\x16gCSٮ嫳lmu\x83\r\xbe\xc2,\x873\xb6\xf6m\xf49z\x1b\xfd\xe3O\xc9PEǰ\x8eB^\xdd\xec\xabr\xf9\xf3\xa4\x1b\xca\xf2\x0e\xe6\x1a\xfd\xa3\x1bF&B\x11^m\xf2\x16c\x0e\xc3 \xcfr\xd04\xe3\xb1s\xcaͅj\x8d\\\x99g1H9\x03T1rFBC\x8dZ\xa3\x930JPh\xca\xcfw\x8c\x1c\x05\xc2\xe5\xe5a\x00n\x99\xd9]b\xd0յ\xd6\x02P5\xb4\x1a\xd0ނ\xec\x95G\xf7\xa3\u007f\xfen\xc1\xd2W\x80\xa3g\xfc\xddk\x17\x0f\xabuʥ\x01C\xd8\xe2\x18?■\xb3ͮ\xb2\f\x1a\xb2|\xdd\xfd\xd4@\xec-\x17^%;\xa9\x95x>\xd0@5\be\xecy\x13A\xccU\x9b9\x89\x01\x93\x1354mƄ\x82Wbp\xd3\\!,\x00\x89\x02\x11G\b\x8f\u007f\x93hD\x1a\"\xdb\xe9\t3!\xc0\n鄛HT\\\x806H8\x93`9L\xb4E5t\xa8\x06V\x13\x85\x1a\\\x91)\xe8\xd9\xed\xaa{`\xb4\xb6{\xe8\xe8\x95\xe3\a\x99\nꔻ\x15\x81@`N\xc0\xb5\xfb\xf6\xe7\x94{\x94\x819\xcd\x01瞞ݷ\xefv5\xe6ٛ:W\x8enY\xaa\x1cu?={\xe5\xe8\xe6%\xea1\xcf4*v\ve\\{z\xf0?gm\xa1\xb1e&\x9c\xd5b+hP\xe2\x8c\xe69B\xc6\xed{\x9c\rO\x8dQ,m\x1b\xbd\x12\xbcճ\xc7U[`l\xea\\5zH\xb7ṽu\xca=\x8a\xc0\x9c`\x80\x14\x84zr\xc7\xe6\xb9\xe4\x8e\xf8\x9f\xab\xe1\xf0X\r~\xb0UӚ\r\x85gv\x8e^5y\xb0#\xafQ(2'}CW\xed\x03\xa3\x15K\x19s륊\xd1O6\xa4\x9f7\x9dՐo\x1b6k\x95\xe8\xb7C\xc4\xcc\x18D\x8d\xa3&PS\xa8\xd9\xd4<\xeaJ\xeaN\xb2\x9f\x13,\x14\\ՅDe\xcePZC1\x11$ӡ\xc4 *r\xe2\u007f\x82\xd11ѽ\xc4c\x81ȅ\x04\x1dOQe\x93\x16\x144}\xa4TB\x90\x86%\"\xac9\x04\x02:\x16\x98\xe9\x10\x9ev̀\xd5\xe1OHn! \u0088\xfb\"B]b\xba\x8d\a\x17\xd0\t\xa2\xecPIH'h\xb7$tl$\x0fg\x1aup;0\x1b\fy\xb9\\#\xd3\xd00\xc2¸iI\x8bq\x83Z\xd7\b\xa5\xb3\xa4!\x17\x84\x80\xb5\x99-z9\x03$\x01Ey\xe1\f(\xafWȬ\f\x03i\xab\x83\xb6\x96\xd4*/c\x19\xd5[4\xa7\f\xba\\6\xb3\x9a\x01\xb4\xc7P\xe4\xe7u\U000396ab\xcf\xfc\f\x9fH53\xc7g=>㯳\xf2\x8f\xa1\x02X\x85N\xdf\x16\x0fo\xdcQ\xee\x195\xfc\x9b\x1a\xa9\\\xca8<\xcc\xd0\a\x06O\xb9n\xb4\xc6\x1d\x90\x83\x9d}\xa7թ\x02N\xc5\x12\x85h\rf\u007f\v ft+\x18\x03x\x8d\xe6\xa42\x83\x93\x8d\xc1\xd9mS4\x90\x81\xcc8\xcb\x13vו2\xe0\x85\n)ѻ\x93\xb3\x1c\xc7\xe8$:(\xa1\xb5Z\x1f\xf41\xb4\x1c\x00\xa5\x11F\xca\xd8\xc8\b\x87\xa4\x04\x82bpB\xa32k\x94\xb4Yc\xc3ÐQ+Ꮏ\xe7\xa4n\xfa\x17#\xfd4\x15w\xc3\xebݩ\u007f\xb9/\xa9\xa3+\x9e\x02kO\xebT=\xf5#\xadʶ\x02N\x86\xa7\x0e=\f\x14;\xfd\x9c\x0e3\xd2\xc93\u007f\xf8Q\xf2\x9d\n@&.\x03\x12֯\x06ɗ/\x99oD\x93\x05{\xe3\f\xf6\x02\xb1\xe9\x1bL\x8d\xc5=a\x05\xb5\x95\xdaM\xddM=I\xf5\xf6\xef\xf4\xf4;\x87eχ,'\xf4\x03\xf1\xedd<\xe7FO\xc4c\xd7\xfdJ\xfc\xffwy^\x04\x16\xf3\xe8@\x16\xd9\xcfL\x92\x03{\xa2\xbci\u05fc\xbe\x9e\xfaɥa\xd8\x13\xeer\xecq\x84SY\x02\xd0\xd1\u007f<\x00\xea\xff.\xbf\xab'\\\x9aJ2\xc9\xc9\xf5\xe7\xbc+\xdf\xe9]>(E\xcd\xdb5\xb9^B\x85K\xc3\xf81\xba\xc2g\x92\xfdՀ\xfabAt\xd1\xd4\xff\xa6\x00\xd8\x0e\xa8\xd2p\x0f\xa2\x887o\xa2C/\xa1Ҳ\x9b\x1aj8\x9e\x03\x16Q\xeb\x05\x0f\x82\x0fQ\xbf\xa3ޢ>\u0094\xd8Y\xa0\x01nP\bj.\xb2\xe3\xd7\xef$Qlw\xdd\u007f\x19\xa7\xff\xcb\xef\xf9[\xfaDž@>\xff\xb7\xd7\xfb\u007f\xf9|\xac\xa0\xacrF\xd4R\xe9=\xe7v\xe0\u007f?$\u007fk\xc1s\aH\r\xf0L\xf4\x9bk\x01꿿\x93\x84\n\xdaN\t\xfb\\\x12|D\x03 g\xbf\xfd\xb5\xe0\xa3\xfd\xc1\x8bC ]\xf9ݭ\xb7~w\x0eS$cw\xe4\xc6T<б\xa1|\xa0\"\x1fQDRMc\x85\b\x9b\xa8\x98jI\xc2d*Y\v\x9fN5\xa5\x9a\xd8\xd3~w\xaa\xd6Q\xefHպ\xfd\x05A\xd8k\xca3\xc1\xde`\xc1$0\t\xae\xfdt1B\b\xa6(_\xa5\x0e%\xb5Z\x90\xd4U\xfah*\\\xaf\x06\x94Tz\x96R\u05cbPy\xf8\xfeRя\xc99\xabh\x9c\xc5\x06\x84\xe7`A\xfa\x1c\xca\xc4\xc9s\xb1d\xc7\x17Ӭb \xfd\x80\x01ဟRX|\xf1\x01\nN\x84j\xc1\x8dh\x01Z\xc0\xbe; \x92'\x86\x0f\xa3\xc1h0{*\xe8A\xb5\xd6Z+\xaaehȦ\x83\x9e`\xae\x0f<\x8a\u007f\xbd\xe6\xb8\x19\xf4\xfar\xc1\xa3\xfe\x9c\xae^P\xbe\xbf\xfb\x81\a\x1eHm˄V\xde\x05\xe4\xfb\xbb\x9f}\xf6\xd9T\x15\xea\xf2WkO\xa8\xd5' \xfe#gm\xb5\x1f\xf4\x04k\xb5O\x83\xeb\xf0\xb1W.\xef\xd5\xd6\x06Q\xf7\xd3\xdaZQ\xa6\x82\xa4\x14\v\xf1{\xcbp\xbb\a\xa9\x02\xaa\x8e\xec\xd6\x1a=4A6\rҘ\u008bB\x8f\x173?\x94\xd8#9\x8f\xc1\x14\xf0Db%>O\xccCxu\x9f'@<\x8f\xe1\x1c\xa1\xc3\xd2>\x0fW\x8a\x008\xdb\xd7\xd9-\x01{\xf4\aj\x96\xeb>\x98\x81\x0e\xff9\x05أW\xbd9\x13\xa6.Yz&\x0e\xc2o\xbe\x82\xfe\b\xacm\x13\x9eC}\xe8s\xd81\xf6\x8ae5\a\x97\\Z|犩\x87\x9f]\v\xe5\x8dC\xc0-`\xe7\x86\xe4\xfe\xdb.\u007f\xb3\xfa*\xc5\xd0\xe2\xc5\n\xc44\xcd\x035\xe8\xf7\xe7K\xc1\xd0\xf5}_.]|[NIw\xd9\xf0\x1c\x1dz\xfe\xa9\xce\xc9\xe8\x91\xe3\x8b\xe7d\xb5\f\x92\x1b6?rp\xe3\xd6\xfd\xbf\xf3\x86\xc1%\xabK끼5\xc3kq\x19\x9c\xfb\x10Ag\xed\xf7Z \xec\xc1\x9a3\xfag!B\x99\x83\x01\bE\t\x03\xe5\x03\xc2\x1cR\x88Ǖ\xa0>C\x80l)I\xc1\xb5\xaf]{\xedk\xa9m;\xe6\xd8\xedsZ\xeb\xdc\xee=-\xc6\x0eC\xd6\xf2\xc1s\xe8\xb7\x1f[\xb7\xfe\xb1\xc7֯{l\x17\xfa\xe1\b\x1a\xa6|~\U000ea9ed\xff\x00[\x86OV\x99\bƀ\xe2\x99#@\xc1\xb8I\xfdk\xcf<\xf7\xf6\x0eI\x8e{wKk\xad[\xea\x91V\x0e\xa5?Z\xf7\x18\xae\xff\xe8\xa3\xeb\x9fE?\xa2\xdfoxtϥ\x13\xc1\x03\xb7\x16A\xb0\xfb\x19 E?P\xe7\xf1\x8eR\xfc>\rTk\x1a\t\x80l\x9fR\"7(\x98/\xc7\xf1C\xc7\xcfm\x84Ue\x18\x8f@$\xfd\x9d8\x9a\xbc} \xb3\xbf,\xb6\ta\x0e\xdf[ҳxq\x0f\xd2^\xdaQ:\xd9ZRP\xb9\xd2j\x89Vu\x98\f\x1dt\x9f\xf8%\x0e\x1an\x982\xe7f9\x18\xbf\xebر]7\xfe\x11~,\xe3\x87U\xa3\xbf\x88\x1f\xe8\xa7\xed\xafn\xdb6c\xe66:\xbbg\xf1\x92\xe1\xed\x8bѫ\a\x96\x96\x17\x19\f\xf8\x1a\x95+-\x1e\x16.\x14?\xe6M\x83&\xae\xbcfv߱\x9d\xbb\x8e\xbds#z\x0e\x04V\x80wq:꙱m۫۷\x11\xb4\xf1\xb3c$_\xb1g)\x15\xee\x97\xf9\x98O\x1e&\xa0&\xd1\\@\x10\xbeb\x06\xcad\xc7\x1c3\xad\x014\xd1n\x8d'B\x80X\x1b\x01̡\xd1\x9a\xb4\xdb\xdb1\xa8R\xa7\x03;\xddq\xa5\"\x04\x16\xa1\xebLN\xba,`/m\xf6O䔰\x1cm\x998\xe4\xfa\xb9\xa3\x8cF0\xd3V\xa9\xd3\xd7\\6&\xf5\x19\xba\xc9\xe9\xa3\x19\x8e\xdd\x0f\x16\x81y\x0fhM&\xfa\xd1\x1at\xcd3J0\xc3\xed`\xa0\xc1\x94g\x8d\xa3\x97\xd0\xce@\x9b\xcf\xe05\x99\xe4zz\bX\xf0\u0097#\xd1Ն1\xe3o\x9eԠR\x01ڮ\xd1T\x89}\xa4V*\xf6y\xb2\xaf\xdbp\x0e-\x82\xf7\xe0\xd6\"D$ן2\xd0pԓ1 \xcd8\x12\xc1\xedG\xba\x87\x99\xa80\x80\x13\x937O\x9e\xbcy#\xfd\xf3xh\x91\xa5(\x99\x05\xb2\xb4\x90\x84\xf4\xea\xae\xee\x9e\xee>\n\x1f\xba\xd4\xfaM\x93\x1cs\xcdwL\xa3\xa9iw\x98\xe7:&m\x02\xebH\xa1\xc9\xe0\x04\x98)\xe5yi\xca*F)\x84I\xf6$q\xbd\x99\x14\x8f\x98\x9eK\xe2\xd2wN^\xbf~2\x9a\xb4I\xb4\xab\x95\x92\xe96JU`>\xbeu\x00\xaf\xf6\xbf<\xb0\x88\xb3\xecI{\xc42\xf3\x19\xbbYp\xee\xdd\xd3)\\֤M\x17}\xf4\xa4\x88\x8a\x97$/p\xea\xb4\xf8\xb83\x06\xbc7\xe3\x11\xd2`r\xd3$\xf2\x12\xb5\xe4\xf1k\xc5㹗8AȬ\x13\xe4UP\x96\xd0L`\xa3\xd8\x00}\xcf\bQL\x0fda\x1e\xe5\x84\xf0~\x94\x9f\fTW\x06\xeb\x8fl\x02\x11\xf7i\t\xf2f\xfdGџ0Q\"\x14\x8f쉠\rE\x80\xdcoE\xbdV\xbf\x1c\xa0\x88-ȃ\x1d\x9f\bǗ\xc81I`\xe1\x93|\xd0\xf6\x12\u0601\x8f\x9f\x80\x1d\x9d%Aݶ\xa0\xd5\xe7\xb3\x06\xb7\xe9\x828\xf7\x86\xfeC\x92\xe7\x11\xae\x10D\v\x85À\xb9\xc6H\xe5R\x8d\x82.L\x1a4I\x9c\xe5\xd3f\xd8\xf1\x04N\xf5\fH\xcd\x12Ry\x9c\xea\x17\xf6\x13\xfbK3\x82{>0P5m\xb6\xeb\xf7h\xcb\xcd9v\x13\x9b\xb5y\xd1\xdf\xee\xe7ռ\xa3\xcb\xf7%\xfa\xc3M\xbb\x8a|Vεz\x030\xbfcQ[}\v\xc2\xebУ\x0f\xbf\xd1cvg\xbb\x15\xce-\x0f\xee\x03\xf9\xb3\x8d\xbc3\xf7\xcd\v\xe1盲\xf8\xa5^Y\xae\xc1)\xb5\xcfVؿ\b\x1b\xb7娢V\x9fԳV\xe5\x03\xbaB\xf3\xd0a\x85\\\xc0\xe5Α\x06\x1a\xab\x94\xd9\x13.\x10\x06\x01ї-\xfe&<\xa1\x86\x89_6\x8e\xe60\x8f\x1d¡\x04\x9f\xf00\x14z\xc7\x02̈\xcd\xdb\xeeB\xc7@\xa1\x05}\n\xce\xe00\xc8g\xdeI=\xedFS]\xe8+\x17(\x84\x83]`\x9f\v\xe8\\x\xec\xe9\xf0\xef\x1a\x19\xc5\\J\xa9\xf1\nK<\xdaWRC\xa8Q\xd44j:\xb5\x18s\xa4ۨ\xeb\xa8ۨ\x83T/\xf5.\xf1\xb6Ez\xa9\x97\x18\x8d\x92\x19\x1bGq3\x92\xb6\xe5h\x839\xe3< Fv\a\xbd\x85Ķ7a&\x8a8\xb1P\xa2\x04\xcf\xf6\xb4\x993\xf8\x84\xf4(\xa6\xd9\xcfe\xb8ӊ;8\x82sd\x80\xe7\f\x82g$\xe2\"ٔ\xb80&FD\xbb\xf02@\x93l\xb2\x06\xf2D\x8ci\xee\x8faz\xd5\xc4s\xc5B\f\xf2\xb1x\xda\x18_\xc0o\x16\xa8:\x92@\tB\nZ\x8bIH\x95\\\xa6V\xab\x81Jf\x029\n\xa5J\xaa\x95\xaa\x80\\!\x91\xa9\x152ٙ/\f\x06\xa8\x86:\x1dT\x8f\xb3٠Tf6ˤ\xc0v\xc4jUȡ\xd1\b\xe5\x8a\xc9f3T\xaa\x8cF\x95\xb2\v\xc7\xd5\x12\x99\xc1 \x93\xa8\xc1\x06\xf4\x91\xd1(\xe7\xb4\x10\xf3KZN>\x99\xe7\x15R\x1c\xc2q\xa9b\x1aN3\xf08\xa2\x92ʔ\xe0ʗ5\x1a\rf\t\xd4j\x8dA3]\xad֚\xb4@\xa9\x04Z\x93\xe6Oj\xbdM\x0f$\x12%\x94\xcb\x14RN\r\x99Y\a\x96\xf5\xfd[\xa5w\x8c\xeez\x01\xb8t\xb1\xb2e\a\xf6\u007f\x03\x15r\xb5Z\x9e\xfa\xe1\x1b\xb9\xaa\xe4\x18l\xd6JYV\xaa\x95\xa4\x9e\x05\x9f\x039\xa7\x90q*\xb0 \xb9N&[\x97\x945\xbd\xf5\xbaL\xfe\xda[2<2?\xff\xe1K\x85\xe2\xcb\x1f\x94l\xdf\xf7*\xd5\xf7}*\xf7g?je\u070f\x9fId\xc8\x04\x17\xa2\xcd?r\n\xfd\x8f`\xad^1\x1c\xe5}/U\xf0߃wyE\x16\x92|k4~\vN\xcbT\xaa\x94\x0e~\x86\xe0Wr\x8dZ\xf1\x15@\n\xb5څ\f_(\xb4Z\xc5\x17\xe0\v\xa5V\x8b\xa4\xffT\xe9\xf5\xaa%\xcb\xe0ZZ#\xe3X\xa9>u㲻\xa0^Eo2˽\xe8T\xaf\xe9\x00\x95\xc1'\xa0\x04\x1f\xc6v\x01\x81\x94\xa2\xb2\xfc\t<Ր\x1d\xfa*`\xfa\xdfc\x8c\x00N-FK\xe2\x90\a\uf07d+\x8e\xa2\xdbP\x17\xba\xed\xe8\n\xb0\xf7W\xe2\x87A\x0f\x98v4\x13?JScF\xdd'\xeac\xdc7\xaa\xef\xbe\x01\x11\x903 \xc2\xe4\xe0SR\x8c\xe1Ӏ\xfd\\\x9e\xb2Q>j2\x1e;\x97ⱳ\x15\xcfI\xbfܯ3s:\x0f\xf1\xa7,([\x13\x11.\x10\xa4ed\x13W\xc2\x19\xc5=s\x0e\n~\xfb\x88=; \xd6!F\xb2\aKl\x0e*`D\xb0\xbfǯ\x8d\x0f\x98\xb2P\x03 1\xe3I\x8e\x98\xbc\xc7\U0003f401\xa3I\xd1\x10\xb9\x8a\x84\r\xfaȘ,a\x8f8\xc2\xfd\x00\xca\xc9p\x97c3X)W\xa2W\x94`:\xb15KQ\x10y\xa2\x15\xe57\xb8\xb4j\b$uE\x97\xd7|p\xffM\xe35*\v`\xe5\x8cl\xf2h\xb5\f\x96$\x1a\xfd\x16\x95J\xe16\x02\xb3R/#\xc6\xf0\xca\x04\xb2\x97\x8c\x8e\x0e\x05\x1b4*\xfc8\x02B\x85\x12\xacݺ\x13\x9aؖ\xa8\xbd\xd4\x05WX.m)R3\xccfa\x8b-\x03\xc3\x1cv4\xa2+\x9cJP\xa6<\xadg(b\xd0v\x9a\x82#l.\xae\u0604\x99+\x00\x82a\x8f\xa5\x02\x9d攀\x91\xdb³\xf3e\x1a\bGw_\xb1\xae\xe3\x96HXc,\x94@\x9au\xad\x19\xb4\x1f\xd9-\x97\x87\xc7ѫs:\xb9\x00\x1df\x18\x80\xeb\x9ap{\xa4\xe6\xc6\xed\x98(nX8fQ\xa9\xc2\xe2\x00\x80:\xaf\x9f\x89\xdfh\xd4o\xfb6\xbc\x91\x00\x1a\xe3֏E\xc9\xe6:\x0e\v\x90~\xb4D\x03|%\x05\xc45\x1b\x01V'\xb4\x9d\x0f\xb78\x1d\x8d\xfdjK\xcfmڿ/\xc9ѐ\xa1\x01K'\xf7\xedoB\xefvNg!d\xf0\xd3K\xe0uK\xae\x83,`\x18\b\xd9靿\xa1\xd9\xe8\xe4\xfc\xd4|\xf0\x89\xc1\xa6\x95Zh\xaf\f\xd9\xe1\xce\xf9\xf3Q\xb3\xc1f$\xcev\xd9,\x19\xf4\xa4>\x92\xb9%F\xa3\xcd\x00\x9e\x98\xff\xcbv\x18\xf9\xdbځ\x98\x02\xf8\b\xa8'\x91\x06C7\xf0\x918-6\x86\x00\xe1F\xc4\r\x85@\x88\xf3\xf4\xaf6\x02\xc8\a\xd6a\xb3Y9\x8b_\x9a\x81,G\xcfo\x01\xbe\xc6\xde\x17\x1aЧͳ\x19%\x8d{\x17#Q\xcckA\x1f6>\xfb\xfcoh\x86\xcf\xe6ͻ\x9d㥌\x84\xe1d\xcc\xed\xf3\xe6\x01\x1d\xb0͟\xbf\x8f\xe3\x19\x1a_G\xb9\x0f\xb7\xc9\xd7蓌\x8e\xcc\xc0\xf7/\x15t\x81\u007fk\v`\x8eR\xf4Ӎ)\r\x82\xec\b|:2r\t\xd8\u2bffs\x16\x18<\xe9ʖ\x9c\x86\xe1\xcd5E\x1d躉\x80]\xb1\xb2\xc4]Z\xed\xfem/x\xb7Ɯ\xec\x18\xb1\xd2\xce\xcfO\xfd\tX\x80R\xef\xe9\x18\xef\xd6\\\xec\x9dr\xa8\xc8o\x9cyt\x9eX\xc2\f\x18Q]\xca\xf0\xab\xaf\xc0$\xfb\xa8^\xb2\xf9\xd1\xdeӍi\xd2\xdf\xf0ܠ\x17\xf5\xf6\x92*\xc9nR\x85 gf\x9e5\xb3/C\x9e7A5\v(\xeb1\x9f\x91\x8d\xf9\x9c\xe9\xb3\xf1\xd7\xdf\xc1G\xc0\xc5u@\xb0\x10\x16\xb4\xa0\xe3|,J\x9c$\xc24\x19\r\x93DI\x90\xfc\xe8\xca\xff\xf5\xed\x92ID\xc1m\xf3\xa5\xd7\u007fx\xbd\xd48=9\xdc\xe4=\"\xf8zc\x92\x03\xfe\xc0\xaf\xbdq2\x89\xa7\xb2wНv\xebȅ\vGZ\xed5\xa05\x99\xb4!\x9b\xe0\x9f\xb1_\xe7u\xc0\xb7*\xa3Z\x04m\xb6ߴN\x183^#\xfb\x1d7$\xe2\x04\xe8Q\x1b\x12\x91\xd5LZ\x01u%\x14!^A\v\x00I1\b)\xbf\xde91\x91C|G\x1e\xd8D\x18\x83M\a\xb4\xe0\x90\x9b߰A\x1b7\x18Y\u074c\x19:֨\u007f\xd6n\x18;V\x1f\x0fB\xbe\xa4\x84\x87\xbc\xe1\xb7\xccN\x05RS\xea\x04q%y\xb7\xb0o|\xb7&5ز\x0f\xec\xd9g\x94\xe8t1\xe3\x1a\xf4\xfc\x1acL\xab\xb9\xd10\xa9o\x12\x0f\xfd1Cٍe\x86\x98^w\x91>\x1d\xfd\xad\xe3\xf4½!6\xd3j\x02\x1af4\xf2\xebK\xa1\xe0\x85\x18\tGz\x01i\x16\xb5\f\xfd\x04d\xb2ߴ\x8e\xd1\xc9L]\x80\x8f\x10\xbf\u007f/y\u007f \xef\x04r\xd9E\xbe\u007f\x82\x1aF\xf0\x93~ӛU\x13\xdbQ@\xb4߉\x85\xa9`\xbe\xe21q\xb4\xe0\xb7\b\x10Uwb\xbe\x88\xa9\\L(\xf0bY\x92\x19\xfa\xf5\x8f\xdf%\xb5)\xa2\nZ\xfa\xc4\x13R\x1a\alҿ\xa9\xf1˪\xd5\u007f\xbb0\x1d-Wi\xe0UФ\xaaI\x9f\u007fS\x8b\xe0+\x04\xf1\x95\xbe\xfb\x0e_!\x88\xaf\x04\xf2y\xfc\x87\x8e]\x98\x9e\x92\xe0+\xd2\xe4\xd2r\x1c\xe8\xfb=\x0e`\x9e'tv7{\x1c\xb7\x17\xd1\xd0\xc5\xe4\x91\x04\x8a\x8e}\xe4\x98\xeb1\xd9\b\xed\x94\b\xf6{\\ǃ\x80\xa8$\r\xdc\xeec\x8fϜZ\xf7\x87;\n\xdb;\x1cusg,\xed\x1ak\av۸U\xab\x87\u07fb|\xfb\x1do\x1fz\xf4\xb9r\xce\xdaPQ\xa7w\x97Gb\xb5\u007f\xbc\xa3\x1a\xbe\xf4\xb2\xf9\n\xf4\xed\xed\xb6\xfc\"]lɵ\x1f\x03\x0e\\\xf2\xd6{h7\xfa\xea\xe5\xae{\xbf\x1c\x02\u0087{\u007f8ֻo=`\x94\xa1\xac\xd9#\xc6vN\x9f\xf0\xf4_\xd22}N\x9c\xd7$\x94\x1csSz̙Z\t6\x00\x0ft\x016\x11\x92\x81@f\xc3\x19\xf3n:6\x80i\x14\x9d!\xedT\x8c\xb0$\"\v\xfdW8\x01=\x8a\x1e\xff\xfd\xef\xe9(\x0e}\x87\x1em\x05Z\xbcx}}5hK\xddż\xf9{\xf48P\xa5\ue8a3\u07be7\x8dyƾ7\xbd^:\x8a\x038\x01,B\x97\x80\xd9\x1f\xf97l\xe8{\x1f\xec8\xf4\xd1\xe5O<\xf1Ĥ\x8f\xc0lt\t\xfaj\x03\x80\xfeC`\a\xba)7\xf5a\xb69\xf5\xa1J\x05\xbd\xe6l\xe8\xcd6C/\xa6\xe4?4g\xf0Z\xf1\x8b\xb0+q\xbf\x1c+\xf6Ia\xd7\xce\xe7Ʌ\x82\x84\xa3\x1f\xc0\x83\xe8\xdd\xebq&\x10\x98g\xa2\xad\x90\xc1\vw\xb1\xd1\xf4.\x1e\x97\xd1\x01\xf3yE\xafZ\xd2EW~q7\xa3\xa1\xcf\f\x06\x90\xbd\xef\x8bK&*\xf7/\x9b\xd2:\f\x84\x1e;\x00,w\x82\xd3oܳ\xf6\xca\xd9\xda\x1aeCk\xa2\xb55\x967\xa2\xaen\xe8\x88\xc5u\xab\xee\xbeg͵\xd3&շ\x94\xb47\x97\xe5\x0e\xaf\xab\x1fڱ\xa8f\xf5}\xb0\xaf\xe0\x95\xd5\xfb?\x05\xf2\u007f\xdeu\xc9\xd3\xf1P\xee\xd2;\xcao>r;\xfa\xe2N\x89\x05}\xbdz\xfbt\xc3Pu]C<֘\xd3\xd8\xd1јs\xed\x8aUۧ.\xa8\xad\x8f\x96\r\x12\x13\xb6\x9do\u007f bo\x12\xab\x9a\x04\xe1?\xce7\x1a\xf0g\xe1W\x89\x98\x13 \x11,I\x84$Z*\v\x1f\xbd!N\x9f\x15\x17|˲f<\x01s&\x03|헪\xff\xb0\x17m\xbe\xff\xf9\x8e\xfb:\x9e?\xf3\xcd\xf3\x0e\xc7\xf3\x9d\xb0\x1e\xac\x15\x13^K\xbb\x8a\xa5g<\xdf\xd9\xf9\xbcCB]DSX\xddI*᪤\xc2\xfdhs\xea9!\x01\x04?\x16+K\x9f\xbf_\xbc\x9c\xb0_\x93%9\xc1\xfe\x85\xa0@\x80s\nNz\xa2\xccO\x11|\x82\xacj\xb2\xe5\x1f\x8a\x99\x18\xbd\xe4ĕ\xffD\xbd\xa8\a\xf5\xfe\xf3\xca\xe7A\xfb\xd1\x0f\xd0\ai\xbf\xb6\xb3\xd0\a\x1f\x1c\x05\xed\xcf\xc3\xe4\xc3$\xf3\xca\u007f\x82ڇ\xff\x04\x96~\xed>\x99\x8fz\xfe\xb1Qtc\xbb\xf1\x1f\xa0+\xff\xa4\xfbk\xb4\x8d\xe8\x84\xf3x>\xfb7n\xc3鸧\xc7\xf5\x89H1\x1e\x85\x8c\xa0L\"\x18\xb0\x03b\xe6N65\x13\xc4|#.h\x03\x11\x82\x91d\n\x01\xb5`\x15/\x1a\xbb\x170\x98뉚\x8a]R\xb3>\xad[\xceK\xff\xfa\x12\v\xa4\xe1\xdaR\x0f;tHdNk\xb5V\x1brh\xec*\xb5<;?G\xad\x9a\x13j3\xf0 d4\xdc\xde\xe3\tьi\xb8\xc31;\xaf\x83\xe7\xdd^C\xa1g\xfc\x88\xc1&c\xe5P\v\x93\x95S\x9c\xadV\xa99y8\u007fxqcn\x91\x83\a\xf4\x87蒳\x87ѡϷ\xc0]\xc7\xc1j^\xb0\xd8\xeb\t\f\xd6閪\x878\x9d\xa5\xb7\x1c\xae\xcdw\x1b<:ml튵ݳGV\xe9t*\xda魏\xb47Ϛ\xb3q0J\xa1\x19\xff\xb8\xf1g\xd0!\xd2=B_Sb>7L\xb5S\x93\xa8\x05\xd4*\xeaJ\xea&\xe2o#\xe8'\x9e\x13\xf0\u007f\xcc\xd4q\xf8\x18\xd4&\xcc\x12\x8e\xa8]\x13+F.\x16O\x84\xe2\ts\x9c\xe6\x88!\x97\x84\xa8\xee\x98q\x17L\x04CDk\x9btK\x92\x8b\x8f\x11|\x01|\x19\xbc\xa2\xdc4c\xceLzbU\xc7\xf5[\xc1\x9b\xaf)\xe5\xb9\xd9\xeb\x1f3K\x83!w\xb6\xd9\xe8\xca\x1fY\x86\u07b6\x96\xcdo\xbe\xab\x92\xc9\x1e\xbd\xd0\xc1X\xee\x1dq\xf5\xe1¾\xe7\xf2\xc7é\x93\xbd\x9e\t\xa9[\xc6?\xf2b(\\\xd95\xae\x02La\xa0乖\xb8/{\xeds\f\xbaa\x13\xa3\xbet\xec\xd8\xf2\x8aq\xd4/\xfcRˀ\x8fƓ\a\xed\x03\xba\xe8/\xec=\xb2\x81\xbc\xfbV\x8b!疕\x80\x9b\t\xffr\x9eR\xba\x01|\x87\xbbB\xdeDP\x8axt\x84\xbe\xea|߳eg)\xe6\x15\xfc\x8d\x9c\x02V\x90\b\x0e\xc6A\"\x01#\xdb^A\x11\xb9\x91\x98\xa4\x10\vq\x01\x1bF\x80\x9d$ڻ\"\xb0\x10\xd9d\x16\xc0\x8f\x89b\x05&B\xe8\xe6%\xc3+\xa3ձ\x9f\xf2\x81\xdd\xc8\xe2a\xa26\x06\x9b\x1a\xc3U\x83\xb5\x8b{\xc0\xbf\xf7\xa2\xefn\xabm0\x9aY\xd6o\x8c\x96M}4\xd9Ғ|\xf4y|*\x91\xab\x82\xd9\xf2\xdaI{\xff\xba\xfc6\xa0b\f=\x8b}\r\xc3\xd16d1y\xa0ݰ\xee\xbb\xdf=\xbe\xb1\xb2s\x98/\xa7}q\x01\x1e\xd8\xdf\xefU\xb3\x01|gF\x95\xae\x8eOS\x97\xcc1\x84\rj~\xcd\xf6\x15\u007f\xdd;q/^\a\xf5\xe9u\x90 5\xa7\x15e\x13\x04Z\x84XnK\xdcDk\x9d\x8cc`LSU\x04\x85\xd2\xc7\x11xM\xb3\x88֔v)#(\xda\xe2\xde&:\x96!\xfb\xe9\x02P\f\x11U\x88\x8d\x14\xd3\x02\xb5Ԥ\x02:\xf5\xe1ˮ>\xbceKqGe\xc4\xeb6(ABO3\xadcC~\x99QgTh\x01&\xb2*\x86\x1aF&\xa4\x90ak\xff\x1d[:\xa2V#U\xd7J\xb3\x1f\xe8\xf05.\x1fUgp+*\f\x8c\x1c¢\x95*\x96\x91\xea\x87f\x03\x86\xa1\xcd\xf0=\xdec(ך\xaa\x95W\x83\xdc\xca\xfa\x841^\xde\xd64\xbd\xbd\x9c\x1d٠.Q\x02\x96\x05K\xfe\xb0 w\x89ƐetC\xc0\xdc<\xc8\x10(\xc8a,\x92\xa9z\x13\xcfB\x06\x80\xfc0\xad\xb1\xc5\x03\xe1\x90\x13\x9a\x00\x84\x90V<[M\x1b\xb2\x1b\x18\x19\x88\x17\x00>CwUc:\xf3y\x01'܃i\xe4\xa1\x02\x86\xec9\xa2}\xa0\xa8\x1b^<\x19\xe0 C\xfa\x8308C\\\xc2OPE\b\xb2\x1c\xd1^1\x8b\xa0sZ\x81R5\xc1\xc6Hvn}}n6m\x8d\x86\xed\xf9\xf9\xf6p\xf4\x8bb1\x05\x1e,\t\x91\x94P\t\xfa\xd1\x1d\xba\x17\x9d\xbc\xd3\xec\xf3؊\xaa\xed\x1d\xb2\xd4\x10\xf4\xe1\v\xa0\xf5\xa5\x87A\xd91\xb8\xe8\xcae\x89Wv5\x92\x02w\x02ǽ\xb7\x03\xc7\xfd\x8c\xbc#\x12\r\x87\xa2h\x8a#/\xdf\xee\xc8\xcf\x03_]\x98p\x1fs3:\xb5\xb7\xad\x99\xa6\xe5\x8c\x0e\xae\u007f\xefu\xe0\xbe\x178\xee\xdc\xfci\xaafٟ\xc6>\xbe0\xb0\xed[\xe0\xfav۶\xefD\xfc\x12\xc9Y\xdc4\xae\xb4\xafa\x81g\r\xd0\"DR\f\xf3\f\x049K\xc0v\x90\x9c\xf4H\xceR\xac]\xadS\xa8Pŷz\xb7Jƛ\xe9\xae3\xc7в\x00\r\xbd\x92\xa4\x06\xaf\b?X§)\xa7V\xca\x1eF\xc7\xcd\f\xe71\x80I\x8c\xafo\xfa\x1d\xea\xec0O\xf7\xca\xce\xe1%\x9ce\u007f\u009ch\xd6yw\x05\x99\xbb\xa6\xef\tx\xc0\xca\xc0\xc0\xfb\xa6\xbeA\u007f\xd6;\xd52ބ\xc2\x01\x9a\xf6I\x92>\xf4\xfa\a\xa7g\x81vz\n\xf2\x9e\xbb\xfb_\xd0a\xa3p\xf7\x17\u007f\xaf\xce\x0e\x19\xe8^\xe3i5\x9b\xdb\xf7ҕp}\xdf\xdfϛwJ\x849\x81\xd0\x1f\xf8ˉ\xbclԔV\xdd\x174\xfa\xf1W5q\x99\x99H\x80\v\x16>.{\xbeC[\xd1|_B\xad>\x8aN\xee=\x88^[\xc8\x01\xe9\x95r\x8d\x96\x1b\xfa\xee\x8a9\xcf^5b\xc4U\xcfΙv\xa8\xe9J\xe2\x8e\x1a\xd5ڂ\xe1\x90k\xe3|\xc0߰\x178\x8e\xa6Ng\x94\xf7N\bJh\xb4\x03\xbdJ\xb0\xb9\xae\xdf,\xb7J\xaf\x92A\xf9\x949\xb8\xfa\xdb\xf8*\x83\xeb\xafr\x85\xc2D\x97\x90x\xe6\xde0s\xd1\xea\xa3{P\xbf6_WF\u007f\xed\x9c\xfe\x8a\x9d\xf0\x15j\xa8\x15\xe8pm\x018Ϛl#\xea\x13)k\x81\x04\x9fu?\xb8\xfe\x02\xc1!K\xe1́\x85Г\xbf\x90\rV\xe3{=\x8f\xef\xb5\x05ӓi\xed3a\x96\xc43\b\x11\xd3\t`\x84F\xda`v\xd1i\xaen`\x89\x10n7\x82<\f2n\x9f\xf0\b\x13\xb87\xa2un\xe4\x89h\xcfC\xe6\"\xbe$T\x00/^B\xb8\xaedG\xde#\xf9y\x0f\xe7Yl\u07bcr\xad\a\x00U 5)\xa8\x02 \xa0\xad\x8d\x84\xad\x96\xc2\xc3\x05\xb9\xf7嘭\xee\xec\xb8\xc6C\xb0/Y\xa9Z\xa6\xa9,\xf0[,\x05\x87\vr\xeeͱZ\xbd\xb9\xa5\x1a\x1f\xaeh\x83\xcfXqE\x9f~D\xd4jŗ\xcc=\x98k\xb5\xfa\xf2\xcbq\xa6W[Y\xe8\xb7$9.\xdb\xeav1r\xb9q\x05\xd8j\x943\x8c܈\xb6m7\xc9%\xc0\xe9\xb6\xe5q\\\x8e\xc5\xe5b\xe5r\xf3\xca2:\x9f.\xb0G\xbc!\x8bD\xce8\x84\xbc<\x9b\xcb\x0e%r\xe3ըר\xa0i\x85\x11\xd4^\x8d\x03\xe6`:\xd3\x01X\xb9\xf9\xaa\xbe\x11+\x8cr\x0e:]\xb6<\x01c\xc8r6\xc9 \xdc\xc6yi\xfc\b\xc1\xfc䜂\xb6\xaf?D\x94\xefE;\xe1x6\xc1\xbb@\x01K\x84\xb1Ih\xbfu\x81\xd5\u007f\xad϶\xc0\xe6\xbbaں\xfa\xdaq\xe3V-\x02\x11\xf0\x91\xd5\xcf6\fu\xd6\x02\x89U\x11;\x93\xb4\xfa\xfdV\xe6\xf93\xd5\xe4\f\xbeV\x16\x96\xafZ\xb6\xfd\xc0\xca\xe5\xd9\x01\xbf\xc0G\x90>E\r\xf0;B4\x88\x1b\xa8\xc1\x98\xda1zb\x81_h\n{b\xbc\xd1\x17#g\xfa¼\v\xf7\xcap9\xe2\xa6\x12t\xa1\x1e(\xb8\xd7J\xe3\xba\xf5\xf4\xf5\x9c8!\xa1RY'\xce%\xd2\xc9saX{\xe2D_\x0f\xd9!\x1d\x00\"\x17\x048\x0e\xa9d\xb2\x0f\xff\x98\xf3r\x1050\x96.&ʷӾ\xe9\x896\x05\xf1\x1e\x82ې\xe0\xec\xe1\x99\x1c\xaf\xa3\x01\xd29\xb3p:\x9e\x9dX\xcc\t\xb1q\xa6w\xcb3Ϡ\x1f\x9f\x81h\xcf\xc4u8\xb8e\xddD0\a\x12\xb87\x12D{ \x04s&B\x8a\x14yf\x8b\xd2th\f\xc9\x1asȤ\x14\xab\xe1\x90\x05'\x9e7V\x03T\x8c\xa2\xfc\xa2\rl\x1c\xb3L\xa6\xa8\xb8\x95\x8c\x97\x1a.\xe3\x1c/!\x18\xc4\xfe\u0094\x8f\xa5.\x1b7\xaa\xea\x1b\b\xbf\xa9\x1a5\xee\xb2\xcb\x1e^\a\xbf\xa9\x1e\x89\x03\xe3FV\u007f\x03\xd7=\f.\x1bH*\xa5\x1e^W\xbeR\xab֮,_\xf70.\xc2iW\x96]\xf6\xf0ee+\xb5ܸ\xcb\xe8\x13\x03\xe9&\xae\x9fw\xd4\xe1o]M\xb5P\xe3\xa8\x19\x98{\xa0(a\xdbW\xd8\xe1\x15\x04\x13\x8980\x13\x9c=\x8d\x80\x80p\x8e\x91\x8b\x12\\\xf5\x88\x1b\xf0\xc2\xe6qZkք\x97\u0381\xb1\xb8\xd8w\x85\xf93\x94V]\x11\xa4\xea\"\xb6K\x89\b\x8df\x80\x83\fE\xd6\x05\a\xf2\xe4\x06\xabJ\x91\xa3\xf7n\x18e\xa5\x9f*\xf8\xbe\x91\xe7k\xc7\x13\xdcT\xf47\x02\xcb*\xc0\xa9>q{-\x1f\xe3\x1b\xcfȕ*\xf9\x04\x99Ln\x93w\xca\xdfWX\x14\x9dr\xb9\xcc.\x9b \xcbҫ\x05\xe0\x93.\xf5\x83z\x87\x1e\xff\xdf=\x81\x14\x95\xe3b6\xb9\x8c\xbe9b\x90\xe7\x1dX`-\x92\xb3\xe1Q\x1b\xbc\n\xf0@\xc1w\x8d\xf8\x82\xb5\xb7?qm\xe6\x1e\xc0Ep_\xc7\xd7\xf2|#\xc8KW\xc4W\xb6\u007f%\x1ceB\xca3µ{ҷ\xd2\xeb\ae\ue3df(\x8dK@ږ\xa1\f\xe4˃\x00K{\xe0\x05[@ Ǹys0df\x03\t\t\x97\xe0\x89Q\xb09\xc1\xf2\x9c)\x92\b\xf1\x018\x15\xb8\x81{!\xba\x95\xfd\xe5\x1e\x10\xb3p笯k.\xdf\xf5U\f}\x8c>\x8e}\xb5kk\xf5׳v\xba@\xd3\u0557.\xfbq٥W\x83&\xf8\xf6\xdbo\xa3\x87\x99\xe4E\x18\xdc3C^?C\x8f?\x01\x1a\x94G[\xd6\xee۷\xb6\xe5\xa8\x12={b<}\xe6\xf5\xcda\xf4\xe7A\xa1\xd0 \x90\x13\xa6\x04\xdfui\xff\xd0\x19\x9b\x82\xa1\x82\xd7\x10\xb2\xc3p\a\xf5(u\x84\xcc\x0e\x19\xcf\xd5iW\xee\x17\xc4\xc1\xaf\xe4\a2JM\xbe_+\xf9\xeb\xf9\x9eX\t\xcb\b\xc0\x0e\xd5\f^\x01]\x8c\xee\x82\"\xba~ǡ@\xf4\x12)\xba\x8a<\x17\x84\xb5\x17MN=\xef\bB\x18\xb4ó\xffM-\x90L!\xb4\x11mL!]\xb4}\xdbc@\x05\xaa\x81\xf2ж\xf6\xa8\xee\\\x99\xa0\x1d%\xed\xc1\x13\xfd:\xf0\x03\xbc\x8b\xa2%\x17K\xdd\x11\xb4o\xd8`\x0f\xa6\xfe\x8b*\xe0*\x95|\x0e\x043\xe5*]I˰\xd6\xf2@\xa0\xbcuXK\t\x1a{\xae\xc4(|I|\xe1~\xb9_\x1a\x17\xc1 h\uf525q\xc0\xfa\xe7%\x9e \x1a\x11A_&A\x10%D̠\x1fڍ\xed\x0f\xc1ޠ-hCxB>\xc5Y\xe0\xbf\b\xbc\xad\x18\xc53\xf9=\x16\xae\xef8\x81:\x02Y\x04\xec7\x13bzS8?%,\x15\x90\xa2\xe7\x9aS\xb5\xb0\xb7/\x89ҋ\x02^$(3H\xa4ݝ\x93\xa3H\xe7\n\xcf\xec$\x14\xa7\x81#\xdaBL\b\xe0\x05*\xa8\xaf\x01f@\x04\x91\x9cp\x96\xfcO \x80\x16\xed\xea\xb9\x13U\x1cF\xbb\x1e\a\xf3\xd6\x16\xdeٳ\v\\\x17\x9c\xd7\x1c@ݟ\x81\xeb\x83\xf3\x98\x8a\xe0\xdc \xea\xc6e\n\xd7\nE\x0e\x83\x97H\x99\xeb\x03\xcd\xf3q\xdd\xcf\xc0u\x01A\xf6o=\xab\x94\xfcS\xf0\xdbg\xa4\xca\x05\xafD\x03Q\x10.\xe2\xeb\xd2\xc5b\xea&.\xc0{\xc6\xcd\x11\x17\xacf\xf1\xa8\u05cb\xd6w\tZ\x10\xfb\xa7\xfd%\xf0\x82\xf3\x05\x170\xa7\xd7\x00\xa3.\x117\xd1s\xd7?\xba\x1e\xff\a?\xae\xeb\x1c\xbf~\xfd\xf8\xceu\x1f\xd7\x0e?s\xcfȊ\xdc\t\x83'D\xc7;F\xc3F\xbb\x84\xb1\xf9\xb8El\x8d\xb9188:\xb4\xaa\xf9\xe5UgFͯ_6\xa7m\f\x03\xa4\x1e\x0e0c\x87\xcfYV7w\xe4\x99U֜\x10\xa3\xa1'70\x9f6L6\x86rh\xc7\xc8\x15+F\x8eZ\xbe|T\xfa\x8c~\x86\xb7\x8c\x1d\xda815\xc5\xec5ipM\xe0\x90\xd0V\xdb\x04\x82\x9aOK\x14Z\xb3۲s6\xfa\xfb\xa1ž\xac\xc2\xe8b\xd0\x04\xa0\x14\xa0\a\x97D\n\xb3\xfcK\x0e\x01\xfb읁\x12;\x94\xd3\xf0\x89!\xb3f\rI5k\xec%\xa4\xcdf\xe0\xf5poZNK\xf0$p\xcf\x12܉\xe9\xf8\x04\xb1\xc17&\x80\x0ex8\"~\xe5\xe9\xe4\xf5\xd0}\xfd\xf5\xa93c@\xd3qL4\xb7\xa1\xa7\x8f\x1fGK\x162m\xa8\rL\xb7\x12\x9f5\xf8\xeb\tT\x9eN\x80y\x8c\x9d\xf7#4\xac\xb0I\xe8\xd1\x19\xb8\xf3 \x1d<1\x86BD\x92\x9f\x12,5X\na\xa2\xe9\xdc\x0f\x13y\xc1\x92\xa0$y\x9aR\xb0\xafc\x9a\xae\xbb\xfdT\xb2\xbd\x1bP\xa4\xd2YL\xddєP\x8f\xea\x97\xc7\v\xbf\xbeZ\xbaW\x04\x12fj\xcf\xf4z\xdcA\xe6\xbd3\x82\xae*S\x9b\xc4Us(\x15\xf7g\x01o\xc1\x8d\xe7\xb6\x11\x98.K\x8fZ\xa3!\xe1\xc5\xccJڊ&A\xf4\xfd\x04 0\x01\xff\xca\xe7%Έ\x05\xf2\x1b\xaf-B:\x8f)\x18\x1cNゝKg\f\xe1\x1d\x97u\\6\a\xb6\xac߸~\x18\xad\xdf-o\xfb\xe2\x1f_\xb4\xc9wSg\x15\xca+\xfe\xb5g\xf4\xfd\xebg\x94C\xdd.\xf9f\xb0\x12$\xc1\xca\xcd\xf2]H\xa1x\f\xadG\xa5h\xfdc\n\x85n\xb7\xfc\x19\xc8@\x1bd\x9e\x91\xefV\xdd`\xc8\xca\xcb\xcb2\xac\x8d\xe0\xbf]z\x95\xbcuܸV\xb9J\xbf\vh\xa5s\xa7\xe7UW\xe7\xed\xd2+\xe5\x9bw\xec\xd8,W\xe2D\x8d\xec\xd6}\xfbn\x95\x91\x82O\xbf\xf1\xc6Ӥ т\x13\xecf\x84}́R\xa9\x1aj\x185\x92\x9aNͧ\xd6\xe0\xc1y\x81O8\xea\xbf<\x13lH\x11\xd5.\x12\x1f\x986\x10\xebN;@\a{ \x8d\v\x92È^\x04x]8!\xf1D\x0f\x1b\x18\xbbh\"=\xaceN\v\xfe\x8f2\xf53\xe6x,>\nI\xaf\xb7\x94\x9c\x16$\xe7,>\xc6扵\xc9\u007f\xf0\xbapB\xaf\x0f\x8c]41\x95\x04\xe7\xa4\xf7\xf0\xac\x98\xd5+\xc0R\x8b\xfc\x06\xbaKH\xa3\xa9\xd3\x14)'!G\xe2\x11\xef,\xc5~%!\xb8z\x83\x84}\x10\xe8\xf1\x11\x98<\x02\x1f \x18A\x91\x8d\xc9\n \xb8\xbf\x11&\x10\xa2d!\xbat2\xf8B\x98\t\xa4\x85&Jd4\xd21Q\xfa\x95\xde4\x16y\xf3\xacA\x96I@6d=c\xb4\xd02\x9f\xde/c\x83\x9b\xb6\xcc~\xa8{V̢\x004\xc3\f\xbf\xa9\xa0\xfd\xc3\xc5Wwv\xce\xd0Ñ@\x81\x8e\x9b\x9c\xf4\xbf\xd8|'\x1c\xe3]_4\u007f1\xbdz\xd4J\xd4\xe8\xb1\xf1\xe8\x80\xc6\xe6q\x19KOt\u007fT\x1a\x80\xe6\xd0\xdc)\xbb\x9bj$4\xa0+\x1e\x9b\xbf\xe1ӎ0\x04\xa0K\x9a\xfaQ\xee1\xb1\xbfs\x06m|\xf6~2\x87\x87\xd2k\xad\x9c\xd2\xe3\x19\x115\x8foZ\xe1D\x10nH\xad\x83\x1b\xb5\xf6\xe5\x93g\r1\xfb\x8d\xae,\x8f\xe2:/X9c^\xa3\xd5k4y\x80UzK\xe4q\xf2j\xbdNo6\xeby\xad\xda\xe0\xf0\x1cu\xb94vg(\xe4t\xa8\xb7\x98\x95N')&]\xeftjJC!\x87S\xddF4\x86!\xa1H!C3\x90Ą'$O={\xe0\x00b\xee\x1f\x8d\x9bj6i\x96\xd1\xf3A\x15\xa8\x1c9\x1d\x1dC\xefN\x9f\x0e\xf2@\xfe\x9a\xf9\xe8\x05\xf4\xc2q\xc8z\xd8|jP\xf8\xa0\xa58uMn\xee˦{\xdb\xc4n\xb82\xeaz$aF/\xbaK\xdf17~\x16\x8f\xa0;\xc1\xd8D\xc91c\x85\xfbA\xa9\x94\x81\xba2\xf7=\x95\xa9|\x8bɪ\xaf\xb3x\a\xd5\xdd\\T\x8e>\xb7\x1am\xba:\x80\x99V\xb3\xbe\xa9\xf6\xa6b̗\xfc\xf5\xaf\xbbo\xbc\x11}Y\x0f\u007f\x9a\xb5n\x9d\xd7[\x1c\xf1\x96\x847\xae\xf0\xfb\x8a\x8b}_Yj/\xbb\xccc\r\xe4\x06\xac\xb1\xf0\x86\xe5\xfe\xf2\xe17N\\\xbd\xd9v\xb9u؆-5\\\x8eƭ\xd4I\xec~\xe7ĩ\v\xa7/\xa1\xc7,H]>|xq\"\xdev\xc9\xf1JϠ\xb0\xb3\n|\xeb\xac\f.(D\u07fc\x8b\xff*+\x81\x06\x9d\x05੧R\xef\x1a\\\x06\x15\a\xc1\x84\xceN\xa0\x19?\xbe\xaf\x14h\xcap\xbd\xd4;\x9f$\x86\x0fO\xc0\x03UU\x05\x05\x85\x85Ӂz\x8cY\xa9\x04\xb0\xaa\xaa\xbc\x1c\xac\xce\xc3\u007f&\xfc7uj^\xdec`+)\x99\xea4\xa5\xff\xca\xcb\xd1\xe5\x15\x15\xe3U\xb3\xa63ұ\x16\xcb\x19sX&\xf3:\xe3\xf9\x1e\xe3t\xa0q\x81{,8\xeeq\xc5d>\x8dI\xceM\x03\x1a\xe0L]\x8a\xefZ\x8a\xef\n\xefE\xdf\x00M\xea\xd21\xe5V\xad\x9c\v\xfaC9eV\xad\fH\x02꙾r\xabJ\tXE\xc0E\x12\r\x8c\x04֣o_\u007f\xbd\xb2r\xcbU\x15xv\x95\xeb\x9c|0\xfc'\xfc5\xa9#G\xc8\xf8T\xf4\x8fO\x05\xe6\xba|x\\\x8e\xa4.\xa1\xb6P\xfb\xa8\a\xa9\xc3\xd4\x1f\xd2ި\xd2\xfbD\xb8K\xfb8\xc2\x11\x10ć\x81\xe9\x02\xe8\bGK\b\xe6\b\xd1g\x13\xa4d,\x1f\x17\x92\aXo\xe33.A\t\xc55 $@\x95\x90\xdek\x163\x12\xe07_\xc9 \xd6\xe0c%ByN\x80;I\x10\xd3p\xf1\x01M\x17\xce\xc3\xf0\xd3h\xc0\xe9\x8b\x04\x1c\x01Z\x87\x99U\x1dT\xe8M6\v\x98\x12\xf5;\xfd$\xf5\xf4=\xad\xd5=<\xac\x03RI\x8b\x01\xea\x81R\xaf5\xd1c\xa6\x81X6IQ\xd3\xf6\xc6!3\a\x95;*\xf5\x8cj\x10\x0f\x9e\x97\xb2\xad\nn^\x1e\xab\x1b\xc6JC\xf9\xa0C\x85\xa3\xd4Y\xb0\xae\xb5z\x9fA\xb8H\x87\x92\xf9\xe5El\x83\xc8E\xf0z@.\xf2\x81\xaaY!\x14\xad\xe7ᩡl\x0e\x9eI\xa0\x82\x0f\xfb\xb9%\xe7\xd1\xd5\xcb\x03\xc5Y\x8e@Գ2\xc7\x05\xe6+\x18\xe3\xbd\xfe\x88\x10\xdf^\x11\xe3\xd1\x1c\x89\x9c\xbfD*\xa7\xe1Կ\x01V\"\xf7\x84\x17\f\xadh\xb2\x18\x942-0\xcae\U000bdef42\x16.\xd9\xcctKUr\xd0]\x9a\xae\xa2\xba\xf4\x97U\x80\x96т\x83@\xad@]\x90\x95\xf1\x80\xf7\x99\xf0\xed\xcc\xe0\xa3\xf3\x96b\xb2\xc7ҿ\x16k\xa8\b5\x04\xaf\xc4\x13\xa8\x05ԥ\xd4\xd5\xd4-\xe2:\x8c\x17TB\xfd\xb2\xbe\xb8\xb0\n\v\xebnz\xd9\xe5҈܄\x96\r\n\xcbn\"\x0e\x12\xbe\x98\x86\x8e\xa6\xcd(E\x85.VX\x80\xf1䫋\x12\\I^X\xc1\x05+\xd7P\x1aM2q\x8e\x81\x172$\xe9\xfa\x02\xf9\x1b\fE\u007f\x81\xc9)\xa92\xf2\x1e\xb3\xde\xe9(\x03O\\\"\x89DO}Q\xdf\xe8\xcf\n\x96\xd7\xeb\x1b:Z\v\x8a\xea\x1aB\xee\"g\x87[?\xa4kDQ\x143[]\x1b\xf4\x05\xba\xea\xbc\xe0Ь\xc2,e\x0e\xb8R\xa3\xca*\x94\xcb7\xed\xb2\x95j\vw킗\xe4\x87\a\xd7Ƥ\x9bw\xf9\xb3FF\xabP^A}AA=\xfdpQdrע\x9aļ\x99\x15ڲ\xc1\xb9\x063\xfb3<\x9fKZ5(\xe0\x93\x9dp\x8d\x99\xf6iE\x9dUeR\xdb<\xddY\xc1PSy\x9dEmֺ\xad\xfa\xc5فl\xe0[\xb4ոD:\xfb\u007fF\xf9]\x8a\xe5\\\xe4%\xeb\xd5t\x96\xab\x14e\x83\x88\x1b=\x04\xfe\xf2\xe1겒\xd2\xc2\xd4\x1a\xebnEi\x1dx\x91ܹ\x10}\xbe\xb8\xa6v\xf3\x92de\"<\xdb\xcd\xf3\x85j\xf8\xc8y\x1f\x8e\xa6Ԙ'\xfeVB\t\xe3\x9c +\xe9ͤ\x81\xc8~p\x88\x8d\x94\bc\x99\xac2\xc0D`J\b\x1a[\x9c\xf8\xa7\xaaf\x88\x1b\x89\xcc\xe6\x13^\xbc\xccD\xd5^b\xaa\xfa\xb2\xa5\x04\xd5\xeezw'\x00\x94V[1:k6\x13\x95\x02\xf9\xcf\x0f\xcb\xed\xd2Q8\xf04\x1f\xe9\x18W\x15\xfa\xec9ii{\xa9t\xeds1p\a\u0381\a\xd1\xdeWKZ\xe6\xed\xda9\uf86c\xd1\x15Z\xed\xd0ْZ\xb9]v\xea>)\x94w\xe1\x02\xb7gys&\xdep߷W\xef\x01\xac\x837\x10\xfdz\x03\xaf\xdf0\t\xcc\xc7\x05D{\xb6s\xefa\xc2tD\x1b\xd9\x15\xea\u007f\xf8\xa8\f\xa4]3jA\xff\xdb%\xeb\xcc\x16\xc1\x8f\x9f\xe0\x9f\x0f\x8c\x03\xf7\xc0S\vVW-80\xb5{\xf5\x96Wt\x8b\x0eN\x8bB\x10\xf3D\xea\xc7\xfd\xee\xc1[\x81\xfc\x96\xc1\xb5|\xa9D\xa9`\x15\xa9\x9b-\x96\x90\r\xc8BU\xcb\xdb0\xf5?1\xd3D\xd7ɠ\xa2X\xa9T\xc9Fv\x92K\x82R\xe08\xba\x1a\x8d\xeb\xd7\xdb\x12\xf6\xf5|dO\x8f2i\x89M\x90A\x03\x88<\x9fx\x04aC<\xf1\x8a\x99\x16\xda\x13\u007f\x172\x10\x02FI\xe3\x91\xc9\x1fϑ\xcb\xff(\xb7\xc9\xe7\xa6\xee\n\xc4^?K\xd5&\x03p\xc2\\1m\xceG\x93\xfa^\x82\xb5\xbd\xa9^\tu\x04\xfd4\xe9\xa398\xf1\x8fr\xa1l\xb2\x16P\xafDŽ\xb2Bڜ\x8f'\x9f\xae\x15\xca\xf6\xa6\xf5Ȑ \x87\xccN\xfb\xe8\xe0\xa8\xcc^;\x88\v\x8e\x1bL\x94\x8fh\xda\x12]\xe4D5#\x19\xde47\x1f\x1d\xda2uպ\xc7'\xc2u\x15}O\x87\xb6\x8e\x04\f\xfa\xe1/k\x9e[Z\xce5\x96Vk\xb2\xd5ֺ\xe6Ys$Ԥ\xa6\x9aq\xa9\xab\xd7L8\xbc>9\n6\xc4\xcf\xfcز\xc04\xf8O\xe8\xfbIw\xbc\xb1\x9c\x8d\x84\xbc\x81\xfaI\x15~\xcdy\xf2\xd0\xfc~4=\x01\xa1:\"`h\x8a\x10\x970*\xc4 \xe96\x82\x97\xca4`\xb1\v\xf2F\xa2\x83)b\xc7r\x02\x84\xd7\xc5#\x84\x93!\x9af\x9e\xfe\u007f\"G#jS1\xb1s2\xc5_F8\xea\x14\x95\xdf\x1et\xb8r}\x96\xb0\xc9\xe4\xf4\xb7\x17\xe4\xb7\xfb]Fs\xc8\xe2\xcbu9\x82\xed\x9db\xa6W\x88\xe4\xa7\xcb\xe4\x17\xb4\xfb\x9d&S\x98\x94\xf9e\x15!\x17\xd7\xe9n\xaf%~\x11\xc4\u007f\xb5\xed\xddg\xa8!\xa5\xb1a\xbc\xc3\xeb\xe0\x83\x9d\xf0?F\x92D\xa8\xe3\xb0[\xec&\xb5\x96\xb7\xda\x1cN\xab\x95תM8\xc1!\xa4\n!P\xdb+\xe6:lb\xee\x05\x05mV\xbb\xa9\xb7\xbd\x1b\xf4\xa2\xda̯\x9bֶ\x8e\x1c\x16s\xe6Y\xb2\xdc\xe5\xc1\x1b[\xfecD\x1c\U000c2f0a%t\xb8\xc7H\xbc@`\xb6\x1d\xff\xa4\xd4\xcf\x14\x9e\x0e\x00u*\tza-\x0e\x9eN2T_\x12⾗\xea\xed\xf7\x8d\xd2+\xac\x83Z\xbc\x12R\x98\xfc\x17\xbc>\xe1Y-\xca{\x88\x1f\x10\xfc\xfd\x19=MA\xef<\xf4ɭ\xef\x88\xf3\xcd;\xcf\xd0\xec\xca\x05\xfbS\xd4;xށ\x97\xa7>\\\xb023\v\xa5\xa8[\xd1'\xf3\xe0\x1d4\x85'\xb8\xf3\x9e͝y6\xb2d\x90\x91F\x86[H\x18a\xc4\xf8\x8e,\x19\xc2\xf3rTH\xbb*\xb5\x15\x0f\x94OQW/\x1cJ\x02\xe0\xedUZ\x9d\x11<\xa6\u058b\xefp\x02\xb5\x1auB\xa9L!\xb1LH\x9f\xf6\xb7\xc4Q\xccX\xaa\x8bP\x92\x04\xb7\x98\x11u\x86%!\xe2]\xb9\x1f\xb4D\xb4\x11\xc1k\x17\x14ա\x89\x13\x14\x11m[\"\x80\xba\x12)\xa7\xcf\x05\xcd\\0$\x10\x92\xacR.w\x95\xf8\x03`б\x9d\x15s\xdbZ\"e\xaebEVŸ\x95\x1d]\x0f\xce\xfaӭ\x8f\x8c(\xb5\x8f\xd28\xc1&t\xf6\x86\x1f\xae\x18{\xfd+s\xc7^7{lyEN\xb9\xad\xeb\xca\x11K\x835\x1dc\xc75\x97*\xe8\x87\x16\xb5\x8d.\x02J\x93\x8b\xd9`s\x98\x9b\x8b\x9b\xe8Z\x89ϙmW\xc9'|\xb3\xe3\xf7\x81\xf8\x94\xf6\xf5\xc3/w\x8c\x98;.\xbc\xe8Ѯ\x9e\xaf\xa6\xd4\xc4\xf6x\xfd`\xcfm\x00\xec\x98\xfb\xda\xee\x89\xc1\xeai3._\xba#\xfe\xea\xd4\xf6\x9c\xca,\xb79\xbfbn\x93Vw\xc9~\x866\xe7(\xec\xf9\xec\xf4b#0֟\xb7\x16\x8c\x15d\xf6D\xf70T\x92پ\xf2\x990)\x1d\x12\xf1H\f\x02\xf2-^\xf8L\x82\xe2*K\xda\xc8l\x14\xe7\xfeD?t\xb10̹\xe8Ep\xea\xf7|\xe6\xf3\x87e\f,\xf6\xc7u\xc0\xc0O\n\xc9=\x83\xa2\xedk\xa1v\xea\fg8b\a#+\xa66\x99\xcbB\x83\x86'G\xce|b\x1e\xcdLzp\xe1ӓ\f\x8aʜ%\xe3\x97\xee\xd9?\xa7\xfb\xd2\x02\xa9ϔ\xedO\x94\xb6\xe4\xcc\xdf3\xe7\xa1\xac1d\xbf\x1a~r\xbe\xc1\x03\x9d\x96\xf1\x8a\x18\xa2Q\xea|ϻ~\xb2\xb1\xef!*L\x9c\aG\xf5Z<\x83\x11C\a-\xee%\x1e<\r2ɴ\x1e\xabx\xa2\x05\xadX\xb4n\xc5\xd5W\xaf\x00\x1b\xe7<{\xd5;dmKQ\x99U\x8e&!h9W!s\xeaDߣ7\xd0\xf7\x9d#\xae\x02w_@\x1f\f\xb0'\xa4\x04\xb4|\xca\x02Ļ\xc3\xf4\xd3\x00\xa6_\xad\x1f\xb3\xbe\xfd\xf7\x99\xd5\u007fo\xe6\xd1\xf3\xee\bP\xfa\xd2\x19\x1a\xe2\xfa\xf3\x1eF\x98\xff\x89\x8a\a>\x11\xebK\v\xa6\x8e\b*\x17\xfe\xce5D\x14\"ђ\xb1\x11\x8ab2\x1fx8\x93\x99\x11@\xf9\x89\xed\x81\xe0\x0f\x8e\xd0\rYx\n\xc9\">\xca\x12!\xb2\x8c\x92~\x83S\b\xcf&\xb8\xa7\x8d\xe2\xd1\x1fJ\x87\b\xe0Z4\x02O\xa3\x97\xc3>ˑ\xba!\x9b\x8f\x1cټ\xf4\xe1;\x9f֗\x81\xc5 \veM\x9fkd\xd9#\x9b+\xab\x1e\xd4\xc8M\x1a\xa3O\xff\xe0\xa4#@\n*\xd1)\xb4\x1d\x9d\x1a\xdeT\x87\xf6\xe9=/\x99\xfb\xee9\x8cN\x01\xee\xf0\x92\x99W\n\xaa\x95 \t\x1e\x1b\xfd\xa1\xa8\x18\xe91\x00ń\x99\x87A\xb2)\xeb\x8c\xfb\b\xfa\xf9\xc8\xf5_\x8d\xae\xb9\x11$7\xcf\xde\xf9\"\x90\x1e\xb1\xa0>s\x89Z\xe1\x04̔\x8d\x9b\x8f\x00\xe1\xba\xf8JS\x1f\xa8\x99\x86rm\xfb\xdf\a\x1cX\x02\xb8ē\xc1\x92`\x92\x88\xe6\x1d\xa8;o\xa0]5'\xf4\x9c\\\x82\xa7G] O\xe63`T\xb4D\x90\x05\xc3\xf3\xfc\b\xfb.ķҕ\x10\xc9'1\x173\xf3\x19\xf90#\xcan\x9dCX\x9f\xb9o\x9e\xd9\xc7\x0ea\x83.&\xe8\n\xfe\xd3aH%\r\x0e\x87\x01&\r\xe0 )\x9c\xa2\xf0!i\x9d-{\x04\xd8\xc1\x18`\u007fD6\xd7\f\x14\x03\xe4\xbfP\t\x92f\xa7ӌ\x92\xae\x82\x02xI\xd8\xe1\b;R\x13Rw%cÆŒ\xe2\x11N\xe8^\x04^n[^Y\xb9\xbc\r\x95\xcf\x12օ+p\xdf\xfb\x19\xaf\v\x05\x04[\x80\x12\x87\xbc\xf0\xed0\x0f-\xe2XE=\x04\x05J0#\xf0\x88\x82,\x8f\x89!\x921@\x18\x03Q\x89\x12\xf7\x81\x908\u007fT\x00\x81\xe0\xf4\x13\xe8 <\x97\xb0OF\xfc\xa9z\u007f$\xe2\x87\xcf\xf9\x81\xd4ܗC\xc2\xf45\xe3\xd0{\x0f<\x82\x8e=d\xa6\xffL\x12\xfa.\x1d\aB\x0fl\xfe\xf6\xc19`iĿI\xb7\xe9}\xf4\xd6\xdd?\xa2\xf9ӟ%\xb9\x9bq\x1c\x14\xdf\xf3\x03\xd89\xfd\x88?\x02\xff\xde\x14\x8d6Enj\x19\x15\xf1\xf9#\xd7\xde\xf3\x10z\xf7\x91Lx\xf6C߀;\xc8\xe8\xd1w\xa3\xb7>\xd8\x04\xe4\xc7#~!\x06\x8a?\u0604~<\x1e!v\x15\x8a\xb3\x14\xf3C\xfa\xdb\xdaq\xff_&`\x8a\xd3f}\f\U000c60adt\x01~5\x82\xa5d&\x10{\x12ZpNM\x84Wd]\x91\xd0i\x91V\\WB\xacQ\xfc\xe2F\x85\x8bID\x04\xf8$\x11\x92\x1c\x8f\x13#N\x0e\x86$\xbe\xb4\xeb5L\xe4\x99\xd2\v\x8f\xb0]q\xcePXT\x15\xe7M\xe6jV\x10\x1b\xd2DI\x1c\x8ah\xfe\x90>\xbcd\xd9]\xc12t\x8d\x8b\x0ex\x959>\xf4\xe6>]\x96\xa6rհ\"\xde0|\xf6f\xafڜ\xa5\n\x96\xd5;\r\xd1۬\x15\xa7n\xfd\xfb-{\xf0w*E\u007fX\x1aP*s\x1bǎ\xebpj9\x8bV\xc38\x1a\xab\xb2j\xc7\ah\xe6J\x99\xd4\x03G\xc4;\xee\xf5\x94H[K\x95·\x9c\xb9\xf1%\xa3';VW9\xb3\xef\xech\xdb\xf4\xbc\x04J\n\xb2\x1b\xaa\x87\a\x06w\xec\xab\x1a\x1eTO\xbe\xafoϢ\xee\x9d\xef1\x97\xa3\xa7\x8c\xe0\x85\x86Ҿ\xeevi\x8e\x15r\x1c\xbde\x1a\x1a/g\xc1\x94\xf7}}?\xf8\x0f\\cS[ڲڧ\xd5\xc6ѭ\xd95\xd7\xef\xbf\xef^\x00s\x8bZ\xf4\xc51\x05\xeb\xf2\x968x\x86\x81<\xefw\xd8L\x96\x82+\x06\xb9\x97\xba\x94J(?\n9ul\xe8\xde\x11^O\xadr\x8eN\xe9\xfdp|b\xe6Z[\xb3\xabz\xb5\x06\x1c\x9d\xdb>3\xf5\x8cN\xa2]\u007f\xc9\xf53\x87L\x1b\xba\x005i\xaa'O\xaa݅\xfa\x9e\xbb$\xa7\f\xa8\xce\xf9\xfb#럍\x8a\v8\xf1\x14\x88\x0e\\\xcc|\xe9Տ,t\x81\xff\x98\x13\x0f\x90\xcd'\x18\nz\xb2\b\x88\xbc\xf0\x05\x89\u007f\x0f\x13\xe3\xc9\"`\xefՀ\xc74,\xad{K}\xef\xc6;\x0e?}͍\xf7\xa8^g\xab\xa2e5r[<4\x05\xfe\xf9\xa8\xfa\x9eL\xfa\x1bLu\x84\xa4\xc7B\xc5\t\xb0Н/\xd18\xe0\x98ԭ\xa9kG\xb3V\x9d$\xdf\xe5ʗ\xe8͒<\xb0\x15\xf0p\xdaX֢c\v\\\xbd?SP{\xdb\xe3\xffz\xf5\xf9\xcf\x1f\xec\xa9mZ\xb5\xachH\x83\xff\xea\v\x13Z\x9ex\xeb\xd5*\xa9R\x0fkj\x18\x8dJZ\xf9\xca;o\xbfR%U\xabYOV\x1d\xa3V\xcb*_\xa6_?M\xa6\xad̺\xc2v\xe1vqR\x15\xa2\xc6c\x1a =8\xc0\xa3\xa30\xd2\x05\x8f\xc3j\x90Y\xec3\x9e\x1d\xe3\x99\b}B\xf0-\xd9Ӎ\xbe\x16\x02\x98a\u007f{\xeb\xc9- \xb9\xe5\xe4VTD\xe28\x11h\xbb{\x84\x00}\x1d\xd2\ne\xbe\xee\xee9\x93$!\x16\xb3\xe5[N\xfe\x1f\xe6\xbe;\xb0\x89#\xfb\u007fg\x8bV\xbd\x17[\x96eɲ$W\xb9Ȓl\x83e٘bl\xc0\x98f\xba馛N\x80\x80\xe8$@BO\x80@\xb8\x10R\b)\xe4\x9b\xde0\xb9KB\n\x1c\xc9A\x0e\x12\x928\xb94\xee\x92\\\xbe\xb9K\x0eli\xf8\xcd\xccJ\xb6l\xb8\xdc}\xef\xfb\xfd\xe3\a\xd6\xee\xec\xec\xec\xec\xcc\xec̛7o\xde\xfb\x89D\x8fNO\x8aŦt\xad^\xaf\xb7'\x89\xe5`\b\x9b\xa6\x97H\xc0T.M\x8fҀF\xc0\x82\f\x15\x98-\x15'\xd9\r\xe8\x9f=I$\x87\a\x80ݨP\xc2Wش\xc8Y0\x19\x1eV3\x16V\"\xe5ར\xb7\xc0\xd8\xd7\xc54h=sF\xdd1\\\xc4U\x0f\x99\t\xa4\xf0l\b\xee\xb0\x00?|\x94U\xa1\xd4'E\x1cX^\x05*\x1f\xfa\xe4Փb\xc6\ah\xa0V\x9c\x04\n\x19|\xfb\x10(\xfb\xeeS1\xbc6\xf0mZ\xde\xf6y\x0e|\x03\x9e\x06^\xd5v\xf8\xe5'\xb9`K\a\x8d\x1a\u0080\xda\v,\a,,\x84/\x82_>\x83_G\xee\x80_\x81\x94?\xfd\xa9\x1f\x98)e\xd1gΌ\xde\xd7\xc0\b\xf2\x12\x82\xff\x8f1\xef(\xd2\xfd;\a\x03\xfa\xd6\t\x8axϯ\xa7\xbf\x06Mϯ\x8f\xfc}\xfd\xf3\xec\xf9\xa7B\x1eh\xf1\x84*\xf3\x98\xc6\xf5\xa7\xc0\xf4\xf6\xaa\r\xaf\xbd\xb6!\xe3\x19\xf0(\xc60\x87zO\x1f\x81ެG\xe3\xedvJJ<{cy\fK1\x98qA|\v\x87\xd8^t\x81\x16\x99@K9\x85\v\x0e#\xc5\xf9\xa9\x80\x8872\x0f\xc1\xdf\xc2\xf4e\xfa\xb3\xa0\xe9|\x03\x98:\xbe?\\\x19}c\xfe\xf8`\v\xed\x87G\x17\xd1\x1a0%S\t\xaf\xc0в\x19\xcc\xefO?\xb1\xf9\xe0\\0\xf0=C}%7\xeb6\x98\nO\x8f\x1eu\x1eL:{g\xe5\x98\x05\xd1\xd3p\xe5\x801`\x1d]\xd6\xd1\x1bL\xa5\xf5K\xc7\xcdX\x0e\x83\xf0c\xa5\xbe\xa8r\xb8\xe9,\xa8\x9dw\xef\x86'c\xb4AL\xb1\xff \xba\xbf\x98\x92\xeb\x04/?d\x87$\a\xe8\xfc\x88\xcd\xf6{mX\xb9\x93\x89\xc73x\xa1\x8b\x18\x19\xc19\x1dO\xbcC\x99\xfc&~\xda\xc1\xf5\xabϜ\xfebϞ/N\x9f\t\xaf\xe2\x0e\xb6\x01\xfa\xea\x81\x03W\x01\r\xff{\xed\xb9C\xab\x1e{\xa3m\u07fe\xb67\x1e[5\xf3\xb6\xa7Ƽs\xe2\xc4O\x81?\xec\xb9\xf7ӧ\x8e,\\\xf5\xfe\x92\xf7\x8f\x9dx\x87]\xde!.\x1d\xbbg\xcf\xd8R\xf6ښY\xb3:\x1e*\xadd\xa2\x83\xb7o\x1f\x1carr\x1ds\xe6\xa43[\xd9{\x0eVE\x86y\x8b\xa6\xcf\xe6\x04>\xfa\x18\x9a\x9b\xc7v\xda[\x8c\xfb\x9fˡo\xba\xee\x02XM@Z!\xb4\xc5\n\xb8+V\xfdx\xbd\x95\x1c\xe0\x97V\xfd4\x1cF\ax\xe5\xd6an\xcbw\x0fud<\xf4\xdd\xea\x99\xd2\xdf,\x98>8\x0fd\xbf\xba7\xb2[\xb9\xf9\xc41\xfa\x13\x83\xd5j\x88:pBZ\x87\x8f\xd1\xef\xf1\x11<\x8e\x8fp\x18\t\xcf\"\xe1}\xe8\xf8\xd0C\xdf}\xf7\xd0\xe27\x8a\xd2\xdd\v~\xd3\xe7\xf9?\xef\x8e\xec\xad*\xb1\u007fLamI\xeaFP$\xd8\xce\b~\xda\f\xc4S\x9b\x9d\xf8jˣ\n)\x1fUJ\x95S\x95T_\xaa\x06\xd1塈2\x8f\xa6\xc6#\xea<\x83\x9aMͧ\x16Q˨\x95\x88BoD\x14z;\xa2\xd1{\xa9\xfd\xd41\xea\"\x1a\x11X\xf4\xe3$G\x9f݀\xad\xd7L=\u007f\x01\x13\x9f\xf8\xc3.\x89\x12\u007f\x00\xe3\x82\xfd\xca\x0f\xdf\xf7\x1a\x02\xff\xe4\xae\t\xeb\xb3\x18\xf8[\xfc\x9cq\x0e\x8b\x80\xdfXi\xbf\xa0\x8e\xe6\xe8ԧ\x03\"\x97\x80\xf5o4y\x03\x1e\x11\x16^\x8b\xa8ȵ\xa8\x98\xbb\xaf\xfd\f\xbd\x97>\xda~f\xa83\xfe\xafB5S\x95\x86~VrnV\r\x99\xa9\x9a\xb9\x1c\xfdn\x8b\x9d#\x95\v\x81~\x110,\x02\xfa\x85\xe4/\x16\xeex\xc1\xb9聞\xf1?\x0e^ԙ\xb13\xbae\xed\v/\xac]\xf7\xfc\xf3\xf0\xb2\xbbwuow\xcb$3\x93\xd6gbj\xa0\xc4\x11\xa8\x1f\x12\xc8\xca4\xa4ר\x107\x9e!\xb1*\xcdFyj\xc0g\x17Q\xed;\xe0\x13\xa0\xa1\x929\x1c\x99\f?\xe22\xdf~\x1b~\xb8hў\x84\xbf\xbb\xd3\xf3\xed\xcatO:\xfe)\xec\x9e\xf4t\x8f=\u007f\x82'݃\u007f\xe3\xf3\xd3=\xec\xfb\x19=\xfe\xc1\x13C\x16u\x8fY4$\xa3[\x9e\xe8\xcf\xf1\xfc:\xa1\xb4\xe0\xf6\x8c,\t\at\x86BoE\xb6Ԙ\x9b\xe6\xc9\xe7\x81LoH\x12\x19Me@\xc5\xc8\x18\x11-5\xe5\xc5\xfd\v,B\xe3o;\xc1{\xc8\uec46\xbd\x95q^̍,f4&\xde\xdfv\xf8p\x1b\x03\x0f\xb7\xdd\u007f\u007f\x1bh\xabȻv)\xaf\xa2\"\x0f<\x99\x1b\xa2\u007f\n\xe5\x82'\xf3*\xc0\x16|\xef0Nز\xe00[\xd2\xfeJnEE.W\x8d\x8f\xbf\xf9\r:\xc6\xf8\xd0LD\xbf.\xa3\xf3\x18D\xbd\xb88\xdc\x11ߵ?O\x04\xcd\x18\x1f\x90\x15\xbcDP\x89\x10I1\xcd\x01\x9f\xb0\xc9\x11We\x17\x1e\xf0s\xfb\x00\xbb烏\x0e\x8f8\xb0ba\xf3\x8c\x85\xcb\xef\x1dv\xe0\xb7\xe7\xef\x9fzi\x04g\xb3\x88\x95\x86\xde\xd3\xe0\xcfk6~\xbe\x19\xa4\x9c[~\xf1\xf0\u038d\x9b\x8e\x8d\x99\xbeq\xedD\xeb\f\x8d>M\xf3\xc7\xfb\xcbf\x97\x17\x89U\x86\xe4^OM8\x05\xd9R\xe6\xc5\xf7\xde\xd8u\xe8\xfd\xc0\xb8\xe5\x1b6.\x1f\x17x~\xff\xa1\x97j\xcb\xd9T\x9dA\x99\xe4k\x9c\xb3\xf8\xc3Mg\x81z\xd4և\x1f\xd9:j崉a\xa7U\xaf\x1d\xac\xbf\xff\xbc3\xd7iP\xe9R\xfa\xd4t\xbc\xe6LU\xc5xY\xec\u007f\x1c\xdb\x12\xe4`\x8c(\xa2\xc2@|R\xa6\x02\xa2*\xd6\v\x10\x90\x11\x8cE\x12Dzgcg\x1d\xf1\xb0@\xfc\n\xa0\x8f\x10'uA\x10`\xe22\x15+\x8b\x97\xe1,vЋ\xa5\x16ć/\tD\xbf\x16t\xc8\x05U\xf2wm\xc9\x1d\xdf\x01\x9eKb\xee\xc5I\"\x94\xd9et\xd2'\xdf\x13\xc4&\xead\x95\x8c\xe5\x01{\xd2\xecb\xba\xe7\x82\x03\xd1D\xc5r\xa6\x15RINf\x05\x9f\x9a$U\x17`\x8c>\xb3\xd2[\xcd2\x01\x14ThӌN\xdeՅk\x8f\xeb-\xe8\xe3\x0f\x13z\x9b*\xaeFO<\xa0\x99\x80\xb1(\x00\xfe\xd3:s\x94\xabX\xb7\x1b\xbdv7b2u\x80\xc2\xd0\xd8Tt\xf7\u007f\\k\xdd.\xe0\xc47\xe0ǻt(\xe7\x1b\x94\x0e\xe7\x97\xfe?\xaf\xbb\xe0GC\xe0߱7N9\xb15C\xb7t\x12\xc6\xee\xd6\xd9%\xb4\xddig\bC\xef\x14\xb6̉g\x0f\x8cS`/\xba@χ\x17\xc0U0>\xda\xef\x8e\xf7`;lc\xa2(\xe6\xd5\xc8\xeb\xf4\xf1\xf7\xe0\x0f\xf4|0\x06\xb6\xc1v0\x1a\x84\x95\xb4:\x12Җi#!5\xad\x04a\xad\x9d\r\xdb\x19*:\x83\xde\x1f\x890,\xf1\xb7\x11\xf9\x86\xdeO\x02 <\x1dR\xda|M\x84\xd2\xebYJ\x93\xaf\xa5)llj*\xc9\u007f\x8f\xe6\xa2\x1a\xea\x1e\xc4\xe9S\x1c\x16\xcb\xf3n\x02E\xfd뇀`\x1c\xfbO\x0f\xce\xc4D\x1a\x06o\x9bk\xbc\xd8ͨ\x01C\x80b\x1f\r\x8c\xa6+\xf5\xbfz%089\x1f\x9efx\x1d\xfa\xc8\xe11Æi\xfd\xdaa\xc3P\xf8\x9f\x1ep\xa2_\xbb?\xac=/!U\xe8\x03\x8d\xdez2,l\x03\x85OZ\xf5\x9a\x0ft\x899\xfd\xea\xeb@\b`\x13\x1f\x88\xfa\x8b\x90\xa1\xee\x9f\xfd~\xe5\xeem\xf8nC\x83N\xd7\x10\x02NPf.\x97\x96\x81\x1cl\x1c\x0e/\x96I\xcb\xcd\xf0M\xf8\xb1\x16\xddl\xf8\xd5LX\xb3\x00\xb9\x19\x1f\u007f\\ܗK\x1fj)E\xd9u\xa8%u*\x00bN \xd3c\xbe \x057\x8e\x12\xec\x80\x1akg1( \x16\f\xa3;\xc7\x1e\x13p{1\xa1\x15\x88-\xc6g1\x16\x11\x90\x16@\x80\\\x8d\xbc\x97\xb72t\xa8\xa9\t7D\xb8\tP4-\x1d\xd9o\x12o\xe1'\xf5\x1b)%z\xba2\xf4\xc7\xc89\x85L\xa35)2<:\xa9B&\x97)\xa4:O\x86¤\xd5\xc8\x14\x9c\x9c\x91\x91T\xe0\x81]\xb7E\xf6ݶK\x92\xea\x19\xea\x1b\xf3\xa1\x91~\xfd\x03M\xdf\f[\xaeuN\xef9\xd6\\[F_\xcd\a\xaf\xf3)\x1f6T\x8c\xceV\x83\xd6p\b\x9bH\x85\xc2t\x11K\x8bu4\xad\x13ӬV\xc2\xf0\x10\xf6\xd56\x11_W\x15\xd3\xca\xd3\xd2ʧU\x14\x0e\xf1;\xe4(+\x94\xa14%ɤfei\x0e\xab^o\xcdH\x93\xb3\xca$S\x8a\x14\xe5\x84\xf2\x93;\xfcC\x98!\x10;\x14\v\v\xfb\x11\xf8竭\x05\x8f\b>\xb1\xe8N\x9f5)D{ʎ!\xfc\x04\fK\xb7\x1d}\xff\x14 \xf8rљ\x8c\x00\xcdy\x18\x98V\xc4\xcbЌ\x80w\x13\xec1\x8cH\xda\x14d\xb0\x00\x9d\x02\x85\x9c\x94e\xa2;\xb5\xc5\xda\xe8\x0eN\r\x16\x18\x1d\\\xbf\xd7D\xe9FC\xbahW\x89\x96vπw\xcf\x17;ty\xb2\xb5\xbf\x139rӹ\xc5p\xf4\f\xd8\x16\\;\xbf>#\xa3~\xfe\xda`\x1b\xa4)\x91\x84a\xa3\x8fh\xb5\xf4\x18Z\x9bb\x00\xc9\xd1iz\xb3Y\x0f\xbejq\x80\x13;\x0f~\xa2\xd1\xd3\\\x16l\xa0\x9fЛS\f\xb0\xe0\xe0\xce+\xd7rjB\x19\x19\xa1\x9a\x9ck\x98\x87\xa3oPl\x98\x8b\x10\xdb\x1a\n\xe8)^\xe3\x8d\xf7\xeaNA]'ޮ\xc6\x03h\xe2}\x96\xd5f\xe0\xbd\"\xf4c\xc3\xf0\xf2\xe5\xb6.\xd0\x18!\xb8\xefok岭\x9fo<\x0e\xb2\x9f\x88PB\x8f\xc3{?L\xeb'\xf0Eԗ\x12\x92\n\xeaD\xac\xfa\t\xa0=\xb8\xe9\xeb]*\xdd.\xf8g\xad\xb0\x9b\x83\x9fJ\xdc\aŶ\x80\xdd}B\x12o\xc8t\xba\x87&\x1b\xc0&\x10\x03\xc2\xf1\ne\xa3\xd4\\\xab\xd9E^\x00\u05ed\x1e{\xf0\xe2\x9f/\x1e\x1c\x8bNK\u07bd\x0f\xac\x86\x1dDX9#^4x\x9dC_\x1b\njK\"\xb8\xf6\xbew\x97\b\xa9\xf1C\xab\xc1j\x92M{\xb8\xab.\x9d\xba(,\xa6\xcd\xe5\x82\xed\x9cր\x9a\xd0\xf0+M\xe8sQD\xe3\fQ\x1c\xac\xb2c\xc5T\x83P\x12^\x14/4\x13\xdcy\x125\xaa\x80\xd8@^+\x04/\xc3\xcb'w\x1e\xab\x10\xe94}\r\xe2\xdc\xd6\xefZsũ\xe5\x1a\x9d\xa8\"\xfa`W%\xd8\xdf\r\x80\u007fy\x18\xb7\xf2\x86\x84GIpC\x12\xe8\xff\xc9\xc3\xc00\xa0\xe9\xa4:E?kݺY\xfa\x14\xf5Ɏ+\tU\"\xfd\x81\xcc5U\xd4@\xbc\xe7\x1cSx\x8fW\x03\x83\xc7\xfd\x8b\xfa\xe1.\xe2\xa70\x11p\xe2\xf1\x1d\xaf\x14Ka\x9b\xf9\xf8\xd7X}\xab\xfa\xed\xfd\xdb:\xb9\x1a\xd8\xde]z\xa5\x91\xba\xb1I\xa9\x8dnN\xf86\xa8\xb3\xa0\xafC\xba̦\x1b\x87\u07feu\x05Q'\xd2\x1c|\x0f䘔U\xfd\xa0V\xd9є\xf8\xb5\xe8N\xdb\xd2\xd9\x18=\xe4?\xa9\x1b\xfev\x017\xdf\t9l\xe8&m\x8fO\x06\x81N\xa4b\xbf\xad{#p\xff\xba\x11\xd0G^]\x1f/\xd7\xec\t\xb1\x1bSJV\xaf\xbe\xa9\x15\xb1\xec\x87\xc6\xfaN\\\x94*\xa1\x82T-\xd5@vf\x8c\xb4\xe8V\xa4\xc3\xfeO\x88\b\xee!h\xd64Rh\x92t\x8b\xd4L\x11aH\\d\xe2\x05\x1a,\x93Ӏ\"\x14F\xf3'aKDP\xbe\xf6o\xfb\x12(\x06\xa4z\x90\x1b\rp\x9f=\xf7\xd8c\xe7\xce\x02wd7b]Z\x17\xcd8p`\xc6\"2\xb3\xd2\xd7\xefX\xb6\xec\x0e:\xf4\"\xaeŋ\xe4\x06\xf3׃\xf0\x87'\xd4\xddH\xd1\xcd\x04\xe9\x1c\xc8\xd3\x19\x16-2\xe8\xe0\x1f\xa2\xef\xac\as֯\x87{\xe0/\xa5Ǿh{\xb8ThrĐ\xb3\xaa!CT0\x02b\xb4\xa1\xf4\xe1\xb6/\x8e\x95b\xbe\r\xdc\x10\xf1\xb8\xbf\xf5\xa3\xea\xa9\tԜ[\xf59\xc4>\x8b(^\x94\xe1\xf60\x01a\xeatv\xeaav\uf726\u0600\x02ńQ1\x05\x81So4\xa1V\xa3\x02x\xb7\v\xd1E\n\x1b\x16\x92Nl\x05\xa2n=\xad\xae\u0098\x06\u007fz\xfe\x03x\xb4ϒ\xf3\xbb\xebŒ;\xbfؼ\xf4\xe3Ѥ\xff$\xa6\xeb\x95\xfe\xdc.\x12\t)\xf6\x81\x8f\xd0_$\xfc\xe91\x06(\xdf\xf5}\xb2\x195$ӊ\x1a\x10E\xc0\x9fP\x04۔\xd8\xd7&\xfe\x10~\x0eF̩\x1f\x9d\x12\xcd8\xfa\xe9\xb2\xcd\u007fޫ\x12\xc6`(1\xd5\xc0\x89\x92E(\x0e\x1eѻ\x92\xdb\x1f&\x87G\"\xa6T\xeb\a\xa0¹|\x17\xbc\x1e\xe1\x11\x17\x84b,i\x1f\xc0\xd3(\x06\xb5\xa1(\xb6\xaf1\x10\xb5\xe18\xaa\xf9W\xda\x10\xf5\x99\u007f\x8b0\x11w#BS\x92\xbeGX\xbd\x80K\x8d{_g\x9fS\xa3.\x17\xeeф6\xf8\x8fg?{i\xc9֛\xc6\xec\xc1뷛\x92\x81⥶\x97v=\xf1vlTRa\f\x15\x80\xaa\xb3dځ\x03Ӗ\xbcȔ\n\x9d\x8f\\v\x1f\xa7\xa8힁\x91\x94\xf4U\x83U7\x0fV͋ \xfd\x81\x97\x81*5}\xd5$2\x1a\xbf\x89uC0\x1fw\xbf҇A\xebå\x91ή\aC\x0f\x97v\xd3\x1d\xeaE\x90\xe3\x13\xe7L\xbeSY\x92\xef>{\x06\xba4&\xff\xe9\xaf~\xb8MjF\t%ۇt\x9f_\a\x9f\x10\xe2O\\\xfc'\xf3,}\x83%\xf3l)\xf1\xe7h\xa4\fz\x9a%ۺZ\u007f\xc0\xd7\xf5\x91y\x01\xd4I\xa8F\xbc\x9e]݂\x8eՇ\x0e_\x06\xee'\xe0\x87\xc77~\xbeU\x86)\v\xd9\xfc<2N(\xc4;h-\xf8\x8eP\x9fq\u008d\xeb]\xb5aV%\xc1\x17?y\x18\xfey\x97N\xb5\xeb\xebM\a\x81\xf6\t\xb5\xf0َ\x8d\x13\x9ey[\xa7{[\xc8h\xdc1r\xa3#\xdc}\x1eB+:>̮\x8eׅ\xa0\xa0\v\xa5N \x97\"\n\xeb\xf1\tܖ\xd1\xe4\xf5\xc57A\xedq0\xaa\xf8\xb7\xe1\xe7\xeat\xf0#I\x8a$O*}\x11~\x14\xa3\xf1\xff\xa4\x8c\xc0\xf5\xa2T\x9a\x87\x12w\x84\xba\xaaD\xcfE\x15\x86\x1f\t7^\x14\xa8 \x9a\x87\x9e\x00ٝ\xed#D\xbe(\xbc%\xf2\xfdM\xf3*\xf96X>$\xf0\x90\x9d@p\x14^\x11 \x96\xb7\x93\r\xc0\xec\")\tzA\xec\xe3G\xf9\x84\xd6%\fb\xf4>\xa2\x13>\x15\xcfT\xb1^\x12}\xb7\xc7;\x11\x81\r\xb3\x18O\x18\x83\xb7ǘQ\xaa\xb3;c-/\n^\xef\xe4#7w\xf5Vt\x02\ts&\xed\xeb\x8aG'*\x01\x87-#\xc1צ\xc6\x1b\xc0\x8a\xaf\xde\x00Q%\xc4\x00\xc3^M'p\xdcc\x8e\xa2\"\a\xbc\xed-\xebW\xf9\xd5+*\x16m9z\xe6LԎ\xe3\xb8p\x91\xa3\xfd\xb8\xa3\x88\x1e\xf6힒\x12\xf0{ɑ]\x8f}\x1b}\x1c\xdd\x18\xe9(\xa2b\xef\xe20}\xab\xc3;ax]\xc0\x1a\x89\xd3\xd1t\x97[)\xc2\xc6Q\xe8\xa5\xda@\x97\xd8]\xd0\x05g\x89Д\x00\x9b\v\xbb\xb6\x1e\xa6vÉ7g\x1c\x06\xea㮆\xa5'fToJ\x95fȬ\xc6\xec\"\xa7R\xa2\xca\x19\xc3ۚ\xeb˫\x1bDŽ\x02\x13*\nS\x14\x1f?u\x06\xfe=95\xd9j\xa4U\xde!9F\xe6\xb19\xa7\xeej.\xde\b\x8f4\xbdp|\xed\xa0P\x89{wΔ\x9c\x86\x9a\"Nz(m\xdcW`\x8c\xb5\xb2yخ\xa1\xc1\xaa\xf6`Ű\xa2\x91\xcdKf\xe6?~\x1aF\xdf\xcam(ȑX\xc60\xaa\x86\xd9s\xe3r\xe9\x15\xa8\xed6\xa1\xf5D\x10#\x96P\x022\t\xd1='\xeb\xec\x80\xe0\x8e\xccH\xb4\x11\x01\xa9\x10\xc1\x19B\x11L\"\xce-\x1f0j\xe30d\x18\xefNG\x94\x8f\x98\xf7̏r\xb4F=/\xbft\xe3\xe4\x1du\x03\x00\xd3?\xc9\"J\xe2u*\xb1\xb8\xa8/\x97^]2Q.U\xb5\xac\xb9\xfa\xc8ԩ\x8f\\\x85\xe8\xb4|\xc8O\x87\x11Y\a\xa6w\x96/\u007f\a^\xdd\xff\xdb\xe3p\xe2\x969\xcbߡ\x8b\x1a%\x9cԞ\xe3\xf6\x05\xf3v\xb5\xcc\x1e%\x1e\xdb\xc7\xc8(\f\xfa-\xbc\xa1FʋkB\xbe\x02\x1e\x0e\x89e\x82Nk\xde=vuP37\x1dg\x02\xcf\xc1\xab\xef,\x9f\xb0\t\xec}\xfa\x0f\xfbQ\xceįK\f\u007fL\xc0\v\xd2\x11\x19\xb1\x1b\xb5\x02Z\xb1\x04\xec>\xbb\x06\xfd:M\x95\x12\xc2\xdaN\x9c\x11⏆\xfc\xb0\x8a/\x85\u007f\"[I}II}{R\u0085\xf0w\xefu\n\xebR\xe3_\x98\x80\xd2\xdcKn\xb0\xb6x\x88\x16RFmX`HS]\xc7\xce}G\x82ŝ\x83-g(\x9bK\x8dq\x05A\x8c\x85M\xd0\"\x89\xcf\x03\xf6\xb8\xf6\bqpn\x88\v\x938o|\x05\x835R\xb1g\xbc\x89\xf0\xf5\xcf1:?\x1d\x02M\n\x9dN\x01\x8f\xe8\x14\xad\n\x1d<\x82/@\x13\xb9\x88\xda\xea\x8a\x01U=\x03\x8b\x86x\x83\xcd\xdfoZ\xb9N?䞧\xef\x19\xa2\xd7m\x18\xf1Yq\x1d\x1d\x8e\x01\xfc\xc3\xfbo~Z\xc87\xdaZ\\\xf7Cѝ\xb7\xf9\xa6-\x99:\xb1O\xa6\xa6\x1c\xfd\xd34\xd5\x15\xc7u\xa2\xf9\u007f\x90\xfay\xa9\x91\t\xf5\xc3=Q\x05\x04\xb4\f\x01\v\xd0W\\A\x86\x18F[%2\x1d|\xc4\xfd\x95\xe3\t\xdcBbE\x8d6RM\xc2|u\xd5\xf3\xd9\xeb\x12\xc9\x16\x89B)\xb9~]\xa2T\xa0 \x0e\xf4\x88\x89\x1a\x9eu:\x87\x19L\xdd*|\x00\f<\xa0\xd7YR-fgg}\xa3\x9f\xfd\xf3L\xbab\x9eu\xfa}\xceaLW\xe5W\xacЈR\xbd\x951a\x80%\x17O0\x96<\xac;\x03\xc3,\x05\xbcA\x06[w\x99\x04\x91*\xe0\rX\v\x15\x95\x18'\xf2\x06\x81\x95\xdc!(\xa8\x0e=\xef\x17\xdei\xc0\xa8}\xa8\x80&?\xd0\xe3#\xae\x19^$\t^\x14\xd12)\xddm4\x15\xa1\xdasD\xd1\xc2E|g\x99P\xc3\x14b\xbb2\xfcD\x00q\x1e>\x91\x89\xb4\x93\x15\xcbn\x03.*\xe6?\xc1W̸x\x9f\xc8(Ļ8\xf4s\xfbD\x0e\xc1\x8d\x89SD<\\\xa3\xf4\"\x1e\x15\x805\xf93Ps\x14\aA90\x907\x13\xcc@\xb7R\xec\x10\xb9\x95\fF\xc3q\v1x\xc1od\xfc\x18YХ\x04&\xe1\xf3\x10\x85]\xfc\x14b\x12\x8c\x04nʁ\xcadb\x89\x8bz\x11y\xc6a(r\xe2j\xf1~\x9f\x00\x97\x87}@\xa2\xac8\xbf\x80\r\xab\x17\x8a\t>\x15\xbb\xb4\xc9>\x1a4\xa4\xa0J\x15\xf3.]\xb2\x0f\xd0\xc3R\x8c\xc6RŨ\xf4\xbc\x81\x9b\v2\xf3\xdb\x17*F\nA\x0f\xfd6\xc8r\xa4\xa4\xfb]\xc5\x16\xaeeH}KK۔\xbf\xadJ\x99\u007f\xfbҡ\xf4Ob\x1d\x0fƆ\xfd\x05\x8d\xc6\xe8\xd0\xe8\xefL\xa3\nG\xbe\fhN'\x16%+Sx\x89̒jU\x98,\x0e\xb3V/\xe3}\x8d2\x89D5\x98NwY8\x85G\xc9\xd0\xd2,\xa9Je\xaa\x06\xc1\x05\x16\x9bA\xac\x1eh*c\x18\x9a幔\u0082\xa2\xcc\x15\xf9\xe5\xd3wޡ\xcf.\xb6\a\xe5\xf40\xe0\x9b\xdc{D\x06\xe0x\x96\xa6\x01Sf\xaaѢ\x89\xc32\xbfw\xff$\xa5F\x96-\x01\xac:W\xc1Y\\\xe9\xf4\x10\xa5D,o\xf4Iy\xa0ך\x1d\x16\x93\xd2nN\x91I\xc5\x16\x85\t\xfe,i\xb0\xb2)\x16\xbdm\xb0#Y\xd1Ǫ\xe0\x98\x12\xafj\xa0U\x99-3\x18\xd5\xd6\xeb\xafY\x1b$v\x9d%%3\xb5Z\x91\xecp\xaa\xbc\x01V\U00092c97.#\xcfcNf.\x8b5\f\xa3\xd0d\xe6\x82$\xd8\xf6\xedC\x0f}\xfb\x90\u007f\xe6,\xc0KSצIX\x0e\xfe$fX\xfa\x02͊D\xb2\xf4M\xf0^uV\xa9J\xcb0R\xae\xef\xeb\x8cs\x030=t\x02\x18\x0e\xda\x19@k\xaaT\xe6\x12o\x1a\xc7\xf2RZ$\xe1\xe5b\xb5X\xc7\xce*e\xe5V\xb5E\xc4\xfcW\x12\xed\xcfϕ\x8b5\x92\xb2T0\x94\xd1T\xbb\xb3nk\xe4\x1c\xeb\xfcޑ\n\x13\xfb\xdb7&\x1f\x9b$2\xd1i\x12y\xaeT\ahF7\x82\xd6\xd3\xd3\xe0\x13u\xf5bqe\xe8\xfcy\x00\xd8#l\x92R\a\x18\x95*[)I\xa3\xd5\xf2\xf7\xfe\xebM\xba\x89k\\\x9e\xed\xea\xaba\xa4#\xbd\xfeu[\xd5N^\x92\xac3Vq\xacא\x10nL\xa9\x94(\x1cv\xcf\\\x8e\x1b\x91\x9e\x10f\xabT\xe2\xbc\x14GQ\x8eI7p\xe6\xcc=3?\x9a\x9bקw\x8d(sn\xfb\x15Y\x9aIS\xb2\xa0\x1fM\xe7g''g\x15\xd0\xcc\xc1aFm\x9aL*1\xa6\xa6J\xa4J\xbd2U,\xb7\xa0O\xa6\xaa\xa1\xa5}}\xae\x9c\xa0]\xe3\x94&k9-\xc3\x02\x0e\xc8D\x99\x8c\x88\xa5\xedi\x19-%\xab}jS*0\xab\x93\x94\x8c\x92\xf6XX\xad\xa7\xccW\xa3\x10\xab\x14b%\xb3\x1a\xfec\xf8\x9dR\x1d\xa3LR)\x95\x96$M\xf1\xea\xd2\x16\x87\xcdNK\xe9,N\x8e\xf2\xe1\x18\x94c\x92إ\xb1Udf\xf9\xfaI\xe8\xc2$\x15\xeaD\x16\xb9Ģ\xd6*$R\x8b\xd5 f\x9eLM\xb6Mu\xaeLձK\xb37\x96)lJeh\x9aZ%\x05\x8bV1՛\n\xa7ڒS\xb5\xac.u\xe5\xd64e\xd9\xc6l\x91J=\xb5RS\xb9j>\x8b\xdar\xf4l\xc6\xedڮ\xd3\xf2b\xfd\xfa\xde4\xbd\xfe\xd8\xe2%ǎ-Y\f]\xa8#\xa6,E\x83J\xc6\f\xe8\xf3\x12\xdb؈\x9a]?\xbc\x81S\xd1gz-K\x16\x8b\xb4\xea=\xa9\xf4:\x93b\xfb\x9b\x81\xc2\xd7\xf7+\f4\x83A|h\x1e\x8c\xc9FCR\xac(\xe4\xc4\"\x0e\xbb\xb6\x04\x12\xbdF'ch\xa0)\xad\x90\x88=\nEj\x06j\x96\xe8\x06\xa5\xba\xffR\x99\xdc7\xdb\ufae7\xe9\xdeW*J\x16\x94\x17o\x99\xc4J\x80\x88\xd6\xeaL2\x85lX\x9f\xf4\xb3\x06\xc3\xeeB\x87\x91a\f\x96\xdea\x90\xef\xafr\xd9\xc1\xa0:\xd4\u007f\x92\xf4Z\x96cůM\xe8\xb5\xcd?\xdb'\x97-\xeb\xa7V\x16\xa2\xe2\xd7\v\x83\xef\xf5x\xdb\xefn\x81\v\x1d\x1d\xac\x86\xf8]m\xeaP\xad\xcfQ\xa6Y\x88\xe5\x05\v5e\x0e\x1fS\xdb\xc30\x1b\xfe \x88\xd3Ư_?^\b\xed:w.r\x17MP\x11\tToܞL\"\xe0ʛ\b_\x87\xd7b^\x8d\xa3GS\xf8\b7e\xe8\xa9ZUd\xe4\xc3\xd7\xc3\nl\x06\x8cX\xa5\xd1\xdb\xd1\xd1\xe6\x16\xd9\x1d>\xafͧAGM1\t\x9b\xfc\xe8\x0e\x13\x82\xad\xe10\b\x85B\xf0ǖ\x16\xf8c(\x04B\xe10lEguK\vP\x87\xb8p\x1bl\nG\xdb\xda»v\x85\xdbh[\x18\x1c!A\xa19\xe3v\rqo\x0f9\x04\xf5\xa2\x17\x91\x9cb\\\x18\xa2\x88\xa4\xc1#\x15\x9d}v\xce@\x9c0\xfb4>\x87\xc1\x89\nB4ZQ)\x89?ݘ\xc1:>\x13\xfbu\x83\x18\x8dX\x18\xee\xa0 vn\x1b\xe6(\x80\xb1z\xb1HE\x84~\x1d\xc2\x19\xa2\xd8\bJń\xb1s\xd4(\xea\xc17Pz\xec\vXx\x8a\xa5@\xdc?n;\x16\xfa\xa3\b\xc1\xe7\x03\x0eE)҃\xc24\xeeE\xf8\x01J\xc0\xceA\x15CuJ\xeb\x94\x11yc>,Fu\xafU\xf7\xbai\x1c\xf1\x1a\x82\xc4Z:\f^\xa7\xbd\xab\xaa\xd8{\xb0\x1d\xfdP?\xf3\xd9cY\xa1ոOB\xea\x8ak\x82\xfe\x84\xa23Xt\x845\x9eP\xad\xa3T\xb8\x1dEr\xe8ׁn\xa0*\b~)pD\xfc\x11\x86\xc0\x18\v\xcf\xe2\x1fM\xce0\xe6\x1c\x98\x1c;bMA\x93폨p\a\xb5[인\x01\xbaւ\x1a\x8c\xef\t4\x89\xa3\x03]\x88Lv\xdcky\x96\x8a4a\x00\x14.\x94YB\\\x14\x83\xdbUE/\x145\x00\x1bl\x12bK2#M%\x03\x1aP\xa4\x8aJ\xb4\xb5\x11\x11\xbf\xca\x14v\x02W\x01\xfcθ\xf4\x03\xd3n\xecp\xb1\x9b\xa5\xd0\xf2k\xa9\xf2\x17\xe5\xf0'`\xeb@\x1d\xbb\x04\x9cɴ\xbc`iʌP\xf1W\x03\xea\x9a\x14\xa58Ġ\x0e\x01l\x99%\xcc\x11t\xaf\t%ʌ\x15\x02\xf7SQ\x02~V\x12\xfa\xa6\x95\xd4pj*\xb1\xba\xec\x04$\xf4w\x86\x8d^#G\x9c\xa5\xa01i\xc0\xe0\x106\xa7\x0f\xe3}\x17\x93\xf5\"vw\xe5\"\x96\xcc\x01b\xba\xe6\x13\xeb\xfezrMZښ\x93\u007f]\xd7].\x8c\xcb\xde\xeb?+;\x83z\xbb\x03\x8d\x83\u007f\xa7\xe8#\x98\x91#J\xfd\xcf\xcf\xf8z\xc6\xf3\xfe\u007f\xbf\xe4\xe7\x9e~:\xa2\xdc\xfevv\xf6\xdbۻ\xf7\xa7\xfe\xff\xbb\xfe$\xe2\xed\xae\xff\xac3\xdd1\x9b~e\xf6\x1d\xff\xbb\x8e\xe4ݹ\xd3+t\xa1\x84\uf822J\xb1G;\xae\aI\t\x04\xc5\x01\x8f\xd8mW\x8ay\xabؤ\xebq\x97k\xeb*\xf9dƜ^VX_<:7''wtq}aY\xba\x99a#\xb7\x8a\x9d\xdc\xf5TH\xab\f\xe33:\x84\x02\xcd#\x1bC\xb5y\x95V\x8b\xc5Z\x99W\x1bj\x1c\xd9\x1c\xb8U\x1c֕\x89?\x94\xa0;A\xa1Y|\x16\xfa.d\xb77\xe6R]\xe3\x16\x02\xa8\xd4&\xbcODh<*z@\xe7\x8f\x01\x8e\ti݉Aw\x11\xf1\x05N\x0e\xe8A\x02\xd2%L\n@\xa8v\x91I0\xe3c\xd0\xe2\xc8\x16*\xf0T\x91\x83\x03\xf8\xdd.3\x8d\x96\xc5\xd29R\x12[\xe4VJЩ\xb2\x88\x13\x0f\xaf,\xad\xea՜\x9eb\x9b\xbaM1W\xd4R\x1f\r\x0f\x9f\x03߫\xdb>EƉ\xb6N,\xf6\f`õ\xbe\xf0\xf8\x82>U\x1e8\xccz\x02\x9f\xdb\xf2\x1d\xf0\x92\xbb\x02/{\x93\xb32\xc03\x19Y\xbf\xe0h\xdb확b\xba\xca\x13^\xe1\x1dāpQ\xba\xbf\x90\xbf{\xea/\xdeRX\x97\x94_߲d8Ȭ\x99\xde6e;\x98\xb8\xceзk\xaf\xa7\t}\xe3B\n\x03r\xe1fq\b\xb6 \xc9 \x0e\xc2\bHˠf\xf1ŬD\x1c\t\xe7ζ\xf0\xe3%\x12\xcf\b,\x99\x1bĬ\xfe\x84m\n?sx\\\x95\xadj\\\xd5\x01W\xc8W\x8bUqC\xf4S\xe9~\xbe\x8e\xab\x12\xe2m\xcflY\x94\xa63M\xd9>\xf3\x1eq\x9d\xf2\xf6\xa1\xd1\xfa\xdes3`ػo\xd6\xe0\xa2\xedSL\xba4.\\剶\xd0jl\x1e\x1a\xfd\xf1\x06u\xd6[\xeb\xcbI\x87\x9477\x1d쵥\x80\x9f\x88\xdd\xe8\x8f\xf1\x04\xf4\x0e\xcf\xeb\xfd\xcb\xd9\xedS4\xa2m3\xa123\a\xce\x19\xd2\x1cȧ\xa9ꑳ\xf6\xa5\x83\xa7\xa7lg\xcb\xe3\xfb@\x82\x0e\xb0\v͢\x03\xa9\xc9؏1\x87\xd7W\x82\x98%`\x17T\xc6;\x91\xa6\xb9\x98\xba\x12ω\x18\xcc\u007f\n\xf0ExC\x86t\x19\x9e#\x18\xbd8*\b\x18g\x1c\x96\x9a3\xc40G\x02x{\x92!w\x05\x1b\u007f>滢\x1cx\x89i$\x16\xf4pl\xe1ɣ\x15\xa6`\r\a;f\xed\xdb7kA\xee\xc0\xb1\xfbfy\xf2\xe8\xc5h\x00\xef\x9b3\x12>>\xee\xee\x83G\xad\x19U\x1e\xb3\x1e4\x14V\x80\x10\x0e\xc1O-\xda\x1c\xb5\xba\xa2H\xaf\x05M\u058co\xa3K\x93\x8c\xbe\xda<'\xad\x8c\x92\x15)m\xba\xea\x99?\xa7\xa1\x06\f\xcb\xf1\xa3%\xe8{[2p\xbb\x97\x16\xf7\xf5\xb8\xe0;\xe1\xed\x85>κ\xa4\xafK\xba\xef\xc2>\x8de}\xfd\xac}\x9a\xbf\xee\x9b\x15\x9dڸ\xd50\xc2D\xbf\xd5\u007f\xa02`\xf7TI\x0fH\xeb\x8bnP(\xb0A!6\x1b\x9cƢ\x90\xe4\x882\xc0h\xae\x89k}\x99U\xca3\xa1\xdaY\xb5\xb3ެș\x1e\xa1t#d}s\xe9\xfb|\xb5\xab\xed\x85\xf0\x92'\xd8\xcfs\xfe|\xbf\\\xf1P_\xf6\x00\xcd\xf6ξGփ\x19\x04\x1f\x0f\xf5$\xd0\xe9į\x1c8;\x99\x15\xfc\x11\xdcB\x18h\x8aQ\xd7\",\x17Ƙ\xc5\xe0\x86\x06{\f5\xc9k'Z\x15\xb1U\x01\x1eָߚ8\x8c\xce\x1c\x13~\xad)\x9f\x97A\xf7^\xdaR\x0f\xc3\xf5-\xf0\x8b\xe8\xa7\xf5-\x8f.\x03\x0ffG\x1b\xa6\xee\x16W\xb6ԋZ\xc7G\u007f\xeb\x0eE*\xcd.F\xad\x91zӘP\xa4\x15\x85\xc5\x03\xf2\xe8\xf0\xd8\xcc\x12.$-J\x83}\xab&\xa0\xb1\\\xa8V\x80\xf2\xa4T\xacTnv\x89\xa8\x92\xc2\xc8\xdf\xee?\x03\x0fa\x8f/'\xefn\xa9\xb7-{4\xbcyʐ\x19\xb6\xfa\x96\xeb\xad`ʡ5\x8c\xa2\xd8e\xb69<\xfa4\x97\xcde\xceU斕d\xaaT\xad\xa9\xce\tU6\xb3\x8b?\xac\xf0\xa4\xbcA\x04X\x02&\x1e\xe6튨Řf\xa15?\x1aM\xe4\xe0\x8fA\xbc\xa5\x80\x18\xd4\x1b6\xa8eb\x90$\xd8d\xc9\xc1`\xedt\a\x13\a\x93\xd2%\x04Q\x83\xe9p3\x15\x05\x80`\xa8\xc7s\xbeb3\b\xc4\xc1N\x18\x87\x0e\a\xc1\xbb\x83n\xd3MSp\x8b\xf9U\xe35\xebG\r[\xa7\x1f6C\xbfn\xd8\xe8\x8d\xcaq\xcb\xf9\x95Ҁ\xb1 \xbd0y\xe6\xbe\xd2\"\xc8U\x8f(t\x95K\x1e\\\xb3SR\xee*\b1\x1b\xccS$AW~\x15\xb3\x98g\xc5S\xc5\xc5v\xfa\xb9\xect\xd0QR[\x8c\x86\xea\xd9\xd0\x00\x86\r\xe5\xbb\xcb%\x8b\xcd\xfb\x98\x8a\x1b\xd4\xc4Z\xb0\xb3ԛg\x04\x9f\xa4X\xc7o\x91\x8e\x983c(|\x10\x9c\x18:c\xd1(\xe9\x9d\xe3\x93\x1c\x90\xe2s\xd4V\x99l\xcf\xcc`\x8b\vn\xf0\x8a\xc2\x05\xae\xe8Hz\x8c\xab\xa0*_\xa5\x88~\x02\xeeuz\xabP5\xa0\xf8\xacX\"\xd6ݫ\x17\xbf~P\xab\x14\xf4\xa0]\xe1\xe0\x88\xc9#jDy\xf0\x02\xfc\xf1\x8d%K\xde\x00j\x90\v\xd4$\xf4\xd1-v!\x98\xcaF\xbb\x16~3\xf02ܪQ\xaa5`.|\x00\xe7\x83ap\x92\xd2\xee\x9b>nw\x86\x94\xf1/y\x03\xfe\xd8#?X\xdb##\x14J\xacw\x1e\xa25\xc4\xd3\x15(\n\xf8\xf3\xb1\x91\x1f\x9a\xa0\xb8Nx\xa34슩\x02q\x87\x1eV\xe0\x15\xec\xff^\xb2\x9b\x9a\xa6\xc7\xfe\x11=~\u007f\xb3R\x96'Ҫe,\xabҧX\x9d\xba\xba\xc9M\x03\x9d}\xd5j\x99J-\xf6)T\x8c:\xd7א\xb7\xe7w\xaf3r\x94T\x9a'\xd6\xfc\x8b\xa4\xbb\xdfx\xdd}scF\x1f\xbcy\xf3\b\xe47k\xb5\r\n\x96V0\xac\\\xa5\x94\xf3S\a\xd5M\xb1(\x952@\xcb\a\xebu\xac:-Y\u007fzǮS8\x95\x92\xf9W\xa9\xd8\xc2[4;0\xdc\xe2\x1b\xe2q\x14\xba\xd1Ʒr6\xa2SBIX\x13\uf580\x80\x84q\aL\x12\xc0\xa3\xfft\x1b&t\xd1&\xfa\xc8#M\x03\xa0\r\xb4\x9d\x86\x9f\xd1G\xe8#\xd1&t\rڠ\xed4\xb07\xc10݆\x85\x9c\xf8\x06I\x86\xa3\xd3p\xa2X2\xfc\xd8\xe7M Lu\x93\x1b\xe1w\xba\x11\xe9Do2\xf1\x12`\n\xb8%\\\xc0\x1d\x90\x007߳\xeb\xd2g\x81\n^mlm\x82W\x81)s\xd4\x1aX\xc6\xe4\x827a\x19\xfco`B\xb1\xc0\x04\xaff\x8eb\xeanQ\xc9\xe7\xb01J\xe3)\x94\x04?\x18F\x8fT\x817ѣ\xff\x8d\xb2;\x85\xb2C\x0f6\x82\xeb\xb7\xe8\x94XV}EBq\x19\xa8\x9c:\xca\x12\xf3\xb2ٗ\x1a\x86zh\xb8\xbbW\x80\xf8\xae*\x17S/\xf3\x13'\xc2\xc4W\nI\x85\xa9~F,\xe4\x15\xd4앀\x00\xb0\x01\f\xcdUd\xa5\r\xc5A:\xaeɫ\xb3+\x89z:\x96\x06b\x8d\x0e\xb44'\xf0Ŵ\x8f\xa8\xcd؉\xf3szk\xc0\xe5\x0e\x04ܮ\x00\xbb.08\x10\x18\x1cq/8\xb2\x00\xfd\xb1k\x17\xd4\x0fY\xb8\xe0H\xa4\xef\xd1E\x8b\x8f>\xf8\xf5Qv\xdd\xd1ŋ\x8e\xa2\x8b\xc8g\xf0\xbfO\xdd~aժ\v\xb7\x9fb\x1e\x83\xf0\x03x\x1a.\xb9\xb0\u007f쨽\xe7\xe8\xa1\xf0'\xb8\x0e\xbbT\x00\xabY\xb0&7(\x99w\x00^;\xb8\xf1\xdb\xfa\xfc\x06\xd9\b[\xfdՍ\a\xe1\xb5\x03\xf3$\xc1\\0w/\xb8\xef\x8b6p'\x9d\"\xbc>@\xe3\xb7\xfb'\xe0w.X\x00H\x19Zɋ\x8f\x02\xf4\xfb\xfa(\xcc\x04\xab\x81j\xd5\xc5\xf6\x8b\xabX\xd9\xfcyc\x0f\\X\xb2\xe8\xfd{'Dy\x1c\x8d>\x03z-\xcbz\xd7x\xefy\xe9>xm\u007f˔\x92\x95\xc6ۜS\x16\xec\a\xe2\xfb^\xba\a\xc5O]Ђ\xfa\xcc\xf4\x1b\x14{\x80\xd0E\x1d\xd6\x17&`\x8d\xe8`\xd0w)\xe7\x00+\xc0\x1e\xc9ySL\xf9\x1d\xad>c\xca\xe5\x01\xacu\xe4a\x04=$+\x8bh)V,\xb2\x02\xa67\xdc\x02\u007f\x01R\xb0\x1cH\xe1\xbe\x17֯\u007fa=\xc8U\xb0\x8a\xcc<\xf7\xa235@f\xb5\xca\xd3F\xa6\xf59\x03\u007fN\x1b\x89\x82i@6\xe0݅\xee\xbcL\x94D\x9aQ\x10\xb2s\xfa\xaa\x01-\xa5c\x1fr\xba졂\fz\t\x90\xbe\xfc\n\xca\xe9\x97W^\x06\a\u05cf\x1f\xb7~\xfd\xb8\xf1чS\xf22\xb2\xec\xc95\x86\x01$\x17\x85\xd5Z}\x06\xfe݊\x02#q~\x86\x9ad{VF^\x8aުԚY\xa5\xc3l\xf4&'\x9b\xb5Jk\x02~\x18O\xf9\xa9 \xd1V\x8d\xef\xda{\x80\x88W\xd2\xe9\xae|\x12\u009aG&\xac$\x84\x9dd\xa1\x19\x15]\xa2\xa3\xbf8\x9f\xc6\xfc/\xadv\xd9Dj\xa3\xed&\xf1\xf1\xfd\xe37\x8c\x1f\xbf\x01x\xa5\x19\xbdҤ\xaeU떦\xa4\xa4\xf5ʐ\x1a3\xfb\f\xbb\xdb{W\xa1\xd1(1\x96\x1bO-\x1c\x84\x8e\x12\xa3\xf1T\xf1\xf6\xe1}2\xfb\xbf\x06\xff\xfe\xdak@N\xafH\x84:e \xcei|\xf4\x17}\x12\x97,N\xca\xcc\xd0j\x93\xb9$}^\xaf\\\x9f\xb2\xf8\xae\x82X\x06\x8b\xea\x84,_+V\xfar{\x01-\x90\xbf\x86s\x03\xdfv\xc77\x15d\x10/\xa0zk\x05\xbfux\x91C4\xa1\x119\x889/\xef\xe4\xc8%\xa0\x93\x15\x15\xa5V\x8e\xd9\xf2\x15<\xfd\xe4S\xf0\xf4\xd7[ƅ\xe8\xd3\xf9\x0e\xb0\xc7ٷ\x10\xad\xfd_\x85\xaf:<\x85}3\xc0^;\x17\x1e[\x19\xbd\xfe\x14l\xfdz\xf3\xe6\xafA\xe8)\x9a\x0f\x8d\xeb\xb8d\xc7\x00\x8b\x85}\xed\xf0\x1d\xe0\xb7\xf7-\xf4\xa6\xc3U\xf6\x98\x8e\xfa\xbd\x88\x06\xcc\xc0}\x8e\x03\xd8\xd4\xc6\xe5sQ\x18\x10\xba\xd8\xe5\xb3\x1b\x94\xb4\xc9H\x99\xb0\x92:\x8dz\x9b\x8f3\b\n\\D\xbd\xce_\xec+B\xab\x0e\x14\xc53F\xad\txh\x94\x00\u007f&\x8a\xe7>\x84\x97\x93\xe1ϕ\xc0\xd7\x00\x8f\x8d4\x8c]\x9c\v\xe8\xfe\xee\xa1\xc5j3\xb8=/\xed#\xa3\xee\xc3T\xd7Q\x1a\xf4\xeec\xb0ϱͫH\xaa\x9e\bB\x17w\xeb\x82\v\xed\x17\x15_\xf1\xe0Ee\xff^f\xf0\x1e\x00[\x83џ\xec3\xe8\xe7\v\xa376\x02\x00N3\xfaw\x8a\x16\x8d\xe4\\\xe2\"\xdaR\xe6\xe8\x15\xd91\xb5\x1c\x1c\xccv\x83/}}\xe9\"\x90O{<\xfd\xfeZ\xfd\xe1\xde@!\xcdg\x88\x00(\xa4\x83E\xb0\x9f=\n5\xccuW\xa1\x12 \xaa\x92\xcbn\xef\b\xd5&\xe0iK\xa9$j!\xe2jw%P<\xbc\xf2T\xb2<\b\xb2N=\x8f\xb1\xb1Q\xfb\xa3Z\x92UA\x1a\xd9nŀ8\x042\x1b\xd1+\xb2^Ra>?\x801\t\xd1E>\xf1\xec\x879\xdd|\xb2.\x10\x11\xf7mV\xec\x0f\x18\r\xe5\n40\x05\r\x8f\xc4\x19\xbb\xdbl\xc0\x84\x97\xe0K\xf0҇k\xd6|\b2A?\x90\xf9\xe1g\xb7\x98`\xe8\xf5f\x17.\x8e}\x18\xddW\xe7\x1e\aF\xb5\\\xa4\x93\xcb[\x0eXQ:\xaeJ1\xb7D\xa2\b\xd5~\xbaNN\xe3*(\x06|C^\xbe&\xb1@\xf4\xda\u007f\xc6G\x81\xd8\xdcj\xa4\xd21:\x0e\xc0;kN\x17\xfa\\\xfe\f\t0\xb2\x01ƅf\x12\xb5Ө\xa5\x11\xc5p\x02?\xed\xce\xc0\xf8$\x88\xb00\xb7\xff\xf8\x87o\x97G\xcdG\xe0\u07fd\xf0\xbb0\x98\x87\x16\x8dC\a\x00は/\xc0\x87\xde\x12\xfd\xae\x8c\x99z\xee\xee\xaf\xe1\xdf\xc1\xdeF\xd94X\xd2~\xf2d\xfbI\x11E\xaf\xd8\xf4\x83[\xf2\xf0.\xf0\xc8\xfd\x8f\xc39љw\xefI\x85\xe5\xf6\xeb`\xcd\x15 \v샧\xe0'\xd1a\x1b\x95\xf4\xfc\xf5\xa0b\xa9\xe8$~\b\x8f+\x1a\xf7/\xeem\xb2\x9b`\xa3\xdc.\x1a-\xac\x99 \x16Q\x04\xf0\x18b\x88\xce'͛\xdc\"+6\x04\xc2X\x1bJ\x16̓n+\xc0fA\x1e\x1c0\xa1\xb2\xb3\x94\xceH+\x01\xcbl\x86_\xc1\xbesʴ\xfd\xee\x9d!\x93-Td\u007f\xbfؿ\x9eO\xae\xf5\x8e\x10\xabdɜiL\x89j\xab\xd6\xe0\xad\xcf\xf2N\xa8q\x96\x97J\xd0\xf2ɘe\xee\xfd\xe8\xed\x03O\x1e\xd9;;%G\xdc'o\xd4\xd4\x14\xd5\xce;\x00\"),=\xe2\x81K\xf0\xea\r\n\xe4][\x0f\x86\x83\xbe g<\xfcF\xc9h\x86.\xa4\xf3~\xdf[\x8c\x18?\xc0\ru\xf0\xa6\x02\xe9\xab}r\x06\x95\xa4\xf0\x12\xaf\x9bf\xcb2h^\xab\x103\x13\x87\xca\xcas\xd2j\xa6\xfbƾ\xfb\x84\xcb5\xac\xffq0f\xfe 8\x1b\xbe\xb1\xe6\x06u\xe5Ĕ\xb8,'\x86\xe3\x1f\x10\xfc5\xb2D\xc5\x15k\u007f\xa2\xf9)@\f?\\\x98\xe0a\xd8\xd9^\xe8\xbb\x01=M\xa0\x14\xfcZ_1\xed&\xbe\x15\xb5\xdc\xc5c\xaf\x1f\x84\xdfM\xaf\x1dͲ\xa3k\xa7\x03\xfd\xc1\u05cf\xdd\x06\xcf>\x9a\xaa|\x12\xfe\xee\xcbM\xb8o<\xc7<\x02\n\xc1\x83\a\xb64/\xbdc遷\xde<\xb0l\xf3\xb2ٛ\xef\xe1,\xf3v\xad\x19\u07fe={{\xfb\xf85\xbb\xe6\xcdY\x0e\xc4{~\x00\xd5'\x9f\xc3=\t,\x8b\\k\x85\x8f\xad\xae\x18^\x02&\u007f\xf9'0\xb9tX\xe5\xed\xf0Dl}\xa2F\xdf\xedG*\x87\xf2Q\x15T?\xe2\xef\xc6.\xacZ\x11ۂK\x8d\n\x89u-\x02Z\xa7\x88\xd1Rhu\x82\x81\xcc0\f\x8e\x91!$\x1b\u007f7@d~X\xc1\x15\xd8ɢ\x16\x11Ŏ\xb5\x1f\xef\x99\xf2x\x11x\xb8\xe4+x\ue457\x1f\xfd\xf2\xa1\xef\xf34\xe3\xde\x02\xfa\x17\xfeV\x01^\x04\xc9V\x15u\xe3\xe9P\xf3\x88\x82\xdai\xfdf\r\x9f\xb3\xeb\xb6w\xfbz\xaf\xbf9i\xe4\xa2{V<\xef\x99\f\xaeї\xb8Kw\xef\xf8#=\xaa\xa4`\xd7\x1b\xe3\x87\xdf\xff\xf7\x8d\xc3\x16\x03~ёޏ\x82\xe6_\x86\xc0\xefф3\x11,1\a&W->\xfe\x1cxj\xd8\xe4~\xf9\x8f\xce\xdfܱj\xe4\xf8a\x03>\xddt\x96\x1ex\xd7k\xaf\xc5\xe5la^\xf03\x82q\x01n\xb9\xabi\xb8i\xbfЗ\xb81M\xe9\x14\xd7Ɏ\xa5H\xd8͌\xda\x00و\x88\x90\x8d\b\xd0\x14\xb5\xe1\rKQ\xa8j\x02\xb01$a\x04\xefg2g#\x82\xfeK|\xbf!\x1c\xd3y\x11\xcaeD\xf3\xe2\x9fQ\xb9Lx\xe7X\xe7\xc5{i\x82\x124\xfa\x1f{{V\xa7\xb9\xa3\x9f\xe1\xb0N\x9f\x9bl\xb5\t\xae\xafѨr\xba\xee|\xa3_I\x86G\xc9$iu,\xed\xb5\x96N\x84?\x16TW\xb3߂bt*x\xfa\x82\x1a\xe6\xd0\xfa\xecA\x81\x95u\xb6\xec\xf2t\x87A\xaaՏ\xe8\x9d7\xa8\xd4\xebЀ\v\xd5\\84\xa2d\xe9\xc6ه&\x8e\xd6I~\x18\xfbXsu\x01\x97\x84\x1fl\xff\xb6\xa0\xfa\x030eZ\xde\xc0~\x85rsUJ\xf5kG\x8f\x9e\x19\xec\xca\n)\xe42S~\xa1m\xea\x93\xc2\xfaVy\x83\xe2n#\xf2\x92~\xd4c\xd4\x1bhV\xe5\x05\x88\x10A\x15\x1a+\x90c%\xee\x98Y\x14Y\xc4\xe1 Z!\x18\xf9\x9b\xadW\x021\xd3\x15\x93\x91\xd3\x13\x88\xe2t\x92\x89\xcfA\xf21y51\x8b+A\x95\x1dE\xa6\x818\xec\xb1\xe0\x8bI\x13Co\x13.\xd1\x1a\x12\xb7V\xec3\xea\xb1\xe5[\f'\x06\x97\x811\xea;\x8b\x8aS\x13\xcdv2\x10Q\x8d\x16\xec:p\xf4ؽ{\xe6/\bf\xcb\xd9b/\a\xb4\x96\xa2\xe9\x93\xc3\x1bvܽ1\xda\xe8l\b\xa4\xf4^:\xa7\xa1\xb0\xa8f\xfc\x90\xf4\xe8\xe1\x91\xf9\xb9\xc6\xe4\xc9y%\x0f\xd0\xfa\xfc\x89\x9d6?a2Gy\x89\x86\xd6\xec\x04\x9b\xd08\xaar\x97mng\xc8\x19ô\xf4\xc50.\xb9\x1eׂ~\xe9\xafX\xabnj\xb5\x88\x8b\xee\x98cpD\b1\xb1\x14N7\x12\x1d0%\x84\xd9p{\x98\xa1\x12\x90\f\x12\x82\x1cUWܥ\xbf҄\xc9oS\xec(آ\v\x1a\x85\t\xe1v-6=\xa4C=s\"\xc1n\xed\xa3\"^\x0e\xbcD\x83͐8'\x14\x19\xb1\xbeݿ\xc6\x02\xfd\x17\r\x8aڊE\x93BTP\x1bAE\x88\xa0U!\x96DwU\x9dI\xf4O\x15\xbee\xab\xa1\x18p$\x9eF\x1b\xfd\x80\xa5Zo\xaa\xb3\x10\x1e|놪\xeb\xde'܈s!}\xc2\xd9\x05q\xe6\"T\xb9\xd3\xf7P\xcc\x0e\xddd\xd4\xff\x9f\xb5\xc3(le\xfe\xca+\x82\x8d\xf9\xab\xaf\nV\xe7\xf1\xebW^\x91Dl\xffY\xd3\xdcs\xeb\xec:\xafa\xdb\xff\xae\xbd\xf4h\x1d\x95I\x95`\xacX\x89\x00\x9a\x14k\xa5\x98\xb5\xfe\xffU\x03q&HI\xcdR\xd8&\x14\xfd\n\x10\xea\xd2\xd1\xf4\x9f5\v\xdd\x1bR\x12\t\xb0\t\r\x82r#\xd9F\xcb\xfe\x83\xc6\x00\x9d\xf0-\xb8\x8f\xaeM\x80\xf5\x14\xfe\x80\a>\b/?\xa6}\xbcD\xca\x00\xa5Le\xe4\xecJ\xa7\xb9\xa0\xa0\x8f{L\xf4\xee'\x80\xfb\xb1\xc7:\xedy\x13\xca\xed!\x88\xae=l\x83\xe2g\xbcw\x82\xc6K\x1a\xc6sC\xfc8\xe6\xcb3\xfcj\x17\xd0wV\b˩}.\xbf\v\xbb\x94\xe0\x02\xc4'\x15v\nc\x05\xb7\xac\xd9U\xd8\f\x0f\xbd\u007f\xf7\xbaQ)I\x9e{W\xe6\x94\xf6-\u007f\x0fLy\xff}0\x14W\xb8_훰\xbd\xb0\x92S%\xb1\f\a\xa4\xb4\x9c\xe6\v\fYIV١g\xbbD\x1d\xf4\xb37\xd7;\xbc\xf5\xbb;Z\xde\x1dX\xd44vh\xc5\x1c\x97H\xbc\xf5;\xa0\xfd\x0en}\x025\x86\xf8\xc9>J1\xa23\xac\x9aU!\xb6P\xec3\x95x\x06d\x8e\x06\xa2}\xeb\xbe?1mډ\xef\xc9w\x94\xb0\x14\xf7\x0f\xd4\x03E\x94\x94R`*\xadA\u007f \x19\x9036\xe3\x85\xe8?M~h\xc0\x8d\x06\xee\xe8Ix\x89Y\x16=\t2\xd9\xc38L\x0f\x81\x97q,\x91\x1b6\xdch\x15=΅\x88\x1d\xba\bP\x8et\xc6\xc5\xd0\xd8{k0f\xf5\xaa\x15\xd67\x01?\x8a\xd4rF\xd1\xe3R\xf8\x1a\xfc\xaf\xaf\ue69c\xdb8`\x84v\ue824G<\xf7\x8d\x98\xb8ؔk\fTzgL\x13+V\x94\x86\x96\x83a\x1dL\xfbwp\x12\x1c\n\xf8#\xa0\n\x88\xea&\x1b\xeeɼS,Y\xbb\x15~>\xf2\xfao~3b\xab\x19\xdc!\x13w\xaecE\x02.\x83\x94 k\xdb\x01\xa3\xb3\xa3\x0e,\xa2\xda)\xb6\xfc\x93O\xa2\x9b>\xf9\x04\x94\xa3\x89\x81\x02\xc7\xe8e \v\xfe1z\a<\x1f\xef\xd7\xf1g\xb5T%5\"\xf6\x98\x9f\x9f<\xa9\xacaIŽRZ\xa2P3C\x9dy(\x97Q\xc1\x810SrO\xf9\x12\xf8\ryI#l\x92YeRivff\xb6T*M\x93\xe5\x14I$E\xd7\xf0\xcbF\xad\"}\xba\xef\rZ\xf42j\x97\x02,}\b2x\x1b\nk:ح\f\xea\xd4\x1a\x91\x1c\xb1~\x18\x94(\xa0\x04\xbc\xdd\xefa\xf3\xd1\n\xaa/P\x8f\xd8\xf9\x1a\x00{\xbe\x01\xf3\xe67w\x1c\x043\x1f\xf9\xc3\x1f߮\x19\a\xbf\x87\x0fl\u007f\xf5g\x9a\xf9\xf2\x0f\x05\xbd\xd5\xf4J\xb1-8\xa4\xa1\xdah\xdc|\xfd\xcd\x03\xf4W\xab\xbfyw\xef\xc8?\xbc\xf9\xf2\x8dW\xe6\x1fm\xb0\x99\xfbx\xe1\xe6\xc0@\xda_\x03\x9a~\xf7\x13\x18>\xb9\xf7\xfa\t\x83V\x0f*1\xab\x00\xe0\x86\xac\xbb'\xde_\x89n\xbd\x80F\x9fBQ\xa8\xa7\xc5X\n\xdc!\xb1\x11I'\xb3\xe4\x95P\x13\xaa\xae!\x06\a\x1bq`3\x15\x11\xe2Q\xfe\x81\xe2ltS\x14\xab\x98\x83tb\u0082\xb8\xa0\xb6\xb6\xaa\t\x9d\xba\x9d/\x13\xbb\x95\x02<\xbf;ɖ\x1c\xee\b\x82?\xc9\x00\xf1&%\b\xac\x11yD,\x1eeOp8jb\x1c\xd8>\xa5\xc8\n\x94@T\xf0\xd1\xc0\x9f\xb7ᄊc\xc4η歿Z\xf7\xc7y\xf0\xfew~\x03?\xba\xb0z\xf5\x05\xe0\xfa\xcdE\xb0\x00\x86\xe8g\x17\xc3Z\xf8\xc3sq\t\xefs\x80\x05\xc7n\xbf\xdfݴŖ'\x97\xe6\xfd2\u007f\xf9\x9d;\xae\xed\x9a\xf7\xd6\xce\x11\xb7\u0379\xfd\xd1\xd6\xd5\x17\xe0G\x88z\xa0,>\xa4\xfb\xc1#Q\xf8Q\x17\xad\x84?_\x85\x8b\x8f\x00bN\x82\xdaɆ\xea\xd1\x16\xc3Ӎ\xe1\x11\x04\xec\xc0\xad\x01i\x88\xce\xd1v\xc0\xed\x8e\x1e\x18njj\u007f\xf6\x05\xf6~\xfd\xee\xe8w`\x1c\x94G\x1e\x05S\x99^`\xdd=\x91O\x173c\xa2\xc9M\x13#\x0f\x81!\xf4\x9aȧt\xafxۄ\xb9\x1f\xc9~\xee\xed\xa8\xa3\x10\x8f\xe4\x9d.k:\xc3\x1c\xb6D!\x9a,茮\x11\xbf\x1a?\xfb:\xcfA\xda\xe8\xd5t\xfa$6\bp9\xe8\x98*\xec> bi(\xf2[\xe9nϠ\xb3A#\x9c鰺I\x8d\xfeh*~\x8e\x86[\x8e\xb4Dqt珓\xf3j`\xb3\xe7\xdamy.\xc3 \xb5\xa67\xaf\ue5e2\xad\xd1e\x16\x015/\xe7\x12\xd3\xd2\xea6u\xd7_T\rBXa\r\xb6\xd2?\xaa\xd5-t\v:\x90\x9f\x88\xc7\x06\xbf\x9bU\x0e\x93\xcdfr\xa84R\x95J\xfd\x81J\xa1\x92o\x04\x80\xe1E-\xb1\x84\xd1\x1d-j\xc1\xc7#髳\x04\x04,\x81\xdd*\av\xa3\xc9\xca\x11\xbe>\x0e\xf2&\xac$Q?㰗.;Q\xf8\x11\xbc\xbe\xa6 ]'\xa5\x15\xa3\u05ec\x19=f͚S\xaa'\x97\x0e\f\r\xce\xee3rx\x83W\xa9˯\xf4f8\xf2{\xb9\x95\xe9\xf9)V\x1aLo0\xe7床\xf2\xd2\x15|`\xcc\xc2;&\fޱ~Riqì\x99^OMN\xaaT\xaau\xf9G\xf9\xd5:\x00\x82\x83\x9dI.\u007fA\xaf\xd4\xe4R\u007f(\xd0\xcf_\xe3M\xb4\xc3\x13\xec\xd7o\xda=p\xf6\xb8Nt\xc4M\xb7j\x957\xc8\xda\x13\xa0#\xe8~\x15\xee\xe9s\xbb\x89&#\xb9K(\x14\v\x83\x1b=q0:]\xea\xf5p\xaaN\xc78D\xe3G^\x1f>\x92\xc9H\x06\x14Y4\xe1\x03\x95\x9c\x01\u05fb\x8a]\x88F\xa3#\x86\xe3\n÷,F\x83\xc1h\x01\xa5L\xff\xc8u\x86O\xb2'zܴ\xff\xe6\x06%\xf8\x9e\xc0\x14*\x1e\xbe\xff\xf3\xcfcvv\xf8d \bE\xbd\xa8\x1alg\a\xf0\x14\x95\x03\xe2:\xbf1\x0f\x18h\xeer3\x1e\xc4\x11\x115kg\xbc\xe4Fa\x94t\x86u~\xac\xe3\u0088\xf0\xa4\xe7\a\x8c\x83\xe8m\xc6>\x03џ\xc5z\xb19q\x94\u007fL\x9fI)U\x8b\xc4\x03<\x1d\x94g\x80x\x91\n_\x83if\am\xa3\xb3\x8a\xf1љ\f\x8e`\xc7\x17\xc5.\x10\x8e\x9d\x9bl\xb4\xa38\v\xdds\x98\xb9dg\xc7\xea\xf1\x1b\xa6鶍yX\xd0W\u007fx\xcc6ݴ\r\xe3e}\xf3\x1eư_(\"\xaf/\x83[0:\xcbӻ\xb7\x87އ\x82\x916:\xcb\f\x8e\x98\x1dl\x96\x196%\xa7\x87P\x18\xc3,4\x91\xe6\xe9\n\x1bP8\x8bu\xe0\x8b,:\x9d\xfd\bN\x05/6\xceǷ\xe77\xc2\xfe\xe0\xbe\xdc\x12\x1c.A\xfdߎ\xfa\xe5gd\r6\x04{\xc8r0x\xf3\xcb\xce؋LF\"\\b\x886(\xea\x15\x8e\xce\x10\xee%D\x8e\x94\x10\"`\xdbF\x9e\xf1v\x86p\x0e\xccg!\x18b`\t\x9f\x04_\f\x81\x80J*eK83|q(\x9fԦ\x96J\x98\xc1\x10\x85>W\x91\xd0\xdb\xf8\x84R\x82\xfe!\x1c&)A\xff\xa1|r\x9b*\x962\x16\xc2\xf9H\xb08\xea\x06\x05\xae\xb5%ݠ\xe4Je[\x12|\x01MojP\x12?\xa3C[\x12\x10\xee\x81\x018\x0e\x9e\x89\x9f\xe5ra\xfd9\x1b\xcd3{c\xf6\x9a\x1abqo\xe25&\x9e\x910\x1a\x06\xeb\n\x024\xfe\x89\xb5%\x1a\xa4\x04e\x93\xa9ٳw\xef\x9e\xf5\xe0<<\a\x8a`\xc1\x8d\xf1 \x04[\xc7S7\xe8߇\xe6\x1f?\xfd\xcb\xe9\xe3\xf3C\xf1\x00\xf8Ӟ\xbd̶\xbd{\"\x93\xc0yP\x84\xfe\x9f\x8f\x1e\xa2n\x8c\x87\xa7\xe0)\xf4\x00hAc\xf5\xad\xb7W\x15\x16\xaez\x1b\x94\xa2\xf1Z*\x84\x85\xb1\x99y\x83b.u\x96\x8br\x06ܚ\x80[\x87%\x05Xq\x12\x9d\xe8Ꮳ\u007f605\xfa\x15\xfc\xe3\x1c\xb0\x18n\x9b\x03\xb2\xe8\x94\x05'N\x80y'ND\xff\x1b\xde\x17\xfd\x92~\v^\x9a\x03\x96\x80%s\xe0%\xfa\xad藂]ML\xd7\v\xcbc\xb2\xa8B\x8a\xea\x94\x1cuJ\x90D\x04\xcdO\x87\xa5_D~\x88\xa5_\x988\xb3\xb1;\x1cU\xd7\\W\xd7\x1c\xad#'\xb6\xees\x01\xa9o\xad\xa2\xa3MgC=P\xc1\xda\xc89\xda\x14\xbb\xf3\x1eNWǐ\xe4u0-\x0e\xecת\u05f6\xa3Nn\xd6k9tz9\x16M\xe4F̍\xfe\xa2(\xf7\"\x91\x92\xa8QIS\xb1?\x18\xec\xf6E\x97\x05@!&O\xfe\"\x80\xdd>H@!\x0e\x9b\x9a\x99\xa4\xc8}Z%?\r\x9c\xa3\xf7\xc0\xe7\xa2?\xbe\t\x8b\xde\x14\x17q\x05\xd3x\xa56r\x1f\x93D.\xc5L0\"\xa1\x97*r\f\xa08\"\x11\x8d\x8d\xdeGO5E7\xc2\xf7\f9\x8a\xe8\x9d\xcc?Е)A\xdeֆ\xbe\x04\xdeu)\xc4~Q}\x0e@l\xc8\xdd\x18\xf0\x8a Lrz\xbc\\\x17\xd4'\xd3\x05\xe5I\xc1\xed\a\x9e,\xd0\\z\xe4\bӷy\xeb\xe6\xebM\xa0\xf1ڞ\xb50\x93`\x1b\x84\xa7\x8c\x86\xd1\x17V\x9c+\xd3\xd5\xe9\xcaέx\x01FGO\xf9\x11\x1c\x02_\x83C?ҭm\xd1\v\xe32h0\xb1\xb6\xa9~\x12\x00\xb7\xb7\xb5\xbe|l\xfa\x9aC\x9f\xcel\x04\xa0q槇\xd6L?\xf6\xf2\xfb\xc2d\x10\xc7n\x88\xcbO\x84u\x96\x8e\xcaD\xfc\x80`\xf3mp\xf8t\xc4\x13\x99\xbd\xebGD\xfd\xc0\xcd\x13\xe3\x93\xd8\x14\x87Vf\x1c\xfa롷G3\x91H\x84\xf9\t>\x06F`\xb5\xdch\x13㖋mp\xd3\a\x1f\xc0M6\xb1\\.f/\x89ђ\xedE8\x8b\xde\xfa\t:|12ؑ\x19\x1c92\xc8^\n\x8e\xa4\x17\x84\xc3ԍ5k F?\xa0\x84p\xe4A\xfc\xc4\r\xea\xb1\xc7И\x14wd\xa2<\xd8\t\xfb\xf6\xed\xd3w=6\xb2\x9b\xceJ\x1a\x9e\x95@l\xc3^\x94\x06\xb0\xb6\x8e\xc9\xca\xe2}S\x1cC\x03\x0fG\xbbmr\x14\x8f\xc1\xd9\f\xc0\x01\x94\xb4\x87f\xc2\xcd%[ϧg\x8c\x96\xba\xdd\xc1i\x8d\xbe\\\t\x9b[\xbfx\xd1\xee\xda\xfd\x00\x14\xf9,\x83ރ\ru\v\x86\xf5*\xf3Ժ\xd10:\r|W\xefl\xb0rJ\x85\x02\xf4i\x86\xdf\x18\xb76\x9f\xd8\xfb\x12}\xfew\r\xef,\xd6i2\xd5ִ\x9ci\x1b&\f\u05c8\x87\xdfy|\xdd\x12[\x95\x88I\xcf0\x94\xa1\x91\xbf\xba\xf7\xbaC\xf7^y\x13\x14m\x19\xd0r\U00091bce\xffi\xd9\xf0\xe1&\xf8\"H\xa5\x93\x94\xb4m$\x95\xa0ۖOv\xb0\x88\x87y\xca\x03x\xd6\xe6t)\xc9^\xb2\x92F\xf4\x95( \n\x1a\xf0buroQ \x88\xa1\xefi7\xe6\xf1c#\x92\xed\xb1\x16\xe9\x89R\xd4s\xad\xc2M\x95\xe7\x99a\a\xfc\x16v\x98\xf3\xe4)\xe6\xd7\xe7\xd2)f\x8bDjL\x96(s\xd5b\xbf&[\xe3\x17\xabs\x95\x92d\xa3Tb1\xa7\xd0s_7\xc3牀\x93\xde:\xffU\xf4\xe4\x17\xb0\xe3\xd5\xf9\xf3_\x05\x1c\xb0\x02\xeeUX\v\xcf\xc0/ϭXq\x0eX@\t\xb0\x90Й[\xad\u007fF\x14\xa7\x88\x82AQJq\x9e\xc8#?\xfc\xe9\xe8\xfe\x86\xe4\x02)\x9b\xa5ߺ|\xf9V}\x16+-H6\xf4\x1f\xfd\xe9a\xb9Gt\x94\x88S\x17\xf4x\x13\x0e\xcdYq\x0e~\xd9ㅰ\xe0Vjh\xa8\xd7W#\xfa\xfdr\xac\x8d\a\xa0\x18#1\x87!\xab\x1f\x1d\x81\xb5w\xc748Q{\xa2n/\xf2\x00\xa2\x93\x8b\x11\x1a\xd1\xe4\xe6\xa4\x05\xa5i=(\n\x90U\x05\xb6-\xc4z\x82FnU5\x97˖g\x89\x98\xdcR\xc6qw`\xcf\x1dc\xcf\xee\xdc4\xfd\x8e\xe5\x0f\x02\xf1\xdeg\xed\x8de\x9c\xed\xaf\xe6j+\xf86C\xae\xc99\v\x16e\xedin\xde33\xf2Ѭ1[w\xbd\xba\xa7c\xd7⭽\xcfҿ\xf4ˏ^\xce.\x01L\x9f\\\xf0\xb8x\xc1\x9aK\xf7\xdd1m\xd3\xces\xe3\xee\\\x98\x02rG\xfd\xc6\xcaU5\xa6^4\xf1Z\xf8\x95!\xbfOѷz\xf0h3Φ\xfd\xb5\xf2\xad\x8bw\xb5\xefye\xcf\xd6ƹ;\xcfR=}\xfc\x0e&\xbe\xe0z\xf8\xf8\xc5(\x01\xbc\x92\x166\xbbIt\x90\xf9\u007f\xd5}\t|\x1b\xc5\xd9\xf7\xce\xec\xa5\xfbZieݲNˇdK\xb2\xe4ۊ\xed8\x89\x1d'\x8eslj\xe3\xdc\xf7\t9I\x88!\xe4\xe0\x86\x04R \xe4j\x80p\xb6%\xd0p\x15\x1a\xa0%\x94\x16H\xb9\x1bZ\x9a\x04\u07b6\x94\x12(\x94\xb6\x90h\xf3\xcd\xccʎ\xed\x84Ҿ\xef\xf7\xfe~ߗX;;\xb3\xb3\xb3\xb3\xb3\xcf\xcc<\xcf\xcc\xf3<\xff4\xf1kA`\x8b\x886KTV2\x81^\x1d4\xb8\xa1\xb7\x0e\"\x96\xb3?\u007fK/\xcfA\x14\xef\xc7nyܵE!\xaf\xcbJb\x16G\xc2\xe3*/\x9e\x98\xac\b\xbb\x12J\x83Z\xb1X\xc5\xf0\xeb?\xbc\xea\xfd3ҹO\x1f\x9a;\xf7\xa1O\x01CBp\xeb`\xa6\xb8\xbd\xb7D\x138\x1do\xafr[Lf\xa7\x9e\xec\xe35\xf9\xab\x03~\x83\xd6\x16\xf0\x14V;\xcc\xf5\x1a\xae\x83\xb7\xab\x8e>\x06\x1aQq\xfd\x8b\x95\x9e\x18\xc4J\xa3\xf6\b\x9f\xa7\xd9\xc9D>\xacC\\K7\xb6\x91\xed]\xcdA-\x10\xc2\ba\xa8oy\x80@\x13]\r\"\r;\xb0v\x0f\xe9sHH\xa4\x05\xd9'\xa7\a\xf0\xd8\a\xa3\a\x13\x04&\x8f\xb0\x1f\xfb\xf2!\x80zX\xa5\x03\x88X5\xa8\x1c\xfc\xa0g\xeaԞNpCM\xa3N\xba\x95\xd714\xaf^\x0f\x0e4\xda\xf4\xdax\xb9\xcbF\xc3\x17\xd9\xf1~Fe2\xf3\xbc\xe01\xaa\x99\xe8\x9b\xd6)\xad^p?\xcf#fJZRԙ\x97\x17\xe0\xd41\u007f]\x01\xf6\xb5\xb6\x81\xde顕j3\xb7R\xfa%\xad\xa0i5\xf3\x8b\xce!\x99\xce\xce̐\xac?\xee\x17\xad\xe0\x88\x86\x87\xb4B{\xbd\xb4WJ\x1f-\xb4sv\x9b\xb6\xc6a\x84\x93\xc1\xfe{>\xc8\v\bZ\x00i\x8d9O\x0f\x11?\xba\xd1W\x90\xfd\a\xab\xa1\x81\xf6\xbe\x15'+\xd2Ӽ\xcd\x0eQ\xe3\x15\fJ0]z\xa4L\xc1BV\x1dQ=\f>\x06\f\x84J\x05\xf1}FS\x1f*)ƉFZ5\xe2\x9e˨Vj\x0e\xb5\t\xcfp4\x9b\xcc\xd9\x00\x01\xa1\x0f]\x82\xc8\x04!\x19n\rs\x00\xfd\xe6\bDs4\xef\xc7\xee3\x93Q:\x9cpӞ\u007f#\xc5\n\xfe\xf9\x10\xa0'\xcd\xe9N%;\x17g_\x00\x82\xee=\x9d \xfd.\xad2I_Y\x04-,V\x9a\xc0H\x9d\x99\xae>{L\xfaBg6\xeb\x80\xe6ep\a\xd0;k\x8b\x12\xa1J\xbb\x01\x00\xa0\xb3W\x84\x8a\"u.#|\n\xa5\xd7]H\xb7\xf5\xa6\x1f\xc9\xe5\xaf\x18\x98\x0e\xa0\x1b(\uf6f8Pڰ\x12\xbc\x92\xd5\xe0\xd2\xeb\xc6\xe8\x03F\xf8\x95\xce\xfc\x92t\xe5oQ\x1f\xfa\x9b\xce,\xcdV\a\x16\xcdXST\xb2fA\xa7ápuN\xdd\\\x1d[;o\xb2\xdd\xfe\x1f\xa6\xcb\xfb\x9fl\x0f\xfb\x05\xd5BME\x12\xca\xd5hZ\xc0\xc0\xf7ة>\x01g\f\xa36\t%\xd3ؑ\aY\x81$h\xe90g\xdd\xce\x13gyX$\xb4^\xd0T\xab\x03\x02\x1a\xb3\xe4\xa5\x1dD\xefV\x11\x11\xaa\xe8Å\xe0\x05 \x92b\xe0\xe5\x04$R\x86rIh\x96\xe0\xe1\x02;\xe2,\x14J\xa5>`\xed\xca\xf3i9\x15\xab\x00\xc1 P\xb0*N\xeb\xcb\xeb\xb2\x06\xf4J\xa5\x02\xc0\x80}\xa2\u05cc\xe4\x8a\xca\xd1\xf5.\x0fG\x97\x85Be\x15\x8e\xfa\xcbi:㳙\xbd\x13\xf7\xd9CB0\x881\xffZ[-O\xa6L\x82\xb0|9\x8e\xed\xdau\x10G\xa6̘1\x05G\x97\\~\xf9\x92;\xd5]k\x95L\x89C\xa1S\xabY\x8b\xe0bz\xa4\x1e\f\tɪ\xd5:\x85\xa3\x84Q\xae\xedR\x8b\xb5\x1a\x85\xc9\x18\x1b\x9fn\xd4\xf0\x8bNH_\x9cX\xb4>\xdc\x19\x00\xc0\xa4\xd0\xd4҇B\xe5B\x10\xbd)\x86,l}\xabU\xf81ƙ[\tjV\xe2\x84]Ҥ]/\xe3\x84\xce?\x03\xeaϝ8i\t\x9a\xf2~%\xfd\x89\xf8I7モ\xa7\x8f\xd7\xf5\x10l\xa34U\x8f\xe6b\x8c\xa75\x1d\xcd\xc7˨5\x88\xf2\xb7Q7Sߣ\xf6\x11;{\xb2\xa3\x12ȅ0\x17\x0eN\xff\xd6|\x83v4\xbf-\xfe]\xe1\xb7\xdd\x0f\xa0\xec\xb9\xf8\xfb$\x90\xff\xe0\xf7\xfb\xa7e\xbf\u007fq\x8e\xaf\xbd\xc4\xcb2\\N\x02i\xf9%b\xac\x1cd\a\xc4.\x993\x17\x03\xdd]\x17\x9e\x00\xe5@\xea\xba8m@\xe4\x9cn\xbf|7\xfe\x03\xb7\\\x1c9+\a\xf4\x80إ2\xca\u007f9\xdfe\xdc9\x8e\xea\xf3\b?\x92\x1aG-\xa0\xae\xa0n@\xac@\xae\xd5R\xbdH\x99\x80\a\xbd\x16T\xf2lI[\xfa\x8c\xa5R\x04V\rw=b\xedC\xd6\x1b\x89\xbc\xd7\xdb\xf6A9MVꐗ#\xbdbPƝ\xc3\f\xaa\x8c\xbf&\xb2b\xaf\xeef.A\x96\xfb\xff@\x8ec\x015\x05I\xac\x8f\x90\b\xfcؚ\f\xf8=\xae\x90\xfe\xd4>,\x89/\xdceM\x04|\x05ဌ\x99\x80\xf2\xf4b7dI~Ќ\x82\xcdӦ^\x83\x82\xd7@\xe05p\x1d\xe1\xe7\x84|\xbe\xe9n\x8b\xc2`LZ\x9e\x00A\xa5Ŧ\xd6\x14\x1b\xa6\xbe*\xf2\x06C\xd2\xf2\xc9}d\xd1\xe1.y\xe9\xa1\xe4<5\x05P\xdb\xe4\bU=kR,\xe2\x0f\xd55D\xf6\x9d«2\v+g\x8c/\rG\x933\xd22\x8a\n\xaeS\x0e\x18\xe2}r\v\xd1\xf6\xc0.\x1eq\xb8\xe3\xb5\xd7nƬ\x9d(\x1c^\x85\x1e\x84*p\xed\x16\xc2\xea\x9dٍ\xa2\xe8\xe99=\\\xfa<\xa5\xc8\xe6\xf4,\xe6Q?\"\xfc|\xce\xf2\x9dp\xbb)\xec\x81+F\xackr\xe0\x8ax\xf6\xd1\x11\xd3o>.\xab\xc4\xe2\x16\x8d\x13\xcd|4߅\xc2A\x19\xea\x0f\xa3d\n)S:\xe5ƦI|*\x87\x89\x87Έ\xc7\xfc q\xccGs\xb26;^\x05O\xf7~+r.\xf3\x88uD\xcd \xed뻐\xc8%WC\xd1\xca\xe2A\x99QTیu\xc1\xf2ր\xcaW\x1a\xac3\xda\xe0e\xbdgչ+\xd2\x04\xe3H\u007f\xdd\xf0D)\xad\xa5\xa7\xee)0:\x02&\x8b\xc5\x14p\x18\v\xf6L\xe5\fN\xe9\x83\xcft\xfa\x02\xe3~\xb5N\xfc\xf5m\xc6\xdb\xd7yF\xc7yOs\xec\x8a[\n\xea\x19\xb6\xb4`\\k\xb4\xfc\xb2y\x01;\xfdh_\x0e\xbb\xbf\xc4e\x93\xf30\x8a@\xba\u007f.ӿx\x14\xd09\x81\x1f?\vf`\xb9/\xdcZ^\x91\xaf\xf0\x84}\xe5W\xe7BHR\x81\xc9o7z\x8c`\xf6\xd8@\xabQ\xa94\xb6\x06\xc6Άб\x96\xf7\x83\x8c\xb5L\xbb\x06\xa8w\x03\xe3l\x1b_7\xca^=t\x9c\x11=\x1b\xd5SU\xa2\x8a\x9bZ7HGq\x0e\xe9\xab\xdd\xd2g\xb3E\xbfG\xce\x01J\x03}9\x02\xdfR\xf6\x00\x9bc\x81jB<\xecT\xbc\xdfM\xb4\xa3B\xde>=)Ĝ\x12l\n\x12#=\x11\x89v\xb9~\xca\x11\xf5\u007f\xb9\x9f\xd2x\x8f\x04q\xf1\xbdvw\x18o\x87\x0e\x85\xb1\xaa\x1b\xe3\xc5\x1dD\xfa\xedk(\xb8\xe6\xc9k\xe6\xe3.\x84\t\x9e@\x9b\x04\xc2\x05\xbe@ºk!\xa6\xe1}\xa7\xf4!\x97\xc7\x1fHZ;wg_8\x9d}V\xe3\xd3ܯ\xd1p\x19t\xf8\xd8>\xac\xe1\xaa\xce\u05f5>x4G\xee;r\xe4\x0f>\xc4p<8\"\xf7\x93\xf4\x8cd4\\:~F\xe5B\xb2\xac\xb9/\xd2P\x17\xf2Gb\x93fU\xa3ޓ\xbd\x01\x17\x8bJ\xf5i8\x0e\x1d\xb5\x1fۆݹ\xa0\xf3uM\xff5|35\x89\xa0.a\b\x0f\xd9\xcfxn\x8f\ao\xf1\xe7X\x810f\xe51K\x00\x89\xed\xbe\xac\x85\xee\xf7\xe1\xbd\x0e4?\xe2\x1e\x95szRG|\x89\xe7\x14\xc6\x13\x17{G\xa3gj\x11C\x88\xb8B\xb3\xba*\xd9\xdc\xe4\xb4:\x8d\xe0\x0f\xa3\xb4\x16m\xe76H\x97}\x91W\xdcu{ˁ\x9d6\xc0\x88\xba֒B\x8b\xcb-\xf2yC=\xfeJۼ\x89\x1d;&[8\x81\xa5ի\x97\x94\x8e\x064\xab|r\x80q^\xd6\xd1\x18\u007f9\xae\xa6\x01\x9c\x95\x99\xf4pH\x97/U\xea\xae`\x15mP<=\xe4c\xcex\xebO\xa6\xef\xd8\xcbA\xdf\xd8\xe4\xccX^\xcckC\x9d\x93\x17]M\x1d\xbeI\x8b\x17\xeeh\x17'\x8b\x1a\xae\xc6\x04\x94P?\xd0L\x0fq\xa9A\xc4C\x9d`\xcfS6ħR\xc4_\x1d\x92h \x06fA\r\x84\xadtL2\xfajX\xbeBZ\x91\xf6\xfb\xfa`\xd2͘\x80p\xd3\xd0iDl\x85\xb2J\x17A\xd1Lx\x8df\xc8ˮ\x81\xdc\x00\xfe\x89Ѻ\xac\xe1\xf0\x82\xc5\xc6\xc0\xd0\x18\xe3ԘUА1\b\xf0\v\xbd\x82\x13\xdb3\x9eCO\xea9\x95Ka\xed\xda|\xb8{۾\xf0\xc4T\xe8\x1e\x90\x1f\x8dz\xf3\xbd%\xed\xe5E\"˫T*\xf0\xe17C\xafxvi2\x05V\x8fd\xe99\a'\x88\x1ea=\xf3z\x9eˣ\xb7VI\xff\xb8\xb6x\xec\xa8\x18\x00\xacF\xd5\x06\xca\xdb:\xb3\x87x-\xa0\r\xcai\n!p\xbd\xa7\xf3\xd1;\xba\x0em/\xefY\xd0\xe8\x04\xd6p|x(\xbf\xa0~\xda\xea\xeeB%\xa4\xc1W\xa7\x17\x9f~\xe1FA)\xdd1S\xfa~\x80\xae\xac\xd3\xf2?E4\x04\xd0\xfc\xb7\x89=K\xd5R\x1d\x88\x8f\xa10j*^F\xc0R0*9GH\xd8g\v\xf6PR\x02\xe4\xb1\r\xb0Ar\x82\x1d\xe7X㲁\x1c\x16\x90xk\fҽ\x8a\xec\x1e쯎\x13\x81\x80\x17\x81\xf5\x00[\xbf\x93q\x9a\xa7\xe5-E%\x90C!\x17\x17P\v\xe2L\xa94\"\xb2z\xaf\xe3\x83ڲ\x1d\x05\xea\xe1\\̛\xfd\xab\xb4_\x19\xaeL\x85\x00#e\"\x95\x10ք\xc1\xd3\xd9\u007fD\xe2\x1cW\x19T\x81SҁP)ǥ\xfc\x9c\x0e\x1c\xfd\r`\x80Uo~گ\xb39,O\x9f`\x03g\x00\r\xf2\xd4^O\x8b\xe3&\xc8\x01\xaf\x89\xbeW\xcf\xe8K5\xe9\x850\xb2\xa3<\xf3\x81\xaf0\x11\xfcĦ\xf3\xe5\xb7\xe5\x01\x95\xf4\x8d\xc5\x12\xf4\xb7\x9a\xff\xba]o\xf1\x05G\x19\x9f\x9f\xa3p\xe7\x01\r\xac\x88\x84+\xe8\xe9\xa6\xdb\n*\x1f\x8c\xd6H\xb3\xbcEL\x85\xb7\xa2 \x98b\xbd5\x91p\x12d\xd8L\xc4_Rӥ\xaa\x0f\x06J`w\x10D\xb5\x1b\xadc\xf2C\xafl\f\xc2\x10\xe0\x00\v<\xa3lV\xb5s'`a\xc9bpH\xfa\xfb\x88\x96\xf7\xab\x9d\xa9\xba\u0603\xb5\x85\xb7Y\x83\xa0\"\u007f\f⺽\xd2~p\xcc\xdf.\x98\xf2|\xd2T0\xc6?\xca(\xd8CҌ\x9f\xe9Y\xb3\xe1d\xa4\x06T\xcac\xa0\x9b\xa7ؙ\xe8kMC\xf2\x00ba\x822x\x01\xa2G\x0eM\x85x\xad\x95ؚ\xa4\xb06\x87HF\x04\"\x8b\"\xf1\x1d\x12\x97\xffv G\xc3h\xd6\xc3\x10]~l\x9dK\x13\xc0\x02\xc1\x1c\xb4\x06\x04\x18$n\x1a(L\xf1bn$E\x9f-\x18\xb6\x82ѐ\x99po\xa5\x85aT\xbc\x8e3\xc1'\x81f\xa9\xf1r\x8dI\xb5a\xeal\xa0\x02\xaf\xef4\x9b;\xcf\u007f\x0f%\xa9\x05Ն\x8c\xd4\xc4WE\xe8\u007f\x9eQj\xab+i\xa9\"\\\x94\a6\xa8u\xd72\vO\x16\xfb\xa0\x97\xff\x11\x9d,\x03\xc6G\x1f\x97>n\x1c\xde%-u\x9a'\xacw\x168\x0f_i\x06\x1dJ\xfeqX\xf9\xa3\xa9\xee\xb0\xd2l0kD\x85\x95>\xbb\xf2%\xad\xa0\xca\x18\xfeK\x90>\xfd\x93g\xa4\xe7\xa6\xdfg^Қ\x95(a\r\x9d\xe4\U000ecb14\x92\x86\xd3H\xe6\xe5\xe9\x11\u0382\xa2l#\xa3*\xe6~\x0e\xf6\x94\x97\xd3\xc5\x1a\xe9)\xd5\xdc\xcee\xc0\x04,\xcb3\x0fL]\xf8,\xac.p\xae\x9f`v:\xcdW\x1e62|\xaf\x1e\xd9\xf7\x18\x89]\x80\xb8\xfc\x18\xc1\xcbţ\xa9\xac^J\x06\x01+\xc7\xe7\xd4q\xbdXrJ\xa5Ű\x19\xea\x81/\x8ca\x9e\xc2b\xd8\x12\n\xbb\x91`\x85\x17ݰZ\x91<\xfc\xe2\x81T\x06Vb\xec;o\xfbßv\xec\xdc\xfe\xc5\xce\xee\t^\xbe\xa1\xedЇ\xa7@\xc7IoCe\xe4W\xfb\xf6\xe9\\\xf9c7\r/\xd1\xd3\xe9\xf4\x88-\x93\x96dǶ\x9d\x18.\xc0\xc2\x17\x17\xf9}\xf6\xe8\xb2\xea.GK\x9ew\x05\xf8\xc1\xbb\xfb\x0e\x1c\xd8\xf7\xee\xce\u007f\xec\xf0\xd4e\x9c\u007f\xbf\xff\xc1O?}pr\x9b60\xb3\xf5\xa8\xf4\xdal\xc0zo\xbc\xff\x8d\x1fv\x0e\xf5\xed\xff>|\xe7t\xf5y\xe9\xa9ֵ\x9b\x82B\u05ed\xb6Tup\x9c\xbd\xd8m\x18_\xb5\xe0\xb6%\xb5m\x8bz\xfdc\x91\xb9\xc3NE\xa8(\x9aO\xc7\x11\x0f\x1eD}\x8c˹\v\xc08\x19\x04%ٛ\xa2\t\xe0\x15/V\x83\x94\x11\xcf\x16a\x91M\x12\x8d\x03\x02r\x88\xdf8NJ\r\x9a,\x18\xbb3R,\xde\xf5\xa7\xddw_V^\xc2Xk\x86\xdc\xf5\xfa\xeb \xf9\xfaa\xa8\xf2\xc4'VZ,\xaa\xf7CL{\xd5TpU\"2vh{^\xcb\x16\x17scS\xb2*1\xcab\x04#\xfaO\x0e\xe0\xb3QCm\xcaxf\xd5\xc1\x83\xab.{@(*\xb6\xfcFz孷A6/V\xbf\xf6\xd6\xcbf\x88\xf4\xf5\xc0p\xf9\x92\xf6'\xc2wG\xe6\x0e\x9f`\x15\x86\x0e)\b\x1ag\x0fI\xae\t%[\xca\v?\xbfhN\xe8}\xff\xd1Do.\xd9ۇ\xa0̡c\xfb\xc5ܴ\x88m}\xad\xb2J\x0f'cy\xe1\xf5 \xec\x99\n\x12\x85\x1f\x1c\x10\xdd*2u\x0e\xdc\xee=/6\xceu\xf1\xe1X8h\xd6\x14\xa8\x19\x05k\fl\x1d\u007fl\xa4\x91eT\x9a\x02\x95ŏ\xae\xf0\x99\xad\xe2\xb5P\xa17h\x12:\u007f\xa6xX\xa4hxQƯKh\r:\x05\xbc\x16\x80\xc1\xaba\u05c8\xac~RF\xe0\xf4\xa2\xc6%\n6\x03\x9c.\x8c\xf6\x8f\x9ax\xaf\u007f\xb40\x1d\xea\xf3\xcc\x16\x97F\xd4s\xc2u.V\x8c\x8al\xa1\xa0t\xfb\xdd\xe8Oa.`Epv\xf0:\x18\xa0\xf4\xa8\x1dV\xa0v\xc0\xad\x90\x92q\xc0dE&\x82;H\x1cpYs\xf0`P\xd6k\xca\xd93\xc9\xcd$7\x9bL\xeaX\x83\x02ʎ&\x12\xf1\x1cx9ݾ\xf5\xedJ\x87R\xa735\x98\\\xa9\xfa\xd6zMp\xf3hg\xd2\xf9>\xaf0[\xcd\xe3Ġ\xcd[\x97\xaa\x9b\x92JN\xaeM\xd5y\xec\xc1\xbc\xb1F\x9bY\xc1\xbf\x8f\xb2\x8c\xda\x12\xd0ԏ\xacO\xba\xf4\rf\x93N\xe9ȼ\xc7\xf6\x80믨Z\x17\xbb\x85w\x04\x9c\xdeb!\xec\xd4;;\xb6\xe7kԜ\xab9_]\x11Բ\xac?R\xe0p\x14D\xfc,\xab\x0fV\xa9\xf3\x9b]\x9cZ\xe3\xbdn\f\xca\x186\x17y\x1cA;\u007fS\xe9\xfa\xaak\xd7\x0f\xa2\x81\xe9\xffWi`\xb0\a\x03\x96\x92\xe9 \x8a\xe8@]\xa0!t\xb0e\xc2Km&N\x85\x17\xd7̈\xf1 tp\x1dT\xe8\fڄ\xd6?D\xa6\x83!~mR\xab\xd7+\xc0u\x80\x1a\xd0\x19\x10\x11\xe8&\r\xc1Z\xd39\"\xa8O\x8e\n \"\b\xb5\x85FB\x83M&\x02\xb5\x0e\x13A\f\x13\x81J&\x02\xa5PD\x8b\xb4zP_\x00\xb2N\"\xe2\xab\xf1\xa8\xa7ce\xf6\a\xbd`\x80\xe5\xf8:P\x0f\xf0\xe2\x12K\xe4'\x9a\v\x13\v`.\nc Y\x9eD\x9f\xd9D\xa1\xd7g\xad\xe9:\x061\xd5Jj\xe8\xf2\x86rQ\xa4U\t\xab\xbeyH\xbb\"6_zH\xfa\xfd\xd47c\xa3\f\xfaaO\x8e\xdd2\xf2i\xc4s+\xd5\x1c\xf7\x82\xde\xdbsz\x87Dm\xef\xd8\xda^\xa8\x01\xdcu\x1f\x1f\x05K~\xc1\n\x95\xe5\xcd\x15I\xdd\\\x18J\f\x9b\x91lذ\xa6\x81\xa3\xa2S\x9bG\x14\xc68ӧQW}\xa8\x98\xf3\xbc\xac{\xb8\xfcJ\x83\x9b\xe7\x1d\xadޠ\xd6\x13\xa29Q-\x1dr\xf1y\x93!pF}F\x00\x00\x97\x06KA\rP\xea}%#\xa2\x8f2m\xddW\xdc2\xa4cMK~??X͈g\xee\xa2f\x13\xdd63\x1fF\xe3{\xbf\x9f/\x9c\xe6C\xfd\u007fxU\x1f\x8d\xed\xfd~hx\xe4\xd3\xe2\x80_\x12\x06\xfcD\xf8\xc0\xe4\x100\tD/\xdb(\xabg\x93\x03[\xc8\xfe\xe5\xa4\x10~\xe7\xd1\xe2\xfa=\xf3jG\x8fօF\x86t\xa3Z\x1a\xe6\xed\xa9.;\xfcNX8\xf9)˞9\x853Dk\xf7\xcek\x1c\x81\x06\xf7pHα\xb76\xfa\xe8\xdbA\v\xca\xe1\xde#}\xb9w\xcd{{\xa6N\xdd\xf3ޚ\xbd@\xbbgDvYv\x19\xbc\x15\xfe,[\x93\xada\u007f\x96%\xf8\x05\xb0\xa7ģ\x1b5\xa2\t\xdd\x18;\xfcnP\xfc\xe8s\x8e;sZ(x\xf7pѐ\xbd\xf3\x87\x0e\x1f\xad+\xf4\xf9\vu\xa3G4\xce߇s\xa0\x87\xff\x85\xe3>=%\x14\xbcs8V\xbbo~\xdd\xe8Q:Ot?\xd0\uf676\xe7\xc4\xda5'\xb0\xc7f=tg\xa1t\x15\xd8\x04%\xb0\xe9\xeb_\x82\xbb\xe94\xd8-\xcd9\xf7\v\xba\xf3\\\x8f\x94\x01G\xe9\x1ep\xb4Oϒ\xd8\x12E\xa8\x14\xc67\xe3s\xfa0H\xa0\xe8u\xa6\x1cL\x00\x1d\xc7c\xb3W\xd4\xc7@B\x00\xc6\xfcT\x1a\xeb]\x86\xd3n\x00\xc6\xc2\xc7\xec\xd9yK\xf7\xac\x9bfm-\xb9\xe1\xd81\xfa\xf7\xff\x90\xdcV\u007f\xba|\xe4\xd8\xc5u\a+\xcdf\xe9Ï\x9e\xa1'\x9c\xfb\xaf\xa0\x02\xde7\xab\xdd6g#\x1b\x1a\xbew\xe9\xb9\xec\xf4\xdb\x05v\xf8\xcb7\xd0\xf4\r/\x9f\xf8\xe6\x8b\xda\xf1\xcbF\x8e)ˇ/\xda\xefN\x96\xa7\x92\xf0w\xd9'\xc0\x17g\x1fH\x9b\x18\xdd\xf8\x1b\\\x8d\xbeǨ^_\xef9]>3\x95O\x95P\x95h4\\J\xad\xa5n\xa1\xfex\xc1\xda\x00\x89I\xa1\x9c\xf7A4\xd3]:2\xf0\x1cp97\xd9i4T\x98z\xbd\xcaYS\xbd\xaeFMa,\x90qX\bK\xcb\x1e\xd5\xd0\xd0A\x14J\xc8\xdd9%\xbe\xde+dDF\xfd\x91\xc5\xf6\xf5\x8c\xbe\x17\xf5\x8aر\x87\x89DBF\xact(LF_2\x92\xd1d\x12\xc7\x12\x1d\x94\xb9u\"\xd4ၝ\xb8\xa4\xe4E9\x81\x1e\xe7\xab\xf0\xf9*\xae\x8e\xd4\x14D\\\xee\xc8\xc3\x055\x91\x88\xdb\x15\xf9A\x04\x855\xbd\x01Ќ\x93\xde\xfb\xe1\x15o\xdf\xd2a\x99\u007f\xf5Zwm\x85ۛF\xbf\xa5^w\x85\xb3L\xbb\xfcꛆ\x1b\xdd\xd3S\xa7\xddc\x0f\xefX6K+5gff\xeag\xd7\xc3U\xadߛ\xd9vK\xba\xb4sn\xf9\xe4\x801Qδ\x8e\a\xd6ƚ*\xe9L'S]\x94+ \x8d~\xb1\x8a)\x8bWOK%W\f\xf5\x86'\xb7\x1e-\xcd3\x95\fY\xdcP-\nVh\xa6U\xf6<\xc3į\xb7\xfb\x1d\xd5\x13\xc7V\xb2\x1a-\"\x97\x90aO\x81\xcd_\x92\x9e\xc2\xfc\xa9*\x16\xab\x8a}3n\xa5\xbb\xa8Ƚ\xd2]\\\xec\xfe\x97g\xf0\x95\xfd\xc7\xe6=tr\xed\xa4\t?|\xf7\xfb\xd2[s*\xe3\xe4\x9f\xc7\xd6\x05\x84\xc7Z9\xe1\xcb\t\xab7ݶ\xebwͥ\xf0p|\xf4\xe8xb\xf4h\xe9d\xf7}\x8b\x9b\xab\xf7-\x99\xbfP\xe0*\x92vsӋ+\x97I\x9f4d\xf6\xd8\xc1ʢ\x8c|\u007fciS;\x10<\xdd|\xf4\xe8ʊ\xf9\x95\xd7\xde}帤\xcbF\x9b9}4d^v\r\x93\xa9dy֨\x17\x00\x97\xa7A\xf3\xf3\xe7\xee\xb2\xf6\xfe2\xbc\x8d\n\x12-\x81d8ߒ\xe8S\xa0\xb5\xe680De\xc1D\xb9\xbf\xdco\xf1[\x12\x96Ā=\xb7\xdb9i\xd7o4\x1b\xdbg\xddpìi5\xf3\x17\u07fe\xff\xe4\xc9\xfd\xf7\xfe\x12L^\xb2d)\xfa\aL\x83X\b\xb8&\xdfs\xcd\xc8\xc97\xbfts\xf5\x9c\xd9X\xbf\xe2\x8d5KI\xc6Ճ\xb9\x03<7\x04s\xe3e\x98\xa0\xd4ajE\x83\x1co\xf4\x1b\xa39'\x81\x18\xc1F^1#\x9b\v\x88L9\xaa\xec\a\xf7\x8c\x90>\x1c\u007f\xcfk\xfb\xebG\xf6\x1c\xe9\x19Y\xffܝ\xb3f\xe9^L\xb6MR_g\xb6\x87\x18\xea\xdcS\xa5\xbadu\xa9\xf4\x03v\x92mySgOOg\xd3r[S\xb1\x1eFL\x10\xfb\xca\xc4\xe3\xf4\x18\x82\xd3\xc1\xa2\xde8\x81\x9aJ\xddFQ\xa6x\nu\x0e6ʆe\x90\xb8z\x10\x85\xa8>z\xe07Ʊ\xcf\x00\xb2\xf9\x8d1ɰ]5\x99\x8aCքя\xddҡLؤ\x01Mf)7\x06\xa3&\\\rCʓ'ky\xe1D\x87=X!.\x00\xf4M\xdeXu\x19u\x1btpsر\xfa\x1d\xed^o\xbb\x97S\xaa*\xedq\u007fT\xdc8\xf6l{%\xa8zT\xac\n\x8eTOmػ\x9b\xf5j\x1c:\x8b\x02D.[>*V\xb9\xcc\xd8Rn\xf6BU~Q\x93\x87\xbf\xa6{ڞ\x86y\x87&W\xfe\xda\xe9(\xdaZ\xfc\xbc\rɮ\x86v\xb3k\x91:\t(R,P\x84\xec\xd2(\xc7\xd2\xe6\xfc\xe9\xe9\u008d\r5\xd7\\\xb1\xacT:%\xddE\x14\xb3\xee\xd55\xb8\xaa\vk2\x81U\xb3::f\x1d\xf2g\xcaR\xfe\x84\x03\xb1\u07b3\xec!Г\xc9d8m\x8b/S\x98\xb4\xde\xd0\xc5t\x0f=\xdc\xf4\x9aZ\r`\xc3\xde\xecI\x80\xa4;\xb5B\xfa\xed\xb2\x98\xb9\xa2\x92\x8b\x9b\xd2VUaft\x1e\xa4\x1e\x1f\xd9\xf8e\xfe\xb8\xfc\x04\x8c\x9f\xb0\xd2\t\x8f0)/p\xbd\xbe\xa1\x05\x15\x85\xb5\xd1\xed\xa1!cU\xa5\x8d\x9a\xf2JƧ\x0e7ŀ=d\x87\xfb\xed!]\x933iu\xaa+*4ƀ\xbd\xdc3\xc4\x10\x1a\xa0s\x11$\\\xc4\x05\x06(\x8d\xc4R\xacg\v\xad\xa8\x01E\x10\x90\xb5\x13\xb0\x89\x96\x8e\xf6\xe1m\xacp\x88\x93\x95\x18X7\x13\xaf\xa3y\xaa\xab\xe1\x9bLC\x97ZQgin^\u007f\xefRvzi{U{|*\xb7\xf4\xde\xf5\xcd͖:\x85:\xfb+\xc0w\xa8iEHaW\xffq9\xdbU\x86\xae\x97u\xb1O\xefQ\xdbQ\x1a\xad\xee\x00\xbc\xaa=>\xaa\xad\xa5mLi\a\xbd\xf2\\\x94@\xb2\xbc\xa1W\xf2icU\xf9\xb4u\xed\xcc\xf0\xfc`\xd0\xd7̶\xaf\x9bV^eL\xf3\xca\xec\xfd?\xadU\xd8\xd4IT\xe8\x03ch|5\u007f8\xbd\xf5rTVRmS\xd4\xfeTQ\xe3+\x11Ř\xb7~\xa0\xdec\x19Վ%p\x90\xf3\x01\xa3\xa3\x8b\xb0\xa2\x97\xec\xc9\"\x87\b覫!V\x81\x0f\xa4S\xa2`D/\x1b\x8c\xe2\\d\xab\x1d\xb5\xc1\xc5\b\x04\x18\xfe\xbc\x0e߄[\f\xa2Vy!\xac\xa0UE\x87\xaed\u0085\xa3[\x82\x00\x04[F\x15\x87ص\x87¨\xb2A\x85C\xdd\xf5\x16\xdbV<4\x0f\x80\xbc\xa1\xc5m,\x80i\xb5\xfd\xa5)C;\xa5w\xe8\xf6\xc2f\x9c\xdc\\\xd8N\xbf\xfb\x8b\xaar\x1d\x8f\x8d\x04\x89\x9b\x0f\xdc\xc0\x91+\xc0K\\ \xda֊\xcblm\x8b\x06\x8aN\x9f\x9e\x14\x81\xcb\x12\xe8\x8d}W͠\xbd\u07b8\xd5\x1a\xcf\xf70Ӯr\x93\xb6a\x94#\x0e2u\x1e\x9f\xcfSǼT\xac\xa0\xb3!z\xff؊\x96?\xc0\x06\xb7\xdf\xefn\x80\xf7\xed+\x8bk\xf8s\x18\xfa\x95~\xe4\x1c\xb1\xa6\xa5\xf7W\x84V\x82\x19\xac\xdb_\x96\x97W\xe6w\a\x1e>ҁɅRS\x96\xf3\x14\xfbI?\xfb\x0e;\xe5\xa6|T\bɢqj5\"#k\fU+\xcc\x02+\x1d\x06A\x1a\x8514\xa7r\xd8F\x1b\xb0t\x10\xa4y+IN\x87y\xa2\x87\x91\xd6\xc30\x8fMYcX\xa3\x9d\xe5\xfc\xa1\xf2p\x88\x0e\xd5\x03\xecdW>\xa6\x83q++Z\x04b\xe8m\xb1b\x1f\x1bilˊ]m`A\x16\xdd\fZ^\xf1\xbd\aL\xc0\xa4\x96ޒ\xce|X\xfa\x15b\"ku\xd2~p\xe3t8\x0fBf\xd4x>[\x0f\xa8&\xe9cf\xae\xfe\x0f0{\n\xac\x12\xa4\xc9\xf4]\xe6\xd3\xf0\x16\x0e\xf2\x00\xba\x1f3\v\xc3\x14̟y~&\xcfH\xef3P\xf1\x11\x93\x86|m\x17\x18\x0e\x15][`7T\x82GY\x1a\xd4rfn\xf5\x95,\xbb\x8e\xe5\xc6\xd1\xeck\x1c\xfb\x15\x03\xf5f\xe6\xa7\x1cx\xe7/oK\x89\x13_\xbd\v\xb6\xbe\r\x86\xfd*{\xfa\x1d\xd0\xf4\xb2t\xb0\xfd\xb3\xd1@\xaf\xa4\x93\xcd\x1c\xdc\xfb2\xf8\xf5#g\x1f\xfb\xf3=\x9f\xc3\x15/\x80\xa7\x0e\x9e{\xe6\xe3\x9b\x16Lg\xd85S?\xe8\xf9(\xbfl\x15K?òc\x0f\xb0\xf4\x9f!\x04_0\xc0\xc83\xc1\t\x1c\x98γ%\xb3\x15\xe0\r\x15\xbd\r\xdcɰR\x19O\u05ce\x87\xdc\x15-\fS\xb1\x94\xa3\xaf\xa4\xe9m\f\xb7r\x1b\xcd\xc2;\xd9\xfe<\x9c\v\x8d\xfc\xe3ɪ)\xed\xd71X\xf0\xf3ɫ\xa1\x88l\xe9\v̊%\xe7\"a \xe6\xd6\x05\xe7\t\x03ΘG՞\xd2\xf6\x04\x97v'b\xd1X\u009d\xe6\x12\xed\xa5\x1e\xf5\xb8Z\x98\xa9\x1d\xf7ȝ\xef܉\xfe\xe0\x06\x93\xae\xbb\xab\xe1l\x86 f\x1cm\xe8\"&\x1b\xdd}GPX9{ΰ\x12&ߐ\xa7R\xe5\x19\xf2\x99\x92asfW\x8e\x981\x03\xee^|\xc7\x1d\x8b\x17\xddq\x874\xfa\xa8\xcet\x12\xdf\xce\x12؍\x93Dӻ'w\xcc\xed'\x90wTRE\xd4dj\x01\xb1\x9f\xcbi\x81\xa0\x11\x8b\xe9}\x1d\xc4GU\x037\x1b\xafc.\xf1.}\xce!.zs\xcbE\x18m\x8c\xfcj\xa5\xd1\x111\xaf\x81\x1fݐ=\xda0Z\xe9,\x19S\xce\xf2qK\x89+\x12\x8a\xb8J,q\xf8\x98\xa0\xed&\x00ʹ\xe3\x80V\xd0\n\xe7)A{\x96\xa0\x8a0\xa87\xd3\x1bЫ.B\xaf,=\xe9\xab\x1d1yd\xa4q\u07bc\xc6\xd2΅mIƣ\xb6*\xd1?\xab\xda\x03\x18\xd4\xed\t2\xb3|\xec\xdf*\xb80\x96\xb8\xf6\xc1V\xc3B\x0e'G!\xf3$\xf9h\x8c\x1bB\x8d\xa1Va{\xe1(\xec\xa3\x00H\xde\b\xf6\x82e\xe7\xe0Rz\xfdq\x1b\xbf#.O\x0f\xe5\xb2\xd3\x00b\xea\xd6{\xd6o\xe5\x882E\xda+\xb9RGqaaa\xb1\xa3\x94\xabl\x8f\x98ZR\x90J\x8d\xdd\xf2\x93-[~\xc2\xf8\xfa\xab\xd2[\xf4ٗ\xf5\x16\x8b\x1eV\xe8-\x03T\xec\xd1l\"\xed\xef\xef\x80C\"\xd0,\x1czw0\xbegѬJƩ7+\x95f\xbd\x93\xa9\x9c\xb5\xa8g<\xacDžo\x91\xfe\xd0\xe7\x80\x02\x98*p\xc9\xf8\x00\xd4\x17RG\xe1oҟ&\xe5\xef\xd3%c\x03^\xdc~[\x88$\x81\x89\x04[⑩.\x1dw\x03ػ\x9f<\xc8\x1fG\xf9wą\x01\xb4u\t\x17\v\x97\xc0\xb5a\xa8\x96\x94D\xa5Z.n\xd8\xeb\xff\x83&E\x14\xf4uF\xc6\xfa\xee\xef\x9f\x01C~\xa3\x99\xe5\xebL_\xf3\xbe\xdd3\xfe\xa2\x16\x06ϐ\xe6\xcdv\xf75䙾\xd6\xfd\xaa/\xed\\\x9c!\x04\x89\xa9\xbc\u007f\x13\v̫\x17zB\xd7\xc0\xb9\x18kh\x14\xa0y\x838!\xf5\xc9 \xb9\x84G\x96\x9dJR\x86^ό\xbd*\x8e_\x8a\x9b\xd74>\xf5\xdaS\x8dk6\x8b\vA\v\xb8\x12\xb4\\\x9b\xd36\x86\xa7n\xfaLz\xfc\x89#\x03\x14\x06\u007f\xbe\xfbUC\xcbر-\x86Ww\xef\xfa\xe1\x0f\xe1a\x19\r\xfc\x14HI\xb7I?\xfe\xeb \xc5\xc2\v\xf52P\x01\xaa\x98\xd8j\x88&\x8b\xf9\x82\x9a%v\f\x99s\x1eh1[M\tћ\x8e\x87r\x95\x85\xaf\xc8%݈\x15$wH\x8f\u007f\x86\xcad\x96\xdc~A\xad\xf1\xf6\x86\xcf7\x83ś?\u007f Wa\x8eº\x94G~\x8c*|\xf3M\u007f\x05\xad\xe4\xf6\xb3\xc3^\xfd\xe6nY\xd7R\xfa\xe8\xeeo^\x05\xc3zz\x0e\xe4j=\x10\x8f\xc5#[ۀ\x01C^\xbaW\x81\xc1b\xa6H\xadR\x06\x01o\x05\xc00\xe7\rsd\x17\x91y46~ZC\xf1\xcb7\x9e{\xf0Ɨ\x8b\x1b\xa6\x8d\x8f\x8d\x1esݳǟ\xbdn\f\x928d]\xec\xa2I\x1b\xf7\xec\xbcU\xba\xfa֝{6N\x82\x9f\xebJgnys\xf3]\xef\xbf\u007f\xd7\xe67\xb7\xcc,\xd5m\xdc9\x1f\xe5F7\xcd\xdf\t\x85\xdc\xcb|s\xea湟\x013\xbfi\x13/\xfd峹7\xf7\xf9\x9bfe\u007f\v6ʏ\xf5z\xfb\xf5&1>\xa0+a\x83\xdaK\x00;\xf5\xa1i\x0e\xe8\nc*\xda\xdfk\xaf\x18\x13پ\xed\xb9m۞\x03\aΡѕ\x96\xb9\xa4s\x84\xd60\x99\x1f\xc5\xf4\x8dHzBτ\t=\x8bgW\xb6\xb6V\xce\x06O\x11R>\xbb\x9f\xed\xfe\x06#9\xb1\xaf~\x93\xe9\x1dVs#\x02\x86y\xef\x1d\v\xb0nI\x11UM\xb5R\x9d\xd4\x1c<\x9e\x92}H$\xbe\xcb\xdbո\xba\xdf6\x9c\x0e\x8e\a\xfb\xc6K\xf9\x8d.\x1a^\xfbP\xe3\xf3\a\xef\xdd\xf6\xe8}M\xb1̓\x99X\x93O__\f\x1e,\xae\xef!\xaa0\xccr\xd4\xc5I\xff\x83\xe8]\xa5\x9e^\xe3H@\x9c\xae\xe4L\xa4d\x93\xa9\xbe\\\x18LӤ\xfb\x1a\xc5\xf9\x81\x1d\xbf)5mb<\x93\x89O\x9c\x96J\xb7\xb5\x81\x83D\xd7F:ya\xec\xec\xf3\xe7\xd2\xef\xd0/\x11,%\xed\u05ff\xab\xff\xabv\xec#\xd9\x1c!\xc0o\x1bS\x83\x83\xe2\xec \r؋\xc7\xd8K\x13\x12n\xc7\xfabiBq}\xbf\xd6\xfc\xef\xb7c\xcf\u05c8丣\x83\x87\xcf&\xd4v龖\x04\xef\x90V\xcc^p\x8c\xf4\xc5%\x1a\xf1Bڹ\xc3L\xf7YL\x96\x03\x87LH|\x94\x9dF\xfd\xc8N\xd0\x19\r\xd0\xef\x83F\x83\t;9d\x88\x923Y\x99\x02\t\x11o\x80#A\x86\x93\xbd\xd9b玲I$^9J ^\xe6\x8fo\x9c\xfa\xe0\xf8\xf1\x0fZ*E_\xaa|D$\x9a_\xb6\xe0\xa1k\x0e56\x82\xad\xab\x90\xb82\xe2Ʃ\xc3\xd6Lmȟ\xb1x\x97\xf4\xe1\xef\xb6m\xfb\x00\xb8n_\xf7ɱ;'\x1c\xb8.6\xad\xaa\xb6\x01~\x8aģJ\xe9%\xe9E\xe9g\xd2/\x8cE5\xcdE.Ì\xce\xc5sn\x97\xb68ڗv\x0e\t\xb5t\xa4\x1d\x97\xff\x02D\x1ex\x10\x14\xbdr\xf9\xf0\x1b\x9e\xfd\xfa\xda礟/j\x1e\xd1\xda;\x1e\xccQR\xecnʋ$\x86;\xa9\x9f\x12\x1bO\xa26\x85^G \xcb\x10\xb9Ez\x03\xd1\xf9\x0f\xf6Y\xbe\x92\xefg\xbe\xa0&\xd1\xebU\x0fuB\xb2\xa4\x86\xb2\xf4W\x88\xb0\x90\xcd\u007fY{\x12o\x96\x12\xc4\x18\xa23A\x96\xd8\xf0\xc2\ac5\xbbY\xa2Y\x12\"q\xc0\x1a.\xe8\x0f\xa4SF\x82/\x84\xedMeg\x98H\x82\xf9\xb9\xd7\x024\xf5\xb3N\xbd\x1d^\x1e\x12\xbc\xf53\xcb\xd6\\\x11\x9f\x00m:\xb3\x92\xad\xf7\xbb\xce\x1e\xb3\x87\xfc.\xa6\xd2\x1ez\xb7\xd169lP\xf3\x86P\x14\xa5\x18i}\x91\xb5\x81Vi\xabD\x96\xa1\xbd\xa1Ty\xa8\xd0\x157\x00`\xe2\x1ck\xee(\x1b\xd6\\fs9\x84H\xbc&R\x13v\x1a\x14\x1c\xadPi\x8c*\xab\xb3@\xe5h\x18^\v\u07fcN\xa8\x1a5\xcekpW\x8dV>\x11IV-\x80\xa2ZP+\xbcB\xf3\x953\xbb5p\x8e%\x9f\xd6o\x04N\xb0\x1d\x8c\a\xc6\xc4\x02\x87ਟ\xdbq\xec\x1b\xe9\x8fo\x8c\x9fD\xdb\r6q\x83+\x1c\xb2\xa3\x1f\x1c\xb1uVh\x8cY\xa5ᔅ\xf1\xf1ё\xa9BV\x13ӊ\xf6\x91\xfa*\xbd\xcdb\xab\x04\f\x03K\xdd\xc1\xbah\xb4.8\xb3\xae\xc8̲\x906\xa8\x8b\x9e_\x9f^\xb7d\xf1\x9ady\xa4ԠԘ]B\"ђ)\xc5\xfe\xa4,\xa2\xdai\xb5\x8d37\x8fܿM:\xf3_\xde\xf6i\xb5\x1e\x83~\xd8X\xf5\x1f@\xc9\xe6\xe3\x8b\xd6,\xa1-\x1a\xabѬ\x14\xf2\x1f\xd8,}\xf4pa\xff\xf5\x86<2\xeb\v\xa9\x10\x8f\x848\x11\xbb\xa9\xb2\x8a<\xa8\x04|\x1c{\x80\xb9\xc8\b\xfbޝʰ\xf7\xdc~\x97Ő\xf7;\b,j^-\xcd@\x14\xb2\xf8d\x06.\xbe\x84=\xc2\u007f\xc1\x1f\x17\x874\xd2cj\xa7\x8d\x1f\n\x1au\nV%]\xfb\x918\xff\xde\x00\xdc})\x83\x02\xaeϷ\x93\x96\xec$'\b\x0e*\x95\xd3\xfdK\xa5\x8d\t\xa3\x1bX1\x8a\xa2l8HH̛J\x9b\x89\x9f\xf041\x84\xb4\x18E!gy\x83\u007f\x10\x8f,\xcdU=U\xcd=M5账\xe9\x19\xa0z\xa6GV\xf2\xeb!\xe7=G\xc9?l\xfc^3\xdbB_\u007fn\x95evM\xdb\xd6\x12\x9a\xc2IY\xaadkۖg\x9e\xd9\xf2\x94\xf45\xe0\x9f:\xb2\x19\x1eñl\xe5fp\x9dl\\C\fl\xfe\x9f\xa8;\xbc>\xfb\xffm\xdd\xc1\xf5\xd2\xffJ\xdd\xcb\x13\x96\xff\xf5\xba_\u007f\xfd\u007f\xa7\xe6\xfd\xeb\xae$\xf3\xb2\\\xfb\xbe\xba\xa3\xb9\xe4?\xaf7\xfa\xfbwj=zŊ\xd1\xffq\x8d\r}\x18Lx\xa5\t{\xabo\xa6FQ\x13\xa8.j.\xb5\x94ZM]Im\xa5n\xa2vQ{e\x8f\x17\xa0\xd7W`\x14\xa4el\xb9|cΑJJ\xb4b\xecL\x98sI\xcd\xe4\xec\x80R\xbd\xf1\xde0)\xa7\x04\x06\xa7\x0f\xce\xff-\xf7\xf7\xde\xc7\r\n\xd9;U\xaa\xecM*\xbb\xaaC\xa5*\x1e.T\xb4\xcc]\xb8\xeb<\x85\x19\xe9\x85\xcf\r\xebz\xad\xa3\x18]ʗ\x15u\xa7\x90@V\xe4\xcdޗSޕ5\x82\xa9\x01\x89\xfd3J'\xfaGr\x19d\v\xe4)\xfd\x8e,\x8f\x9e\x83ꁪaW\x15w\xfeiְ]\v\xcf\"F\x1ds\xf5\x1d-aאb\x95J:D\xee\x9br\xd11I\x8a\xe8\xf9\x96\xab'.J\t]\x94\x82-[\xfb|\xf5\x05\xa9\x12\x82\x98:\x94j\xa36\"y\xfbF\xeavj\x0fu/\xf5\b\xf5c\xeaY\xec\xc1\x17\xefx\xf5\xb1|\xc4P\xbd/\x86\xfe\xa8A\xdaޡ\\(\x0e\x8a\x87.\xc1]V\x83\x1c\x1e\x9eH\x96\x15\xd1\x04\xc4!\xba\xe9O6q\x91\xfa\x96r\xbe\xad\xfc\xc1\xe9\xbdq\xaeGv\x8eX?$K\r\xa9\x17\xb4\xd8q3̘\x9c&\x93\xb3\x83\x1c\xa3丣߹|d:dn\x1dI&\xbb\x16.\x1e\x19\x9d\x1f\x11\xd5\xeaB\xb5Zz\x89\x04b@\xe9\f&\xca[1\xbe㹞\x8b\xee~\xe3_\xa6\xc8O\x03G\x8f>\xb0\xea\x05\xfc\x84բ\xb8\xd4h\xb5\x1a\x9f^\xf5\xc0Q\xf0\x03|\xcd\x14\xedw4]\x94\x92\xed\x13\x0f`\xcf\xc2]\xa3\x04\x9dw`増\xc7\xfd\x18s\xc9\x04\x8e^toǿL\x91\xff\bψu\x1d)VB\xe3l\x86\x1aN\xad\x90u\xbcx$\xce\x12V\xce\v\xcc\x186\x01\xab\xbe\xe2\xff\xd8}y\x00\xf1q\x84c\xc3<$^\xe6G\xdc\x1fV\x17M\x05\xd2)$\xcf\xf7\x99U\x98e_y\xd8[\x1e\xc0\x8ań\xbb$\xf6`xK)J\xf6_Sn@\x9f6z\xf2D霘\xe71\x82\xa3\xd0-\xfd\xed=\x05F]` P\xec{\xfe\x88\xf4\xf2\x8f7\x9c>0\x1d\x80\x9f\xed\xe3!M\x03\x05\x04z\xc5m\xa7\xd7)\xf8\xd5?\x05\xf4\xcd\xf7\x80\xd8\xfb\x9b\xb3\xa77?\xbdy\xf3\xd3\xe0\xe0\xa2i\n\xc4\xdbXyUUê\x97Vl9\xaaU5\x0eQ\xf1y,4(\xa6/\x82\xf45\x1f\\}\xcb?o\x05\x93&,{w\xe6\x94)3\xdf]:\xf1~@}.m\x98@k\x94\xa5&\xaf^I\x8f\x01\xf1'\x1f\a%\xf7\xab\xf8ŏ\xfcq\xe3\x93\xd2\xeb\xa3i\xa5%O\x19\xd3(5L\xd5\xefA١\x9b\x01\xfb\xfcz\xa5j\xc5q\xe9\xfd ~\xe6\xe6\xf3\xd4\xfa\xb7\x87q\nU\xb2@\xa5J\xed\xe8X\xf6\xf4\f\x8d\xfeg[\xa6\xde_\xa3RE\x92J\x05\xd7rb\xe3\xe6\xd3\xd7r\xfcֿ\xe6|\x93\xcbv\xc5\x02\x9a\x0f\b\x9a\xfb \x94e4L\x9cE\xdfCލ\x90\xe5f\f?\xdc\xdd_^\x01r9\x00\xdb-R\x83\xe57~\xc0\xbd'\xc9rfna\x88\xee\xf3\xef@S\x1a4\xd6S\x11`\x8c@4z\xcb\xeb\xb29\x14\xae\v\xd5\xe9\xab\x13Me\x11\xa1`(x$\xef\xd3\xe8\x01\xd9\xfd\xbd\v\x01\xb0[vr\x0eQ\xa6\xf3\xe8\n\xa4p\xba\xbc\x9e\x88\xd3\xf1\nAW\x9f_v\xfc\xee\xd8\xd7.\x15L\xa7\x921@\x0e!\x9f\x1e\x84Cd/\x12;)̡\xa0X\x91\xc4?x\xa5\xee{;T\xaa\x8f?V\xa9v\xa0a\x15\x85v\u05608\xbc\xac\xff\xab\xbf\xfbm\xd9rqF\xe8ߦt\xbf\xfa\xc9\xeb>\xff\xb6_\xdcA\xb5\xfc\x18?\xe7\x81\a\xe4\xe7\xa0P5(~N{\xf1'\x06\x0f\\:o_\\z\x95\xa1\xba\aʬ\xbdc<\xa1%\f\x84}\x11[\x1f\x05\xf1\xecJ\xe95\xb6\xfb\x12<<\x98\v\x93\xd9_\x81\xe3\x97\xe2\xd7yR6$\xba\x1f\xd8\x17k\x94j\xa4~F\xbd\x85\xadLt\xe8\xb5\xeb\x00\xcbɦq\xd8N\xce\xda\xd7DrÄ{\xaf\x89\xe6 \xe9\xe6\x04\xb5\a\xf5x!E\xb6\x00\xf9:\xe0\x01\xa90\xde\xf0\xc4r \xde\xe9D\x17\xd18\x82\xf5\xccҡ\xb0\x8fhWaY\x13[\x9fp\xe8\x02\xbe\x8eq.\xd1p\x83Qr\xf0Fv:\n\xf9:&!\x12=\x19Q\xbeΊ\xd6PXǠ\x01&e\":\xa6آ}0\xf6\b\xab\xd6\x17hԺ\xa4A\x9a\xa2\xb0\xf2\n\x05oU\xf0{\xfd\x1a\xbf6\xa4\xd1\xc8\xc1:\x9c\xc4+D\x03\xb8\u07b73\x15\x8a2-m\x99\x10\x14y\x81\xd3\xd1,ͿH[\xbd>\xae`\xd2P\xa1P\xa3\x81\x01\x0e\xd0tQ\x05\xa7Z8\xaef\xb1\xd3\xcd\a\x12\x9e\x92\t:g\x8dA\x1b\x0f\vQ\xadV\xab*)\xd3Bȃ\xa0\xdb&\xfa\xe7\xf8\xf2\xa7\x1c1\x00\x95^o)*\x8c\f\x17\xa0\xd2k\xb4V\xe4y,Z\x9d\x82/X\xc8\x02\xa7V˸E\x8f\xa0\x87J?\x14m\x85\x82N+\x94\xbc\xf4\x84g\xc2jGl\xd1\xfc\xfa\xf0\xdfч|\f}\xb1\xc7\xc8\x17kC_\xac\xeds&`4\x16\x98\x8cl\xe0-\x85B!\xe2W\x12;\xfcZmH\xeb\xd3\xfa5\x9a\xb0ƿ\x1a\xa7+\x14\x06qJ\xa6(\xe4l\x9b9\xc1\xec\x0e@\vgQY\xf4\xa29O2\x99]:\xb3jXڠU\x03PRb\x8e\xa8Ty\x1d\xf1q[T|\xa2,1\xbb%\xa5g2\x15\x8bWZ\xd4B\x9e\x1d\x80\xb8\x13\xdd\xe4bh\xe7\xf4\xeb\xcbu\xa2aI,\xea{b\x98A\xad1٪D\xa3P놜\x12\xb0z\x96\a|$X>\xb7t\xde\xe5\xaeB\x8e\xe3\xe3\x91\xfa\xea\xc6\x06wʞ\xe7N\x85\x8a\xbdj\xdba\xa0\xecNn\xaa\x986~,\r\xc1\xbaKڠ\x83\xbeuX\x8c\x10h\x14\x89}y=HЂ\x9fh$\xe6\x16\xa1\xea\x18\x94\xc6A\x8cT\xe3\xcfg\xcb\xf1w\x17La엪\x9c͏\xa71a\xe0\xfcx\xdd\x0fr\xf3\x1e\r\x06\x9bJ\x8c\xf9\xf3t\xfc<\x97\xbe&5Q\xfa\xc7\xc4)`\x8e\xbf\xac6\x16/4M\x9b\xcc%\xd8\x1d\x9f\x94\x14go\x90\xb6oj,\x03\nZ\rcM\x9b\xc0Z\xf8\xdc\xf5\x9fp\x06\x86\x9d\xe6\xf5Lh\xce\xfe֩gGdW\x00\x96\xa6a\xc9\xf0\x9b\xa4\xe7\xa4\xe775Ł\"\xfb֨VFm\v\xd7\x15\xbe\x17\x94:jY\x0eh\xe6ڴ\xa5i\xb8\x19\xec\xf8\xb26\xaa͛\xabq4e\xa7Mݰn\x951\xb7\x1fBt\\\x8cT1U\x8ax\uec79\x95;$\x0f\xe8\x18\xbf1\ue99d\x80\xc5\x11H\x14\xaekh\xccb\x93Ą\xd1\x0fЏ\x0f\x85\xfdH\x84\x13\x12\x02\x8b\xba\v\xeb\xf3\xfb\x8a\x801\x9e\x10S\xe1\x10[.\xdbs\x94\xa3\f\xe9Kګ\xdc\x05\x00d\x15:\xa5\x12I\xef\x10\xd4\x00\xc0\xa8\x15J\x96\xa1\x19\x8e\xe5\x14,\r\xce~\xb0~=8\xbcp\x9fӬٻ\xa8dd\x11x\x80\xa5\r&\xaf%b\xb4(\x98Ns\xe0\x81\n\x1a\x80ZF\xefsE=\xab\x96\xf2\xeeX\xdc\xfbx\xff-9\xf8\xe1\x11FT\x18x\x05\rʡ\x826\xb0\xe2\xacu\xc0\xaa\xd0sJ\xd5n\xa8\xe2\xd5\x1c\x06\x18\xe0Ԭ\xee\fxO*\x00\xef\xfd\xee\xb6\x11(\xa8\x90^\x06\xf5\xbaF\xab\xc1fа4JH\xec\xae۷\xc5\xe5\xf5\xeb}wI\x05\xee@-m\x1a\xb4\xd7\xc1R\xa5硢\x95\xfd'\x9a\xd1,\x94\x1d\xb5\xe2\xcd(1\x14&^\xcbD\n\x0f+1\xac\xd3/\xe0\xd1\x04\xe0\xcd\x05\xa2\xaa\xc9\xd7\xd1\xd8\xf3\x05\x1f\xc2J_\x10\x8di\xb0^F\"\xe0\xd1\xfb\x87\xb1\x815\x1e<\xd0M\xd8ҍ\xe7\u009c\xdfKѾ\x90\x9f\xc30\x04\xa25J\xc7@\x14\xe5\x83\xd6\x1cc\x84\x87\xb2\x00\x83\xb8\"f\r\xc7j\xa3W.Z\xe51\xeem\x00\x1dҴ\xfbm^\x9a\x19\x17d\xd7\x17\xf9\x8a\xdd\xec\xfe\roJ\x1f\xec\xdb)\xfdm\xa1[_s\xdf\xf7\xb6E\n\xf2\v\x94\f}\xe5/\x0f\xaeof\xf4\x15\xbe+\xbe~\xfc\xd6`P\xf4\xdb\x19]\xf9q)\xbb\xedH\xe4\xba\xed\x1b\xc3\xe1\x9b\u05fex\xa6Ego\xfe\xfd륾ᝁ F\xcbi\x01\x88\xa4\x8d\xfe \x1a<\xa2\xc3\x16\xc5]4d+\v\x1a\xca\x12>\x85P\u007f0\x03\xd5c#ۜ\xe5z\x9fw/\xf0\x83\xca]\xbf=\xfds@+ܳ\x97<4\x91\xf6\xbd-\xbd\x03\xab\x9d#\x9fH\x95w\xdc4\x04\x96f\xc6EEi\xef\x01\x10xk\xe3\x82\ueab9\x89!\x16\x8e\xa1\x81+\x18T\xa9-\rm5\x81\x15_Vq\x91\x86&[\x9eA)\xd8f\xe4\xcd\b\x9a\x99\xee\x03ӆ\xa85\xd6\xd0,\xb0\x01(\xb7\xb5\x1d\x97>\xb9,_mW\xd1`\nЂ\xf8\xc6\x05\x9dv\xbb\xa69t\xed͛\v\v\xa1Eo\xcfs84*O\x8d\xc2{\xfb\x8d\xaf\x1c\xbcl\x96ӧo\xa9\t\x8d\xbaLjF\xdf/x^ý\xc7\xfe\x8d\xb2\xa2^\x90\xa1&\x12\x8fS\xa9P8\a\x8d\x86\x15>\xf8\x14\xd0A&\x80\xb9\xcc::\xcdف\x06 V\x937C3\xf1!D6d\x00\x1b\x05\xc5\xe8\x02\a\xad!X\xc7\x10|y:E\x85\xb1_%7\xa3\xa3\xd1\agk]\xc3&Tm\x9bc\xd2\xe8\xfdVO\x95#P_\x14\xcc3k\xd5*\xb0\"\xf9\xfc_\xa4/\xa4o>\u007f|\x1e\v\xf4\xaa\x10\x93\x98\xff\x05\x18\a\xba\xc1\x94\xcb\xcd\xf0\xcb1\xdb\u007fr\xfc'\xdb\xc7\xc8\x01X>\xe4\x8fҧ\xd2/\xa5\xf7%\xe9H\xbb\xbb\x8c\x1dyӳ\xa7>\xfb\xfb\xe9\xd7Z\xf3\xabj4һ\xffT@h\xdf\xf8\xc6\xf6n\x8bu\xf6\xad\xa7\xb6/~\xe6\xc0L\xf8y\xf1C\x95a\x97\xd9aU\xb14\xa3Wi\x83\xc1\x82@~\x9e\x16d\u007f\xb9\xe9\xe9\x19y\x89\xcdG\x81\xf5\x9e\xc8\xc4\xc8Z\xedqi\xab$ݥ9p\x8fC\xcb@\xcf\xf1\xe7\xf0&\xd0sr\xc0\xed<>K1\xe6ѿK\xf7\x1c;\x00J\xfe\xf6\xc6\xf7\xe6D\xac\xe3\xef\xb9,~\x93t\xd5\xdf\xc0\xa4&\x16\x95<\xf5\xb6g\u007f\xfd\xfaOvL\x86\xee\xd9;^\x97\xf5I\xc8\x18C\xf6\x01\xf1\x1aJ=\xd1\xe9^FmB}d\x1f\xf5C\x8a\x12,~\x1f\xf6P\x89xG\xec\xb92\xf1?\x8d\x0f\xe6\x85\xd0XVD~\xe5\xd8\x05h\"^\xfe?\x8c\x1f]n(5\xa0\xbf\xe5\xdf\x112?\xaa(8w\x14\xfbL\xa53\x05\x15\x881\xfa\xee[H\b\xa8\x1e\x83\xc1\xe0E\xbf\u007f\xf7l\xff7\x19\xfc\x18\x16?\xec\xac\x02\xa7\xa0+\x9f\u007fG(\xeb\x10\xc6\xd0\xfc6\x06}\x9b[0\xaf)\xdb\xe1ư4\x15\n\xd3A\xa3\x15k߄b\x80\u061d\xd4\xe2k\xc4Ŋ\x91\xa5uX\x84\xeeU\xf5#\xf8)V\xb6\x04\xb0\xc4\xea\xa07Ń\x8d\xcdD\xab\xc0\x1ae\x80\x95\x1ct\xb1\v[\xa7\xb9\xb1ٙ\x11\xfb>\x16\xf5@\xb6\xee\xd5\x03\xf284\xcd\x04\xb5 \x88-\u007f9\xf7\xa1\xa7\xadZ\xad.n}:\xad\x8d\x0f\xd3Ε\xfez\xdc\x00\xf3\xf2#\x86\xe5\xa1dh\xb9!\x92\x9f\a\rǥ\xbf\xce\xd5\x0e\x8bk\xd3O[\xe3:\xad\xd6\xfa\xf4!\x97]Y\xe8\x02)\x02\f\xf9\n\xa3t\xf8\x18\xbb\x03\x17dO\x8a\xb9r\x80\xfe\x12\xe5\x00\xfd\xa0r\x1cv\xc6\xe7P2\xd2+\x04\xd32\xe5*T\xda\xc1\xc1\xfcEڄ\x15Uj\xe1\xfePB\x15\x04\xc5wK\xc7Θ\n=\x82\xc2\xd4\xf3\x0e\xd6\x05|\xa7Ǥ\x10<\x85\xa63\xa0\xf2n魠*\x11ڿ\x10\x95fMh\x17\xe5s\xd1X>W\xb7gO\x1d\b\x14\x17\xb2\xb8\xa4\xa8N'\x17$\xbdu7\xa8\xbctAұ\xbbA\xf1\xc0\x82\xd8\xc2\xe2\x00\xc0\x05q\xf9\xb1h\xaf͌̇\x9b\xb0D\x050\x93\x8b'\x15\x0e\xcf*\x01\x93\x12\x88&4\x870<\vBXFF\xe3V\x80}\x9eo\xdfq|\xd5\xe5\xef\u07fb\x80Gg\xbf^\xb5\x1b\x98\x1f\x06ä\x83kש\xd4G\xa4\xb7\x8e\x9c\xb3\x81Nr\x0eJ\x8e\x1c\x82w\xc1\xe9\xab\u007fs`\x0eϏ\xba\xf9\xf5U\xe4L\xb9\x9d:\xcf\xd4J\xf7\xac\x92^\xb9\xef\t\xe9\xe5c\xb6k@\xe7\xe5 }ߓ\xa0\xe2\x98M\x9c$\xaf?\xe6\xf0\xfft\xa8^\"\xaaY\x8a\xf8\xa0S\x03\xbf\x10N[yļ\x94\x00+\x1f\x0e\xa2\x1f\xf3]p}\x8f\x1fL\xfc\xf0\xa1\xb2\xc7FY>\xb7HCA\xe9\xd5\xd2qp\xe2\xf3y\x9f\x81M?\xedx\x0e\xd6\xe2\tMzA\xfa\xe0\xcd\r\x1b\xde\x04>Dm\xbe7\xffr)y\xe3\x9c\xf4\x04蒾\x0fV\xe7\x97͍\xc3\x05\xa8\x94\xab\xd7\xcc\xfbl\xee\x941ύ\xe9\"wm\xe8_\x12\\s\t\xae\x10ɬ\xe7\x01?\x85=OM\xa2fR\x8b\xa95\xd4U\xd4C\xd4\x13\xd4\vԫ\xd4{\xd4G\xd4\x19\xf4\x8e\xd8\x06\xa7\x0e\x84eHa\x1a[\xe2\xa0y\x1a\x8b\x18\xb4\xec\xef\n\x9b=sD\x84 R\x82U\x94W%Rd1\xc2\x1a'\xf3=\x9euR\x8c(/_\xd4\x01 \xea\x009\x11\xa9ܺ\x05ַ\x13I\x97\xc4\n\x8c\"\xba%\x8c\xb3\xe4\xd6;\xa20\x95\xc6ݎ\xe0\x95\xa6\x10\x93\x81\xd8b\x90+M\xbe\x81\x94G`\x8dp\xb2\\\f\xe8{\x9e\xd8?sX\u0381R\xd9\x14\x13K\x96\xd0\xec\xc8\x16V7\xaf\xc4M3\x90\xa7y\x96\xc7>\xd0\xd5\n\xb5\x9as\a\x1c\xc0\xa0\xb4h\xd4)wd\xa1\xd5\x10\x0f\x16\x89c\x9a\xdd\x11\x13\u007f\v\xcbyt\x0e\x0e\xce\x04\\\xa2\xd9̌m\xe7\xcc\x16\x17\x037\xf1\x9ax\x99\xb1\xa95~n\bg\xd0\xebl4mp\u0089\x1a\xde\x17Ѩ\xd1!k\tԣI\xdcdBG\x96\x114\x15CB\x1a\x87s\xc85C\xcb\x17OYb\xbejo\xad\x06\xcc\xfb۰8=vMa\xa8.\xc0\x94/l\xf2n\xdd\xf7\xe8\xb0\xe1\xdb\xd7M\x8aq\xc9f\x8b\xf7\xecJ\x9d\xd2,\x94i\xc9\xf1a\xc6\xe4s2\xb4`0:\x99{\x19\x8bY\xf0),fs~v\xb1A\xeft\xd4\x1a\f\xfaT\x1d\xfc\x861\xe8\xf5\xb8\x1a\xa82?\xd1+E1\xe5V\x15\x97\x83h\x9e\x19\xe4\xd9cO=\x1a\x9e\x03\x81\x11B@\x03\x9a\xa1\xa1\x96U\xb1\x1c\rX\x83\x15\xe8y$c9\xb4\xa6h\xa1\xf3\xc6\r\xb7\x80\xa1\xb3\x19h\xcfׂU\n\xb5\x8eׇL_\xaaCAkHq\xff>\xa5\v\x84\f\xd2\xd7\xce\xf2\xd9yJ-\xed\xb9\xdf-?\xcc\xceI'\x8c\x91<\x85\x11\x1f\xe8TJ#\x982v\x87\xc6$d\x81\xb31\xa4\xa9h0\v\x1a\x98Y!}=\xb2\x9en\xefb\xd3J0\xacd\xfe\x88N݊\x9b\x0fT\xd5l_9V9\xfe\xcaJk\xda\xc2\x0f\x99\xbem\x84\xa1\xa3{\x1e\\n.ӡ\xb7>A\x97B0\xa2\xd7f\x84s\xd5f\x1f\xc3X\n|,c\xa5\x17:\xea\xd1k;\x9cu>Cv\x9c\xde\xc6\xd0F\x9dގ\xeasZL\x19\xf4\xaa\xe2\x94W\xf5\u007f\x00T\v\xe1\xb6\x00\x00\x00x\x9cc`d```a<=\xe1|Ed<\xbf\xcdW\x06nv\x06\x10\xb8b|\xd6\bF\xff\xff\xff\x9f\x81\x93\x91\r\xc4\xe5``b\x00\xea\x00\x00d#\v\xd7\x00x\x9cc`d``c\xf8\xcf\xc0\xc0\xc0\xc9\xf0\x1f\b8\x19\x19\x80\"Ȁi+\x00{\n\x05\xce\x00x\x9c\x8dVKk\x14A\x10\xaey\xf4<\x8c\x9b,\x86\x155\x04VIL\x94,\x8a\xa8\xe8E\xe6\xb0\x1e\xbd\x88\x1e\f\x88\"\xe2E\"\x82'sj\xfc\x19\xfe\x0f\xc1\xa3\xbfJ\xbc\xadU3U=ߴ\x93\xacK>\xaa\xbb\xba\xba\xdeՓ\xcc\xd3g\xe2_\xfa\x92(\xf9ET\xd2\u007f\xe1u\xc1\xb4\xf0=O\xd6\x02'{?\x99Law\x18\xae\xe3]+t\xcfw\xef\x99\xcc\x18\xe4^\xde\xe9nD.\xd3}k\xdb\xf7zՇ\v\xce\xfc\x04\x99\x1c쯍U}ɩ\xa7\x18o9\xe4\x9d:\xf4\x1d\u038b\x94\x12\xf6\xe5;\xe3\xf8\xac\xd8FШ\x9e\a\x82\xb2\xe7O\x9c\x0f\xb9;\xc5\xdcX\x0e\x14S\x17\xd5B\xe5\x8e[x\x88\xa3\xcbe#2U\x94o\xcb\x03ا\xccC\x1e\xfa\x9a\x84\xb8\x91\x9a\xaf\xae??✼\t9\xb2Xz{\x12w\x8a>\x9f\tO3\x8d\xdbE\xb5\x9f*\xfd\xc2\xfcDe\xf2\xb8\x97\x18[\x03\xbf=픖wE\xad:s\xade\xea\xa9I5o\xc6ÞR݇\xd8G\x9c\xaf\xc4\xf2\x85=SB\xfcP\xbb\x06s\x12\xce|W\x1f\x8d+\xf8Ⱥ\x16\x8c\t\xd7\xe0\x99\x80}[0\xc2\xdel\xe4]\x8d1V\xcb\xf5\xb0\xa7\xa3~\x81ٴ\xb3F\xe7o\xc2\xfb\x85\xdeM\xd9\xc7\xd4r\xa2\xf4\xad\xe4\x89\xf1\x8e\xef;\x01\xcb'\x85\xfa\xc2\xf2\x13\x9bO^gL\xf7\xc6\xea\xady\xb9h\xb3o\xbc\xc4\x0f\xf2\xfd\xd0\xf8l7\x13\xac\x9b/\xa8\xdd\xfd\xec\x1bӌr\xa7q3}\x04=vC\xc0\xfc\x16\x85\xc1C\xaf\x13\xedH\x0fF=\xbc\x11ǡv\x97\xed\f\xf1\x9f@\xf3i\xf3lr\xe1.\xfbr\xa44\xbcC\xa5\xf2\xb4\x0e\xf3үV\xf8\xa6\xb2\xecldV¬\x8aL\x05\xfe[\xbde\xf6\xebN\xfe\x04\xdf\xe90WԿ\x0f\xe5o\xba\x15ϓ\xfaios\x1bW\x8dwz:\xadz\xfe\xdc\xeaQ\xaf\xa9Y\x84\x03\xf3Y\xfd\x9f3\xb6\xc1\xc6R\xfdy\xcc\xebK \x87>?\xe1\xf3+#\xefB\x8c\xab\x8c\xf7|\xfeJ\xfd\xbe\xadzj\xa6\a\xb5\xfa\x1e\x83\xe56\x05\xf8]@\xbdUD-\xbfP\x87v\xcd>n໌u\xc0;\x83\xb5\xd6W\xf7\xdb\x05\xe8\xd4\x1eO\xad\xaf\xe0\xbdMeFY\xbeг\x94\xd7\xed\\\xd8l@\x9d\x83\xae*\xf2!\xee\x89\xea\x0f\xbd\xa8u?\x96'\xebm\x8c\xbb\x80\xf3\x92\xce\xef\r\xcc'\xe6\xb2\xfc18\v\xfd\xc8\xf6>\xb4w\u007f\xf6\xfaC\xfcÚ\\f\xb9M\xa6\xbbc}\xa1\xef\xf8~5\xce\u007f\x1e\xf9\xf7\x14l\xcd\xcd\x17\x88mo,.\xd5}\x9d\xf7\x1fY\xef\xa1\xf2\xb3r\xa8[\xd6K\x9d\u007f\xe9\xc7\xccf\\\xf5\ay\xb7\xa2\xfdB\xbfG\x0e\xedy\xda\xc2\x1e\xb1o\x95\x9e\xef\xd7C[\xb3\xa8\xbf\xfe\xe9\r\xe0\xef\xda\xdd|\x04\xf0\xbfE\x12\xcfE@\n\xbd\xee\xe9\xae\xe4\\}\xbc\x13d<\xdd\x14z\xde\xef/\xf5\n|\xf1x\x9c\xa5\x96{T\xcfg\x1c\xc7\xdf\xcf\xe3N.\xb9\x86\x10\x1ai\xcdB\x91d\x8a\x10b!\xe3\x10\x8b\xb93\xb3i\x9bM\x86\x89e\x8c$\u05f94\x97\xadM\xc8=\xe4\x1e'4r\x0f\xb9\x87\x90i\xae!\xece\xff\xf8\u007f\xeb\x9c\xf7\xf9\xfe\xbe\xcf\xf3\xb9\xbc\xdf\xef\xcf\xf3}Nҿ\u007f\x1e\xff\x011\x92\xa9\b\x16H6\x02dH\x85\x82A\x9eT8T*\xea\n\xaeH\xc5GJ%\xc6\x02\xf6K\xb2^\xca\r\x9c\x92\x1c\xa2\xa4\xd2\x03\xa52\tRY\xde\xcb\xf1\xeeHY\xc7\xc5Ryr*УB\xa6Tq\"(\x90*ѯ\xb2\x97T\xa5\x9c\xe4D\x9eS\xbaTu\xb4T-\b\xc4I\xd5\xe9\xe7\xccz\r\xf2j\x16\ap\xaaE/\x97\x19\x00N\xb5\xe3\xa5:\x9eR]\x17ɕ\x18W\xb8\xd5\v\x94\xeagKn\xf4l\x007w\xf2\xdcS\x90G\x0f\x8fG\xd2{\xf4o\xe8\x0fx\xbe\x1f\x0e\xd8\xf3D\xb3\xe7J\xa9\x11=\x1bé\t=\xbd\xe0\xe5Ż7\xb5\xbd\xe1\xeb\x9d,5\xe5w\xd30@N386C\xa7\x8f\x03\xa0\x8e\xcf&\xa99^5\xe7\xe9;\x14\xe4J-\xf6H~\xe8i\t>\xf0\x03\xf0j\xc5^+z\xfb\x93\xefO\x9d\x00\xf8\aP\xbbu/\x90/\xb5\xa1w\x1b\xb8\aR+\x90\xf8\xb6\xec\xb5\xe3\xbd=q\xed\xb3\xa4 \xeav@\u007fG\x1f\xa9S\xa2\x14LLgr\xba\xa0\xbf\v<\xbb\xe0\xfb\x87IR\b\x9cB\xe0\xd7\x15\x1d]\xf1\xa9\x1b<\xbb1\x83\xee\xc4ug\xbe\xa1\xec\xf7\xa0fO|\xecE\xdd\xde\xf8\xd4\a_\xfaP;\f\xaeap\xe9K\\?\xfc\xeeG\x8f\x8f\xa9\x11\x8e\x8e\x01\xe4\x0f\xc0ǁ\x85\x01\\\x06\x85\x00\xce\xc1\xe0Ti\b5\x87\xd0s\x18܇\xa1}8\xb3\x18A\xdf\x11p\x1a\t\xb7O\xa9?\x8a\xfc\xcf\xd8\x1f\xcd\xd9\xf8\x1cϿ\xa0\xf7\x18\xceR\x04\xf3\x89 \xf7Kr\xc6Q'\x92s\x13\x89?\xe3Y\x1fO\xdcw\xd1\xd2\x04\xe61\x91\xb5IN\x00\x9e\x93\xf10\x8a\xd9EQ\u007f\n\xb9S\xe09\x15\x8d?\xd0'\x1a\xee\xd3\xe00\x9d\xfc\x19i\xd2O\xc4\xcfdo\x1691\xcc1\x86\xbdٜ\x8fX\xf8Ų\x16\v\x9fX\xd6b9\x97s\xe8?\x87\x9c84\xc6Q+\x0e\x8f\xe6\xc2\u007f\x1e\xe7q>\xf3_\xc0\xac\x16:K\x8bຈ\xf9\xfcL\xaf\xc5\xf8\xb3\x84zK\xd9[\x8aw˘Y<\xfb\xbf\xe0\xcfr4/G\xc3\nf\xb6\x02\x9e+\x99\xd7*\xea$p\xd6V\xe3{\"\xb5\x12\xf1r\r\xefkr\xa4\xb5\xf4Z\x87\xc6u\xcc1\tnI\x9c\xeb\xf5x\xb4\x9e\xefc\x03\xdc7\xf0\x1dl\x80\xdfFzmd\x16\x9b\x98\xcbf\xfc\xdaL\xdd-\xd4ڂ\x1f[9\x87[\xe1\x9dL\xde6\xe2\xb7\xc1i{\xfa[\xec\x80G\n\x9aw\xa2o\x17:wSo\x0f3܇\x1f\xfb\xf0j?\xfcR镊\xdf\a\xf0\xf0\x00:\x0f\xe2\u007f\x1ag&\r>\x87\xe8u\x88:\x87\xa9s\x04\xbeGXK\x87˟\xc4\x1c\xa5\xe7Qt\x1c\x83\u007f\x06\xb5\x8e\xa3\xff8\xf3;\x81\xd6\x13\xde\xe7S\xeb\x19g\xe29\xbd^г\x80o\xa5\x00\x8e/\xd1\xf7\x12\xde/\xe1\xff\nͯX{]\\F\x15e\x8al\x92)\xfaH\xa6X\xbeL\xf1\f\x99\x12\x03eJ\x96\x03\vdJ9\xc98\x14\x06+eJ{Ȕ\xe1*.\x1b-\xe3\xc8o\xc7x\x99\xf2\xe92\x15|@6\xd7t\x8cL%7@l\xe5^\xa0@\xa6\xca\x1e\x19\xa7(\x99\xaace\xaaE\xcaT\x0f\x95q>%S\xc3\x1f\xf0\xacIN-\xea\xd7bυ\xbc\xda\xc4\xd7!\xb6.\xdcꎔqeϕ\x1e\xf5\x87ʸ\xe5ȸ\a\xcbxP\xa3!\xcfF\x11\x00ލ\xaf\xc84\xf1\x04I2^\t2ެ7%\xa6\x99\xab\fw\xa1i\x1e$\xe3\x8b\x1e\xdf<\x99\x16\xf4\xf3\x83\x8f_\xa6L+8\xfa;\xcb\x04гu\x9aL\x1b\x10\xb8X\xa6-\xf1\xed@\xfb\xd12A<;\xc0\xa7\xa3\v@c'8\a\xa3\xbb3\xbetAC\b\xe0.3\xdd\xe0\xd0=P&\x94\xb8\x1ep\xfb(\x1c\x10ۓ\x1e\xbd\xbc\x001\xbd\xd1\xd2\x1b\xef\xfa\xe0o\x1f\xe2\xc3\xd0\xdc\x17\x1e\xfd\xd8\v\x8f\x93\xe9O\xaf\xfe)2\x03\xe0\xf9\ty\x03\x13e\x06\xa1e0ڇd\xc9\feN\xc3\xc2d\x86\xc3g\x14\x1aF\xd3{\fu\xbeB\xdb\xd7p\x1f\x8b\xb6o\xa8\xff\xed\f\x99q\xe4D\xf2\x1c\x8f>\xee*3\x81\xbc\t\xccs\x023\x9e\x88\xaf\x93\xa8\xfb=\xf1\x93\xe16\x99\xfd(\xf2\xa7\xe0\xdfT~G\xb37\x8d\xdc\x1f\x99\xeb\xf47\x80\xdfL4\xcd\xc4\xdbY\xf8\x1aC\xbfٜ\x9b9\xe4\xc7\U0005c2ee\xb9\xccz\x1e\xb5\xe7\x13\xbb\x10]\x8b\xa8\xb7\x98\xb8%\xccq\t\x1a\x97\xb2\xb6\fϖ1\xc3\xf8T\x99\xe5\xcce\x05\xbdW\xa2e\x15}\u007f\x9d(\xf3\x1b=\x12\xe0\xcb\x1dd\x12r\xdf\xe2w\xbc\xf8\x83s\xb5\x1aoWs\x16\x12\xf1e\r\\\xd6\xf2\xbe\x16\xbd\xeb迎\xf7$\xfcH\xe2}\v\x1enEc2\xdepϘ\xed\xeco\xc7\xdf\x1d\x9c\x87\x1d\xe8K\x81S\n}w\xd2o\xd7\x1b\xb0\xb6\x9bZ{\xf0\u007f/\x1c\xf7\xc2o?9\xfb\x99w*z\x0e\xa0\xf9 \xfd\x0f\xc2%\rއ\xc0a\xfa\x1ca/\x1d\xcdG\xe1|\x8c\xfa\x19\xf4<\xcelO0\xab\x93!\x80\xbd\xd3\xcc\xe9\f\xbd\xcer\x96\xce\xe2Q&\xe7\xf5<\xfc/P3\v\\\xa4\x16w\x85\xb9D\xbd\xcbp\xb9\x8a\x0f\xd7\xc8ˆ\xc7\r\xf6n\xfa\xc9܂\xd7-\xf4\xe5\xc0?\x873u\x9b>w\xe8y\x87\xdfwᘋ\x8f\xb9ɀ\xda\xf7\xa8u\x1f}\xf7є\x87\x86<\xfc\xfa\x1bm\x0f\xe0\U000d0f07\xf8\xff\x98\xbaO\xf8~\x9fp\xee\x9f\xc2\xed)>\xe5\xc3\xef\x19k\xcfy\u007f\x81g\x05\xc4\x14\xa0\x85{ü\xe4,\xbc\xa2Ǜ\xfb\xe2u\x86\xac\xf1\x92\xb5β\x85\x03\x00\x1d(\x01M\x00x\x9c\x95\x93\xdfj\x13A\x14ƿݤMk\xa4`\xd1R\xbc\x90AD\xc1\x8bݴ\x94\x16\x827\xdb?\xe9Mhb\b\xa5W\xea6;I\x96&\xbbav\x92\x90k_@\xf0\x05\xc4+\x1f@\xbc\x17\xbc\xf4U\x04\x1f\xc1o'c\x13\xb1BMH\xe67g\xe6\xfc\xf9\xce\xd9\x05\xb0\xed<\x85\x83\xf9\xc7\xc7\x1b\xcb\x0e\xca\xf8d\xd9E\t\xdf,\x17p\x0f?-\x17Qv\x1eZ^\xc1\xa6S\xb7\xbcJ\xfb\xd4r\t/\xddg\x96\xd7p\xd7}oy\x1dw\xdc/\x96\xcbx\xe0\xfe\xb0\xbc\x81G\x85\x80Y\x9c\xe2:w\xafLƜ\x1dl\xe1\x9de\x97\xb7>[.\xe01\xbe[.b\xcbq-\xaf\xe0\tu\xcdy\x95\xf6זK\xf8輵\xbc\x86mwfy\x1d\xf7\xdd\x0f\x96\xcbx\xee~\xb5\xbc\x81\x17\x85\x02\x8e\x90b\x84\x19\x14b\xf4Ї\x86\xc01BL I\xa7\xa4\x04\x11\xcf\x05vQ\xc1\x0e\xf6\xe1\x91\x03\f\xf8\x15K^\x99\xd9I\xae\x92k\xee\x1d\xf1&\x8e\xd2\xd1LŽ\xbe\x16\xc7\xe1D\x8a\xd30\x89fb\xb7\xb2\xb3\xef\x89`0\x10\xe6(\x13JfRMdD\x87\x1a\xebI\x18/\xc0\xd4DK1\xe4\x8aZ\x9a\xe8`*\xb3t\xc8M\x8b\x96\x1eƬ d.\xb4do<\bU\xee\xdb\xc0\x19ڨ\xd3\xfb\x10U\xeeڴ\x9d\xe0\x02Mr\x8b;\xd4\x1ag\xedzpXm\xb4k'\x17\xcdF\xab}\xbb\x8c\xe7FUF\xb5\xf9]\x81=j;௲\xd4\x17\x9cK\x95\xc5i\"\xf6\xbc\x03\xafbD\xde.x\x93B$\xa5d\xa6\xe5y\x13\xbb&\x9d\xa0_j\xfe\xfb\xe6\xe4\xa6Q\xe5>\x1d\xd2\xefº\\ՒO\xd7\xe6\xcf-\x8a9\"Z\x87\xa6mW\xb4\x85\xb4j\x13\xef\x92\xed\\DI\xb8滎\xa9\x99Si\x0ed\x98IΩ+\x95Щ\xd0})\x16\xa3\xcddG\xe7»\xa92']\xaa\x13Z\x85\x91\x1c\x86\xeaJ\x84Z\xab\xf8rl\xae$\xa9\x8e;2\xb3\x83V\xa6\xb2\xbfz\xa3\xb4\xb8n\xceM\xcf\"\x16\xcf\x12L\x1f4\xfbR\xe5+\xee_\xeb\r\xff\x88\xe9\x19e\xe8k=\xaa\xfa~^^8\x8f\xef\xc5\xe9\xffD\xf09\xa9yW\x12\xd3y\xff\x1f1\xfd\x01E&\x99\xf4\xf1\vϋ\xd8\x11x\x9c}W\x05t\xe3ȲuU\x99b'\x19X\xa6\xb7̔ؖ\x9c,O`\x99\x99\xbd\xb2ݶ5\x96-\x8d 0\xcb\xcc\xcc\xcc̏\x99\xf61\xbf}\xcc̰\x8f\x99\xaa\xa4\xf6L\xe6\xfcs~N\xd2$ݾ\xdd}oW))L\xfd\xbf?\xf8\x1a\x17\x90\xc2\x14\xa5nJ]\x9f\xba.uc\xea\x96ԭ\xa9\x1bR\xb7\xa5n\x06\x04\x824d \v9\xc8\xc3\x10\x14\xa0\b\xc30\x02\xa3\xb0\f\x96\xc3\nX\t\x1b\xc1ư\tl\n\x9b\xc1\xe6\xb0\x05l\t[\xc1ְ\r\xbc\t\xb6\x85\xed`{\xd8\x01v\x84\x9d`g\xd8\x05v\x85\xdd`w\xd8\x03\xf6\x84\xbd`o\xd8\a\xf6\x851\x18\x87\x12\x94\xa1\x02\x06\x98P\x85\t\x98\x84\xfd`\u007f8\x00\x0e\x84\x83\xe0`8\x04V\xc1\x14L\xc3\f\xcc¡p\x18\x1c\x0eG\xc0\x91p\x14\x1c\r\xc7\xc0\xb1p\x1c\x1c\x0f'\xc0\x89p\x12\x9c\f\xa7\xc0\xa9p\x1a\x9c\x0eg\xc0\x99p\x16\x9c\r\xe7\xc0\xb9P\x83\xf3\xc0\x82zj4\xf5Fj\x04\x1a\xd0\x04\x05-hC\alX\r]p\xa0\a}p\xc1\x835\xe0C\x00!D0\a\xf3\xb0\x00\x8b\xb0\x16·\v\xe0B\xb8\b.\x86K\xe0R\xb8\f.\x87+\xe0J\xb8\n\xae\x86k\xe0Z\xb8\x0e\xae\x87\x1b\xe0F\xb8\tn\x86[\xe0V\xb8\rn\x87;\xe0N\xb8\v\xee\x86{\xe0^\xb8\x0f\xee\x87\a\xe0Ax\b\x1e\x86G\xe0Qx\f\x1e\x87'\xe0Ix\n\x9e\x86g\xe0Yx\x0e\x9e\x87\x17\xe0Ex\t^\x86W\xe0Ux3\xbc\x05\xde\no\x83\xb7\xc3;\xe0\x9d\xf0.x7\xbc\a\xde\v\xef\x83\xf7\xc3\a\xe0\x83\xf0!\xf80\xbc\x06\x1f\x81\x8f\xc2\xc7\xe0\xe3\xf0\t\xf8$|\n>\r\x9f\x81\xcf\xc2\xe7\xe0\xf3\xf0\x05\xf8\"\xbc\x0e_\x82/\xc3W\xe0\xab\xf05\xf8:|\x03\xbe\t߂o\xc3w\xe0\xbb\xf0=\xf8>\xfc\x00~\b?\x82\x1f\xc3O\xe0\xa7\xf03\xf89\xfc\x02~\t\xbf\x82_\xc3o\xe0\xb7\xf0\x06\xfc\x0e~\x0f\u007f\x80?\u009f\xe0\xcf\xf0\x17\xf8+\xfc\r\xfe\x0e\xff\x80\u007f¿\xe0\xdf\xf0\x1f\xf8/\xa6\x10\x10\x910\x8d\x19\xccb\x0e\xf3\xa9\x1dp\b\vX\xc4a\x1c\xc1Q\\\x86\xcbq\x05\xaečpc\xdc\x047\xc5\xcdps\xdc\x02\xb7ĭpk\xdc\x06߄\xdb\xe2v\xb8=\xee\x80;\xe2N\xb83\ue0bb\xe2n\xb8;\xee\x81{\xe2^\xb87\xee\x83\xfb\xe2\x18\x8ec\t\xcbXA\x03M\xac\xe2\x04N\xe2~\xb8?\x1e\x80\a\xe2Ax0\x1e\x82\xabp\n\xa7q\x06g\xf1P<\f\x0f\xc7#\xf0H<\n\x8f\xc6c\xf0X<\x0e\x8f\xc7\x13\xf0D<)\xf5:\x9e\x8c\xa7\xe0\xa9x\x1a\x9e\x8eg\xe0\x99x\x16\x9e\x8d\xe7\xe0\xb9X\xc3\xf3\xd0\xc2:6\xb0\x89\n[\xd8\xc6\x0eڸ\x1a\xbb\xe8`\x0f\xfb袇k\xd0\xc7\x00C\x8cp\x0e\xe7q\x01\x17q-\x9e\x8f\x17\xe0\x85x\x11^\x8c\x97\xe0\xa5x\x19^\x8eW\xe0\x95x\x15^\x8d\xd7\xe0\xb5x\x1d^\x8f7\xe0\x8dx\x13ތ\xb7\xe0\xadx\x1bގw\xe0\x9dx\x17ލ\xf7\xe0\xbdx\x1fޏ\x0f\xe0\x83\xf8\x10>\x8c\x8f\xe0\xa3\xf8\x18>\x8eO\xe0\x93\xf8\x14>\x8d\xcf\xe0\xb3\xf8\x1c>\x8f/\xe0\x8b\xf8\x12\xbe\x8c\xaf\xe0\xab\xf8f|\v\xbe\x15߆o\xc7w\xe0;\xf1]\xf8n|\x0f\xbe\x17߇\xef\xc7\x0f\xe0\a\xf1C\xf8a|\r?\x82\x1fŏ\xe1\xc7\xf1\x13\xf8I\xfc\x14~\x1a?\x83\x9f\xc5\xcf\xe1\xe7\xf1\v\xf8E|\x1d\xbf\x84_Ư\xe0W\xf1k\xf8u\xfc\x06~\x13\xbf\x85\xdf\xc6\xef\xe0w\xf1{\xf8}\xfc\x01\xfe\x10\u007f\x84?Ɵ\xe0O\xf1g\xf8s\xfc\x05\xfe\x12\u007f\x85\xbf\xc6\xdf\xe0o\xf1\r\xfc\x1d\xfe\x1e\xff\x80\u007f\xc4?\xe1\x9f\xf1/\xf8W\xfc\x1b\xfe\x1d\xff\x81\xff\xc4\u007f\xe1\xbf\xf1?\xf8_J\x11\x10\x12Q\x9a2\x94\xa5\x1c\xe5i\x88\nT\xa4a\x1a\xa1QZF\xcbi\x05\xad\xa4\x8dhcڄ6\xa5\xcdhsڂ\xb6\xa4\xadhkچ\xdeD\xdb\xd2v\xb4=\xed@;\xd2N\xb43\xedB\xbb\xd2n\xb4;\xedA{\xd2^\xb47\xedC\xfb\xd2\x18\x8dS\x89\xcaT!\x83L\xaa\xd2\x04M\xd2~\xb4?\x1d@\a\xd2At0\x1dB\xabh\x8a\xa6i\x86f\xe9P:\x8c\x0e\xa7#\xe8H:\x8a\x8e\xa6c\xe8X:\x8e\x8e\xa7\x13\xe8D:\x89N\xa6S\xe8T:\x8dN\xa73\xe8L:\x8bΦs\xe8\\\xaa\xd1ydQ\x9d\x1a\xd4$E-jS\x87lZM]r\xa8G}rɣ5\xe4S@!E4G\xf3\xb4@\x8b\xb4\x96Χ\v\xe8B\xba\x88.\xa6K\xe8R\xba\x8c.\xa7+\xe8J\xba\x8a\xae\xa6k\xe8Z\xba\x8e\xae\xa7\x1b\xe8F\xba\x89n\xa6[\xe8V\xba\x8dn\xa7;\xe8N\xba\x8b\xee\xa6{\xe8^\xba\x8f\xee\xa7\a\xe8Az\x88\x1e\xa6G\xe8Qz\x8c\x1e\xa7'\xe8Iz\x8a\x9e\xa6g\xe8Yz\x8e\x9e\xa7\x17\xe8Ez\x89^\xa6W\xe8\xd5\xd4\x1d\x99\xb6c\x05A\xa6\x17\x05v#\x1b(\xcbot\xf2\xaa?\xa7\x1c\xd7S\x99\x0e\xf7\xc3t\x10Z~A\x8a\x9a\xeay\xe1b:\n\x94\x9fn\xd9N/\x1fvj\x8e\xe5\xb7\x15\x86\x9d\x9c\xb4\xed D\xb7\x9b\xf5UϝS\xb9\xb5\xae۫\xd9\xfd|\\\xbbQHn\xab\x95\r\xecv\xdfr\xa8\xe1\xb63\xa1o\x05\x9dt\xc7\xed\xa9<Ϧj\x96\x13\xa6C\xbb\xa7Ҿk5\x87\x9b\xee|\xdf\xe1\x86\f\xe7\a\x9dl\xe4I\x95\xb1\xfbuw\xa1\xe89\xd6b\xada\xfb\rG1\xa7\xa7\xac0竖\xaf\x82N^\x96\x12O踍n\xba\xe5X\xed\x02o\xa6\xe9uܾ\n\ns\xae\x13\xf5T\x8d\xd7S\xd4M!\x18\xd2\xed\xc8ˮ\xf1\x1bnS\xe5\xeaV\\Sh\xb5\xd3\xfc\x17\xa4\xeb\xae\xdb\xcdKѳ\xfcn\xc6\xf3\xed~\x98mX=\xe5[\xe9\x96\xdb\x0f\xf9\xb9\xd3\xccڡ\xe5؍b\xa8\x16\xc2ZG\xd9\xedNX\x88\xdb\xf3v3\xec\x14\xf8Y\xbb_sT+\x1cN\x9a\r\xd5\x0f\x95_L:\xbe\xbc>\x92\xb4WGAh\xb7\x16Ӳ\x97\xa2\xddo\xf2{\tN\xb7\xe3wG[VCɩ\xd5\xe6\xec\xa6rs\x9e\xdd\b#_e=\xd5o\xd8N\xa1gy5Y\xab\xf2\xb3VS&\xe4\x13\xe6u\xaa\xa6\x1df\x82\x8e\xe5\xabL\xa3\xa3\xf8\x84D\xb0\x91 T^\xadn5\xba\xf3\x96\xdf\x1ciY|\x84\x83^~\xd0Hˡg<\x8bM\xc0\xc6p\xbd\\\xcb\xf5e|8~}Љgҝ\x8cZ\xad\x1a\xe10\xf3\xcc\xf9n\xb2\xf3\x91A'\xde\u0090\xe7DAM\x8cQ\xe8\xd9}\xdd,&&\x8a\xdb9\xb7\x1b\xd7#k\"\xc5G\xc28\xe9\r\xd9\xfd\x96\x9b\xc0\x82\x86\xafT?\xe8\xb8ሆ%\xae\x18b`\xd2*ԭ\xfe\xa0i\xf9\xbe;\x1f\xaf\xa3\x984\xe3U\xe4\x93v\xe4\xe9\xe7\xb1#\xe2#\x12\x1f\xf1r\x02{\xad\xaa\xb5\"\xc7\x19\xd6\xed\xa0g9\xcer\xb5\xd0p\xac\x9e\xb5nY\xe9\xb6\xddb\xdb)\xab\xc5w\xc4Wy\xb5\xc8Fc5\x86\xa4\xd1p\xdc@\r\xf3\xa9\xf4\xed~;~=\xc3\xe7\xd9W\xf9\x86\xe5\xa8~\xd3\xf2\xb3\xbe\xd5o\xba\xbd\\\xc3\xed\xf5X\xe3l\xcfj\xf7UX\x18\x9cW\xe4\xad;GY\x1f\xdb=\x9cW*\x1c\xe1\xad{\x9eL\xd9\xe0\v;\xdcb\x17*?!+\xea\x8e,a\x99^\xf8\x9c\xf2C\x9b\x19W\xe8~\xc7\xf5\xed\xb5l_\xcb\x19b\xc7\xd7\x1a\x1d\x99$\x9c\xb7C\xf6er\xf0b2\xb1}\xdc\x1bN\x1c_crߥ\xaeZL\xf3m\x0e\xf2z\xc9\xc1H؉z\xf5\x80\xd7*\a\xb7L\xf7d\xb9\xd2\x1f\x8a\x03I\xc7rZ\xc58\xba$1%'\xf3r\x88\x18q\xec~\x97͙\x1ce\u038b\x82\x0eok\x84o\x8f\xf29l\xd4\xe4q\x1cB\xec~\x96ɽ\xceb\xb1m3C=\xf1A\x12\x1d\x84&\xe3\xb0\x0f\xf8p\xe5\xbe\x17c\x8b'D\xa3\x83˛t\v\xf1\v\t\x99\xdep~\xb0\xd7l2s6\xeaK\f)\xb2\xc5\xf8\xd2\xc8\x017\xc9\x0f\x02\xea4\xf9R\xb0\x1b\xf8\xf0\xfa\xe9\xbar\x9cbC\x8e\xb5\xc5\a\x1b\xaaB\x87e\xd4\ue39b\xe2\xb6\\܊\xbcdD\x0edE\xe2\xc8\xdazG\xae\xdc`$\x9e`\xd9\x06C\x91\xb7!H\xa6\xe1\x18\xee\xd6Uv\xde\xe7;\xdfɄV\xd0\r\xb2\x1cQy3Cu\xdfV\xad\x86\x15\xa8\x8287\xb9'\x99\xb6\xefF^Z\xce2\xc3\x1e\x89\x9aٺ\xb28BP#\nYJ\x8fO\xc5\xf2b\xff\xd8^:\xb0\xe6TAΧVg\xa3v\xd9q\xae\xcf~\xc2\xc8A\xd7\xe1\x88\xe1\xdb]\x15vx\xc2vg(\xe2\xb8\xe4\xf3\xb4\x8a\xd7PwT\x86\xcdk78\xccG\x8d\xee\x10\xcb\xc8\xeb\xe1\xeb;\xba\xae\x15\x1f\xfb\xf2\xb6\xeb\xb6y7\xebb@q\xc9@\x865T\x8b\x05>s\x15\xc6;\xcd'M\xbe\xa4I#\xbe\xc4I3>+\xbe7\x1c\xc2\xfbA:p}\xb6\x1a\x17\xc9=\x89[|y\x06\x99-N*\x03\xaf\xa5y\xdd.\x1b\xa6\xcd\xfeorJ\xaa\xbb\xacqQ\xdbY\xde\x1c\x1eX;\xce(\x1c\xe3C\xf6k\xa88\xb6\xe6\xd9\xdb>koqD\xe4\x98Wpd\x115\xb6E=\xcfq\x81un\xab\xd1\xf8\x88k\x83\f6\x9ct\x13\xa7\xe6$\x95\xd6z\xcd\"cÎ\x1b\xf0\xe1\xab|\x10١(\x96\x17S\tc\xb6\xc1\x89J)\xce0.Geɔq:\x91-\xd4#\xdb\xe1\x1d\xb4\xf3\f\xf6$\xef\fY=f\xb7\xfa\r\x95\xed\xa9f\xd7\x0e\x8b-Y\x12\xb3\xacV\xbct\xc5y\xa0\x93\x84\xa9\xd6XK\xadh\xbaQ]\xacԗ\x13\x8f\xfd\xb7\xc1H\xe2\xbf\r\x86\xd8\u007f\x1b\xf4e_\x85\xf5\xf8\xe2\x12`~\x80(\xac\u007f5\xd7TA\x97\xd3Fֱ<\xa9b\xa3\x84\xc3=\xb7.\xfb\x8ao\xe3\xb0\xf6w\xec\xb7\u009a\xc8\r\xf5\xd4I3љw\xdb\xef\xf3f\x92w3\x9c\xfd\x9dł\x0e\x05|0˗\x86\xc08\f-\t\x83\xd2/\xa8\x05Ona\xa2.\v\xe8%\xefe\x82\x1e/$\xd3\xe2\xabէ\x9e\xea\xe4\xda\x1c\xeb<\xab\x99\xe70\x17\xfb\"/\xdf\x12\xf2\xe6h܈C\v\xbb\xb9\x99\xe73\xe6\xece9i\xf9b\x18\x8a\x17į9\xcb\xd6\xc5;\x1d\x808\x98$\xc9\"\xbe\xbf\xe9\x06G\xb1!\x81H\xba\xecJ\xb0aW\xa6k\xa5\xeadqIf)\x06\x11\xdfH\xbe\xbe\xb6Ƕ\x8e\xeaI\x8b_\x9b(\x0f{\xd1ڵrv\xb6j(N\xa02\xa1\x1c\xe3\xe8\xfaf-\xfe\xf0\xea\xd8\xcai\x8e\x0e\x12M\xb2\x9a\x15\x92\xa2j\xec&\xf6Pd\a\x1d>Q\x9f\x83\x9d\x92ij\xd0hr\x80\xd2\xd9&\x18|\xb4\xac\xdc`D\a\xa8\xa5C\x12\xa0\x96\xf6\xe3\x00\xd5\t{\x8e\x91n\x04A9\xcb\xde\xe4\x90YH\xa2\xaa61G&Ύ\x1b\xb1\xdfm/\xb0\x83%\tiź\xb1A\xd2J\xd7\xcac\xe5\xa1\xf8\xd3O\xe6\xcf\xf2 \xafwt\xfd\x97C\x9c\xae\x93\x90\x1f\x0f\xe6\x1dŗ^l\x984b\xc7&\xcf\xe3ψ8\xac\xc7W\xa2V\x1e/\x15\x92\x94\x1fg\x04\xbe\xf6|\xad%\xb3%\x06Y\xef\x14\xb6\xae\xbc]%\x15\xf9Ԯ{\x14\x05M\xb2\xfb>\xad\xf6\x16ɏ\xea\xd4\xf5\xe7\xa9\x1e6\xe43Y\r\xad\xbb\xb3\xcb\xe38T\x17cx\x1d\xab\xce7\xb2V.M\xae\\7\x1ar8\xadG\xa1\n6\xfd\xbfC\xb2\xad\x91\xc1p\x1c\x83WlЋcS\xad\\\xaeHa\f/r6\x8d\xeaz#\xba\x93^`\x99\x87\x16\x06\x9f\x1e\xebޑ\xc3\xcc5\xd9,\xfcQ\xcd!\x9d\xbf\xf4\x06\xc1\x8b\xbf\xb1\xb8\xdf\xf6\xad^\xb6\xc5ߴ]\x9f\xac&\x87\x8e\xf1\xea\xf8h\xdd\x0e\xeb\x91\x1c\xbd\x96\x81#\xa1\xe3\x17\x93*\x1eZ\xe6\xb8L\xb4>K\x8d,\xe9G\xdeҧ\xe2\xab\xe5K\xfa\xc9\x15\x9f\xe7\xcf\\w>\xc8\xf15\xf5]\xbb\x99\xe1\x8b\x11-\xf02\xed\xba䖠\xbb\xe8qRs#?X\x13\xb1b\xfc9\xc0Vq\xb3-\x0eˎJK!\t<\xb4=\n\"\x91\xd64s\xf2ύ=\xa7\xa8\x1e\xb5q\xae\x9b\x99Wv\xdd\xe5\u007f\x1c\xfa\xfc\xcb/TK\xa3\xf1\xdek\x83\xcd\xcbXe\x93dI\x83\x9c\xeb$9G\x1e\x99\xa3M7\\\xf2@\xc6&\x86\xe7\xf8S\x9c\xbfJ\xe35\xf1\xc8\xc4\xd8H\x92\xd9⁚+C%)\xcaR\x88V\x13\x86\x14\xa6\x14U)&\xa4\x98\xccE}\xfb\xd0\xf1Uc|\xd6\xd68\x8fL\nh\xb2,]\x01M\nhR@\x93\x02\x9a\x14\xd0\xe4d\xbaV\x19\x8b\x11ui\x95\xa4(KQIf\x9b\x1a\x97\x8e)EU\x8a\t)\x044>&\x85<\x1d\x17и\x80\xc6+R\x18R\bb\\\x10\xe3\x82\x18\xd7k\x9b\x1eӵ\xe0J\x82+\t\xae$\xb8\x92\xe0J\x82+\t\xae$\xb8\x920\x95\x85\xa9,\x88\xb2 ʂ(\xeb\xe5\xcd\xe8\tg\xc6u\x1d\xbf!в\xa6\x9c1tm\xeaZ&\xaf\xc8\x1c\x15a\xad\bkEX+\xf1\x03\x81V4tV\x88\r!6dZC@\x86\x80\f\x01\x19\x022\x04d\bȐ\xa5\x9a\x820\x05a\n\xc2\x14\x84\xa9\x97zh\xfcL@f\x95ϻ\x15?\x13PU\x1eT\x05T\x15PU\x1eT\x85\xa6*4US^nHKh\xaa\x82\x98\x10Ą \xc4\x17\x15\xf1EE|Q\x11_T\xc4\x17\x15\xf1EE|Q\x99\x10Ĥ &\x05!\xa6\xa8L\nb\xb2\x92n\x95b\x19\xd9\x14܊\x1f\bBLa\xb0)\xb8\x18\x97\xa2$EY\x8a\x8a\x14\x86\x14\xa6\x14U)&\xa4\x98\xcc\xcc)\x0e\x9b\xdc\x14K\x182\x97!\x960\xc4\x12\x86X\xc2\x10K\x18b\tC,a\x8c\vIIHJ\x82\x103\x18b\x06C\xcc`\x88\x19\f1\x83!f0\xc4\f\x86\x98\xc1\x103\x18b\x06C\xcc`\x88\x19\f\t_FY\x10eA\x94\x05!\x1e0ʂ\xa8\b\xa2\"\x88\x8a DzC\xa47DzC\xa47DzC\xa47*\x820\x04!\xba\x1b\xa2\xbb!\xba\x1b\xa2\xbb!\xba\x1b\xa2\xbb!\xba\x1b\xa2\xbb!\xba\x1b\xa2\xbb!\xba\x1b\xa2\xbb!\xba\x1b\xa6 LA\x88\xe8\x86)\bS\x10,z\xab\xc4\b.\x04\xc1\xa2sK\x10\"\xba!\xa2\x1bUAT\x05!\xa2\x1b\"\xba!\xa2\x1b\"\xba!\xa2\x1b\"\xba!\xa2\x1b\"\xba!\xa2\x1b\"\xba!\xa2\x1b\"\xba!\xa2\x1b\"\xba!\xa2\x1b\"\xba1)\b\x89\x04\x86D\x02C\"\x81\xc1\xa2\xb7JU\x15۴41\xa6kƙ\"\xbd)қ:\x1e\x94&\f]\x9b2X\x95bB\n\xe63\xc5K\xa6\xe8o\x8a\xfe\xa6\xe8o\x8a\xfe\xa6\xe8o\x8a\xfe\xa6\xe8o\x8a\xfe\xa6\xe8o\x8a\xfe\xa6\xe8o\x8a\xfe\xa6\xe8o\x8a\xfe\xa6\xe8o\x8a\xfe\xa6\xe8o\x8a\xfef)\xb9\x96\xa5Uz\x85\xab\xc6u]\xd2uY\xd7z\xa9\xab\xf4RW\x99\xba\xae\xeazB׃\xf9V\xe9zJ\xd7Ӻ\x9e\xd1\xf5lROi\xde)\xcd;\xa5y\xa74\xef\x94\xe6\x9dҼS\x9awJ\xf3Ni\xde)\xcd;\xa5y\xa74\xef\x94\xe6\x9dҼS\x9aW\a\xcdҴ\xe6\x9dּӚwZ\xf3Nk\xdei\xcd;\xady\xa75\xef\xb4\xe6\x9dּӚwZ\xf3Nk\xdeiͫckI\xc7\xd6Ҍ\xe6\x9dѼ3\x9aWGؒ\x8e\xb0\xa5\x19\xcd;\xa3yg4\xef\x8c\xe6\x9dѼ3\x9awF\xf3\xceh\xdeY\xcd;\xabyg5\xef\xac\xe6\x9dռ\xb3\x9awV\xf3ΊS&5\xe9\xac&\x9dդ\xb3\x9atV\x93\xcej\xd2\xd9\xd9\xff\x01\xba\t\a\x8c\x00\x00\x00"), + } + fileg := &embedded.EmbeddedFile{ + Filename: "index.html", + FileModTime: time.Unix(1576651902, 0), + + Content: string("\n\n\n \n Vitess\n \n\n \n \n \n \n\n \n \n\n \n \n\n \n\n\n Loading...\n\n\n"), + } + fileh := &embedded.EmbeddedFile{ + Filename: "inline.js", + FileModTime: time.Unix(1576651902, 0), + + Content: string("!function(e){function __webpack_require__(r){if(t[r])return t[r].exports;var n=t[r]={i:r,l:!1,exports:{}};return e[r].call(n.exports,n,n.exports,__webpack_require__),n.l=!0,n.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,o,c){for(var _,a,i,u=0,p=[];u1;){var o=r.shift();i=i.hasOwnProperty(o)&&isPresent(i[o])?i[o]:i[o]={}}void 0!==i&&null!==i||(i={}),i[r.shift()]=n}function getSymbolIterator(){if(isBlank(h))if(isPresent(n.Symbol)&&isPresent(Symbol.iterator))h=Symbol.iterator;else for(var e=Object.getOwnPropertyNames(Map.prototype),t=0;t=0&&e[r]==t;r--)n--;e=e.substring(0,n)}return e},StringWrapper.replace=function(e,t,n){return e.replace(t,n)},StringWrapper.replaceAll=function(e,t,n){return e.replace(t,n)},StringWrapper.slice=function(e,t,n){return void 0===t&&(t=0),void 0===n&&(n=null),e.slice(t,null===n?void 0:n)},StringWrapper.replaceAllMapped=function(e,t,n){return e.replace(t,function(){for(var e=[],t=0;tt?1:0},StringWrapper}();t.StringWrapper=s;var a=function(){function StringJoiner(e){void 0===e&&(e=[]),this.parts=e}return StringJoiner.prototype.add=function(e){this.parts.push(e)},StringJoiner.prototype.toString=function(){return this.parts.join(\"\")},StringJoiner}();t.StringJoiner=a;var l=function(e){function NumberParseError(t){e.call(this),this.message=t}return r(NumberParseError,e),NumberParseError.prototype.toString=function(){return this.message},NumberParseError}(Error);t.NumberParseError=l;var c=function(){function NumberWrapper(){}return NumberWrapper.toFixed=function(e,t){return e.toFixed(t)},NumberWrapper.equal=function(e,t){return e===t},NumberWrapper.parseIntAutoRadix=function(e){var t=parseInt(e);if(isNaN(t))throw new l(\"Invalid integer literal when parsing \"+e);return t},NumberWrapper.parseInt=function(e,t){if(10==t){if(/^(\\-|\\+)?[0-9]+$/.test(e))return parseInt(e,t)}else if(16==t){if(/^(\\-|\\+)?[0-9ABCDEFabcdef]+$/.test(e))return parseInt(e,t)}else{var n=parseInt(e,t);if(!isNaN(n))return n}throw new l(\"Invalid integer literal when parsing \"+e+\" in base \"+t)},NumberWrapper.parseFloat=function(e){return parseFloat(e)},Object.defineProperty(NumberWrapper,\"NaN\",{get:function(){return NaN},enumerable:!0,configurable:!0}),NumberWrapper.isNumeric=function(e){return!isNaN(e-parseFloat(e))},NumberWrapper.isNaN=function(e){return isNaN(e)},NumberWrapper.isInteger=function(e){return Number.isInteger(e)},NumberWrapper}();t.NumberWrapper=c,t.RegExp=i.RegExp;var u=function(){function FunctionWrapper(){}return FunctionWrapper.apply=function(e,t){return e.apply(null,t)},FunctionWrapper.bind=function(e,t){return e.bind(t)},FunctionWrapper}();t.FunctionWrapper=u,t.looseIdentical=looseIdentical,t.getMapKey=getMapKey,t.normalizeBlank=normalizeBlank,t.normalizeBool=normalizeBool,t.isJsObject=isJsObject,t.print=print,t.warn=warn;var p=function(){function Json(){}return Json.parse=function(e){return i.JSON.parse(e)},Json.stringify=function(e){return i.JSON.stringify(e,null,2)},Json}();t.Json=p;var d=function(){function DateWrapper(){}return DateWrapper.create=function(e,n,r,i,o,s,a){return void 0===n&&(n=1),void 0===r&&(r=1),void 0===i&&(i=0),void 0===o&&(o=0),void 0===s&&(s=0),void 0===a&&(a=0),new t.Date(e,n-1,r,i,o,s,a)},DateWrapper.fromISOString=function(e){return new t.Date(e)},DateWrapper.fromMillis=function(e){return new t.Date(e)},DateWrapper.toMillis=function(e){return e.getTime()},DateWrapper.now=function(){return new t.Date},DateWrapper.toJson=function(e){return e.toJSON()},DateWrapper}();t.DateWrapper=d,t.setValueOnPath=setValueOnPath;var h=null;t.getSymbolIterator=getSymbolIterator,t.evalExpression=evalExpression,t.isPrimitive=isPrimitive,t.hasConstructor=hasConstructor,t.escape=escape,t.escapeRegExp=escapeRegExp}).call(t,n(82))},4,function(e,t,n){\"use strict\";var r=this&&this.__extends||function(e,t){function __(){this.constructor=e}for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);e.prototype=null===t?Object.create(t):(__.prototype=t.prototype,new __)},i=n(217),o=n(41),s=n(215),a=n(897),l=function(e){function Subscriber(t,n,r){switch(e.call(this),this.syncErrorValue=null,this.syncErrorThrown=!1,this.syncErrorThrowable=!1,this.isStopped=!1,arguments.length){case 0:this.destination=a.empty;break;case 1:if(!t){this.destination=a.empty;break}if(\"object\"==typeof t){t instanceof Subscriber?(this.destination=t,this.destination.add(this)):(this.syncErrorThrowable=!0,this.destination=new c(this,t));break}default:this.syncErrorThrowable=!0,this.destination=new c(this,t,n,r)}}return r(Subscriber,e),Subscriber.create=function(e,t,n){var r=new Subscriber(e,t,n);return r.syncErrorThrowable=!1,r},Subscriber.prototype.next=function(e){this.isStopped||this._next(e)},Subscriber.prototype.error=function(e){this.isStopped||(this.isStopped=!0,this._error(e))},Subscriber.prototype.complete=function(){this.isStopped||(this.isStopped=!0,this._complete())},Subscriber.prototype.unsubscribe=function(){this.isUnsubscribed||(this.isStopped=!0,e.prototype.unsubscribe.call(this))},Subscriber.prototype._next=function(e){this.destination.next(e)},Subscriber.prototype._error=function(e){this.destination.error(e),this.unsubscribe()},Subscriber.prototype._complete=function(){this.destination.complete(),this.unsubscribe()},Subscriber.prototype[s.$$rxSubscriber]=function(){return this},Subscriber}(o.Subscription);t.Subscriber=l;var c=function(e){function SafeSubscriber(t,n,r,o){e.call(this),this._parent=t;var s,a=this;i.isFunction(n)?s=n:n&&(a=n,s=n.next,r=n.error,o=n.complete,i.isFunction(a.unsubscribe)&&this.add(a.unsubscribe.bind(a)),a.unsubscribe=this.unsubscribe.bind(this)),this._context=a,this._next=s,this._error=r,this._complete=o}return r(SafeSubscriber,e),SafeSubscriber.prototype.next=function(e){if(!this.isStopped&&this._next){var t=this._parent;t.syncErrorThrowable?this.__tryOrSetError(t,this._next,e)&&this.unsubscribe():this.__tryOrUnsub(this._next,e)}},SafeSubscriber.prototype.error=function(e){if(!this.isStopped){var t=this._parent;if(this._error)t.syncErrorThrowable?(this.__tryOrSetError(t,this._error,e),this.unsubscribe()):(this.__tryOrUnsub(this._error,e),this.unsubscribe());else{if(!t.syncErrorThrowable)throw this.unsubscribe(),e;t.syncErrorValue=e,t.syncErrorThrown=!0,this.unsubscribe()}}},SafeSubscriber.prototype.complete=function(){if(!this.isStopped){var e=this._parent;this._complete?e.syncErrorThrowable?(this.__tryOrSetError(e,this._complete),this.unsubscribe()):(this.__tryOrUnsub(this._complete),this.unsubscribe()):this.unsubscribe()}},SafeSubscriber.prototype.__tryOrUnsub=function(e,t){try{e.call(this._context,t)}catch(n){throw this.unsubscribe(),n}},SafeSubscriber.prototype.__tryOrSetError=function(e,t,n){try{t.call(this._context,n)}catch(r){return e.syncErrorValue=r,e.syncErrorThrown=!0,!0}return!1},SafeSubscriber.prototype._unsubscribe=function(){var e=this._parent;this._context=null,this._parent=null,e.unsubscribe()},SafeSubscriber}(l)},4,function(e,t,n){var r=n(15);e.exports=function(e){if(!r(e))throw TypeError(e+\" is not an object!\");return e}},function(e,t,n){\"use strict\";var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=o<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if(\"object\"==typeof Reflect&&\"function\"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(o<3?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){if(\"object\"==typeof Reflect&&\"function\"==typeof Reflect.metadata)return Reflect.metadata(e,t)},o=n(0),s=function(){function DomHandler(){}return DomHandler.prototype.addClass=function(e,t){e.classList?e.classList.add(t):e.className+=\" \"+t},DomHandler.prototype.addMultipleClasses=function(e,t){if(e.classList)for(var n=t.split(\" \"),r=0;rwindow.innerHeight?-1*i.height:o,r=a.left+i.width>window.innerWidth?s-i.width:0,e.style.top=n+\"px\",e.style.left=r+\"px\"},DomHandler.prototype.absolutePosition=function(e,t){var n,r,i=e.offsetParent?{width:e.offsetWidth,height:e.offsetHeight}:this.getHiddenElementDimensions(e),o=i.height,s=i.width,a=t.offsetHeight,l=t.offsetWidth,c=t.getBoundingClientRect(),u=this.getWindowScrollTop(),p=this.getWindowScrollLeft();n=c.top+a+o>window.innerHeight?c.top+u-o:a+c.top+u,r=c.left+l+s>window.innerWidth?c.left+p+l-s:c.left+p,e.style.top=n+\"px\",e.style.left=r+\"px\"},DomHandler.prototype.getHiddenElementOuterHeight=function(e){e.style.visibility=\"hidden\",e.style.display=\"block\";var t=e.offsetHeight;return e.style.display=\"none\",e.style.visibility=\"visible\",t},DomHandler.prototype.getHiddenElementOuterWidth=function(e){e.style.visibility=\"hidden\",e.style.display=\"block\";var t=e.offsetWidth;return e.style.display=\"none\",e.style.visibility=\"visible\",t},DomHandler.prototype.getHiddenElementDimensions=function(e){var t={};return e.style.visibility=\"hidden\",e.style.display=\"block\",t.width=e.offsetWidth,t.height=e.offsetHeight,e.style.display=\"none\",e.style.visibility=\"visible\",t},DomHandler.prototype.scrollInView=function(e,t){var n=getComputedStyle(e).getPropertyValue(\"borderTopWidth\"),r=n?parseFloat(n):0,i=getComputedStyle(e).getPropertyValue(\"paddingTop\"),o=i?parseFloat(i):0,s=e.getBoundingClientRect(),a=t.getBoundingClientRect(),l=a.top+document.body.scrollTop-(s.top+document.body.scrollTop)-r-o,c=e.scrollTop,u=e.clientHeight,p=this.getOuterHeight(t);l<0?e.scrollTop=c+l:l+p>u&&(e.scrollTop=c+l-u+p)},DomHandler.prototype.fadeIn=function(e,t){e.style.opacity=0;var n=+new Date,r=function(){e.style.opacity=+e.style.opacity+((new Date).getTime()-n)/t,n=+new Date,+e.style.opacity<1&&(window.requestAnimationFrame&&requestAnimationFrame(r)||setTimeout(r,16))};r()},DomHandler.prototype.fadeOut=function(e,t){var n=1,r=50,i=t,o=r/i,s=setInterval(function(){n-=o,e.style.opacity=n,n<=0&&clearInterval(s)},r)},DomHandler.prototype.getWindowScrollTop=function(){var e=document.documentElement;return(window.pageYOffset||e.scrollTop)-(e.clientTop||0)},DomHandler.prototype.getWindowScrollLeft=function(){var e=document.documentElement;return(window.pageXOffset||e.scrollLeft)-(e.clientLeft||0)},DomHandler.prototype.matches=function(e,t){var n=Element.prototype,r=n.matches||n.webkitMatchesSelector||n.mozMatchesSelector||n.msMatchesSelector||function(e){return[].indexOf.call(document.querySelectorAll(e),this)!==-1};return r.call(e,t)},DomHandler.prototype.getOuterWidth=function(e,t){var n=e.offsetWidth;if(t){var r=getComputedStyle(e);n+=parseInt(r.paddingLeft)+parseInt(r.paddingRight)}return n},DomHandler.prototype.getHorizontalMargin=function(e){var t=getComputedStyle(e);return parseInt(t.marginLeft)+parseInt(t.marginRight)},DomHandler.prototype.innerWidth=function(e){var t=e.offsetWidth,n=getComputedStyle(e);return t+=parseInt(n.paddingLeft)+parseInt(n.paddingRight)},DomHandler.prototype.width=function(e){var t=e.offsetWidth,n=getComputedStyle(e);return t-=parseInt(n.paddingLeft)+parseInt(n.paddingRight)},DomHandler.prototype.getOuterHeight=function(e,t){var n=e.offsetHeight;if(t){var r=getComputedStyle(e);n+=parseInt(r.marginTop)+parseInt(r.marginBottom)}return n},DomHandler.prototype.getHeight=function(e){var t=e.offsetHeight,n=getComputedStyle(e);return t-=parseInt(n.paddingTop)+parseInt(n.paddingBottom)+parseInt(n.borderTopWidth)+parseInt(n.borderBottomWidth)},DomHandler.prototype.getViewport=function(){var e=window,t=document,n=t.documentElement,r=t.getElementsByTagName(\"body\")[0],i=e.innerWidth||n.clientWidth||r.clientWidth,o=e.innerHeight||n.clientHeight||r.clientHeight;return{width:i,height:o}},DomHandler.prototype.equals=function(e,t){if(null==e||null==t)return!1;if(e==t)return!0;if(\"object\"==typeof e&&\"object\"==typeof t){for(var n in e){if(e.hasOwnProperty(n)!==t.hasOwnProperty(n))return!1;switch(typeof e[n]){case\"object\":if(!this.equals(e[n],t[n]))return!1;break;case\"function\":if(\"undefined\"==typeof t[n]||\"compare\"!=n&&e[n].toString()!=t[n].toString())return!1;break;default:if(e[n]!=t[n])return!1}}for(var n in t)if(\"undefined\"==typeof e[n])return!1;return!0}return!1},DomHandler.zindex=1e3,DomHandler=r([o.Injectable(),i(\"design:paramtypes\",[])],DomHandler)}();t.DomHandler=s},[1104,5],function(e,t,n){\"use strict\";var r=this&&this.__extends||function(e,t){function __(){this.constructor=e}for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);e.prototype=null===t?Object.create(t):(__.prototype=t.prototype,new __)},i=n(6),o=function(e){function OuterSubscriber(){e.apply(this,arguments)}return r(OuterSubscriber,e),OuterSubscriber.prototype.notifyNext=function(e,t,n,r,i){this.destination.next(t)},OuterSubscriber.prototype.notifyError=function(e,t){this.destination.error(e)},OuterSubscriber.prototype.notifyComplete=function(e){this.destination.complete()},OuterSubscriber}(i.Subscriber);t.OuterSubscriber=o},function(e,t,n){\"use strict\";function subscribeToResult(e,t,n,u){var p=new c.InnerSubscriber(e,n,u);if(!p.isUnsubscribed){if(t instanceof s.Observable)return t._isScalar?(p.next(t.value),void p.complete()):t.subscribe(p);if(i.isArray(t)){for(var d=0,h=t.length;d=0;a--)(i=e[a])&&(s=(o<3?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){if(\"object\"==typeof Reflect&&\"function\"==typeof Reflect.metadata)return Reflect.metadata(e,t)},o=n(0),s=n(3),a=n(0),l=function(){function Header(){}return Header=r([a.Component({selector:\"header\",template:\"\"}),i(\"design:paramtypes\",[])],Header)}();t.Header=l;var c=function(){function Footer(){}return Footer=r([a.Component({selector:\"footer\",template:\"\"}),i(\"design:paramtypes\",[])],Footer)}();t.Footer=c;var u=function(){function TemplateWrapper(e){this.viewContainer=e}return TemplateWrapper.prototype.ngOnInit=function(){this.viewContainer.createEmbeddedView(this.templateRef,{$implicit:this.item})},r([o.Input(),i(\"design:type\",Object)],TemplateWrapper.prototype,\"item\",void 0),r([o.Input(\"pTemplateWrapper\"),i(\"design:type\",o.TemplateRef)],TemplateWrapper.prototype,\"templateRef\",void 0),TemplateWrapper=r([o.Directive({selector:\"[pTemplateWrapper]\"}),i(\"design:paramtypes\",[o.ViewContainerRef])],TemplateWrapper)}();t.TemplateWrapper=u;var p=function(){function Column(){this.sortFunction=new o.EventEmitter}return r([o.Input(),i(\"design:type\",String)],Column.prototype,\"field\",void 0),r([o.Input(),i(\"design:type\",String)],Column.prototype,\"header\",void 0),r([o.Input(),i(\"design:type\",String)],Column.prototype,\"footer\",void 0),r([o.Input(),i(\"design:type\",Object)],Column.prototype,\"sortable\",void 0),r([o.Input(),i(\"design:type\",Boolean)],Column.prototype,\"editable\",void 0),r([o.Input(),i(\"design:type\",Boolean)],Column.prototype,\"filter\",void 0),r([o.Input(),i(\"design:type\",String)],Column.prototype,\"filterMatchMode\",void 0),r([o.Input(),i(\"design:type\",Number)],Column.prototype,\"rowspan\",void 0),r([o.Input(),i(\"design:type\",Number)],Column.prototype,\"colspan\",void 0),r([o.Input(),i(\"design:type\",Object)],Column.prototype,\"style\",void 0),r([o.Input(),i(\"design:type\",String)],Column.prototype,\"styleClass\",void 0),r([o.Input(),i(\"design:type\",Boolean)],Column.prototype,\"hidden\",void 0),r([o.Input(),i(\"design:type\",Boolean)],Column.prototype,\"expander\",void 0),r([o.Input(),i(\"design:type\",String)],Column.prototype,\"selectionMode\",void 0),r([o.Output(),i(\"design:type\",o.EventEmitter)],Column.prototype,\"sortFunction\",void 0),r([o.ContentChild(o.TemplateRef),i(\"design:type\",o.TemplateRef)],Column.prototype,\"template\",void 0),Column=r([a.Component({selector:\"p-column\",template:\"\"}),i(\"design:paramtypes\",[])],Column)}();t.Column=p;var d=function(){function ColumnTemplateLoader(e){this.viewContainer=e}return ColumnTemplateLoader.prototype.ngOnInit=function(){this.viewContainer.createEmbeddedView(this.column.template,{$implicit:this.column,rowData:this.rowData,rowIndex:this.rowIndex})},r([o.Input(),i(\"design:type\",Object)],ColumnTemplateLoader.prototype,\"column\",void 0),r([o.Input(),i(\"design:type\",Object)],ColumnTemplateLoader.prototype,\"rowData\",void 0),r([o.Input(),i(\"design:type\",Number)],ColumnTemplateLoader.prototype,\"rowIndex\",void 0),ColumnTemplateLoader=r([a.Component({selector:\"p-columnTemplateLoader\",template:\"\"}),i(\"design:paramtypes\",[o.ViewContainerRef])],ColumnTemplateLoader)}();t.ColumnTemplateLoader=d;var h=function(){function SharedModule(){}return SharedModule=r([o.NgModule({imports:[s.CommonModule],exports:[l,c,p,u,d],declarations:[l,c,p,u,d]}),i(\"design:paramtypes\",[])],SharedModule)}();t.SharedModule=h},function(e,t,n){\"use strict\";var r=this&&this.__extends||function(e,t){function __(){this.constructor=e}for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);e.prototype=null===t?Object.create(t):(__.prototype=t.prototype,new __)},i=n(1),o=n(6),s=n(41),a=n(899),l=n(215),c=n(517),u=n(317),p=function(e){function Subject(t,n){e.call(this),this.destination=t,this.source=n,this.observers=[],this.isUnsubscribed=!1,this.isStopped=!1,this.hasErrored=!1,this.dispatching=!1,this.hasCompleted=!1,this.source=n}return r(Subject,e),Subject.prototype.lift=function(e){var t=new Subject(this.destination||this,this);return t.operator=e,t},Subject.prototype.add=function(e){return s.Subscription.prototype.add.call(this,e)},Subject.prototype.remove=function(e){s.Subscription.prototype.remove.call(this,e)},Subject.prototype.unsubscribe=function(){s.Subscription.prototype.unsubscribe.call(this)},Subject.prototype._subscribe=function(e){if(this.source)return this.source.subscribe(e);if(!e.isUnsubscribed){if(this.hasErrored)return e.error(this.errorValue);if(this.hasCompleted)return e.complete();this.throwIfUnsubscribed();var t=new a.SubjectSubscription(this,e);return this.observers.push(e),t}},Subject.prototype._unsubscribe=function(){this.source=null,this.isStopped=!0,this.observers=null,this.destination=null},Subject.prototype.next=function(e){this.throwIfUnsubscribed(),this.isStopped||(this.dispatching=!0,this._next(e),this.dispatching=!1,this.hasErrored?this._error(this.errorValue):this.hasCompleted&&this._complete())},Subject.prototype.error=function(e){this.throwIfUnsubscribed(),this.isStopped||(this.isStopped=!0,this.hasErrored=!0,this.errorValue=e,this.dispatching||this._error(e))},Subject.prototype.complete=function(){this.throwIfUnsubscribed(),this.isStopped||(this.isStopped=!0,this.hasCompleted=!0,this.dispatching||this._complete())},Subject.prototype.asObservable=function(){var e=new d(this);return e},Subject.prototype._next=function(e){this.destination?this.destination.next(e):this._finalNext(e)},Subject.prototype._finalNext=function(e){for(var t=-1,n=this.observers.slice(0),r=n.length;++t\"+i+\"\"};e.exports=function(e,t){var n={};n[e]=t(a),r(r.P+r.F*i(function(){var t=\"\"[e]('\"');return t!==t.toLowerCase()||t.split('\"').length>3}),\"String\",n)}},function(e,t,n){\"use strict\";var r=n(81),i=n(514),o=n(217),s=n(42),a=n(38),l=n(513),c=function(){function Subscription(e){this.isUnsubscribed=!1,e&&(this._unsubscribe=e)}return Subscription.prototype.unsubscribe=function(){var e,t=!1;if(!this.isUnsubscribed){this.isUnsubscribed=!0;var n=this,c=n._unsubscribe,u=n._subscriptions;if(this._subscriptions=null,o.isFunction(c)){var p=s.tryCatch(c).call(this);p===a.errorObject&&(t=!0,(e=e||[]).push(a.errorObject.e))}if(r.isArray(u))for(var d=-1,h=u.length;++d0?i(r(e),9007199254740991):0}},function(e,t,n){\"use strict\";var r=n(1082);t.async=new r.AsyncScheduler},function(e,t,n){\"use strict\";function __export(e){for(var n in e)t.hasOwnProperty(n)||(t[n]=e[n])}var r=n(86);t.HostMetadata=r.HostMetadata,t.InjectMetadata=r.InjectMetadata,t.InjectableMetadata=r.InjectableMetadata,t.OptionalMetadata=r.OptionalMetadata,t.SelfMetadata=r.SelfMetadata,t.SkipSelfMetadata=r.SkipSelfMetadata,__export(n(115));var i=n(162);t.forwardRef=i.forwardRef,t.resolveForwardRef=i.resolveForwardRef;var o=n(163);t.Injector=o.Injector;var s=n(571);t.ReflectiveInjector=s.ReflectiveInjector;var a=n(250);t.Binding=a.Binding,t.ProviderBuilder=a.ProviderBuilder,t.bind=a.bind,t.Provider=a.Provider,t.provide=a.provide;var l=n(253);t.ResolvedReflectiveFactory=l.ResolvedReflectiveFactory;var c=n(252);t.ReflectiveKey=c.ReflectiveKey;var u=n(251);t.NoProviderError=u.NoProviderError,t.AbstractProviderError=u.AbstractProviderError,t.CyclicDependencyError=u.CyclicDependencyError,t.InstantiationError=u.InstantiationError,t.InvalidProviderError=u.InvalidProviderError,t.NoAnnotationError=u.NoAnnotationError,t.OutOfBoundsError=u.OutOfBoundsError;var p=n(374);t.OpaqueToken=p.OpaqueToken},[1104,32],function(e,t){var n={}.hasOwnProperty;e.exports=function(e,t){return n.call(e,t)}},function(e,t,n){\"use strict\";var r=n(13);e.exports=function(e,t){return!!e&&r(function(){t?e.call(null,function(){},1):e.call(null)})}},function(e,t,n){var r=n(75);e.exports=function(e){return Object(r(e))}},function(e,t,n){\"use strict\";(function(e,n){var r={\"boolean\":!1,\"function\":!0,object:!0,number:!1,string:!1,undefined:!1};t.root=r[typeof self]&&self||r[typeof window]&&window;var i=(r[typeof t]&&t&&!t.nodeType&&t,r[typeof e]&&e&&!e.nodeType&&e,r[typeof n]&&n);!i||i.global!==i&&i.window!==i||(t.root=i)}).call(t,n(1100)(e),n(82))},function(e,t,n){\"use strict\";var r=n(0);t.NG_VALUE_ACCESSOR=new r.OpaqueToken(\"NgValueAccessor\")},52,function(e,t,n){\"use strict\";function _convertToPromise(e){return s.isPromise(e)?e:i.toPromise.call(e)}function _executeValidators(e,t){return t.map(function(t){return t(e)})}function _executeAsyncValidators(e,t){return t.map(function(t){return t(e)})}function _mergeErrors(e){var t=e.reduce(function(e,t){return s.isPresent(t)?o.StringMapWrapper.merge(e,t):e},{});return o.StringMapWrapper.isEmpty(t)?null:t}var r=n(0),i=n(313),o=n(47),s=n(32);t.NG_VALIDATORS=new r.OpaqueToken(\"NgValidators\"),t.NG_ASYNC_VALIDATORS=new r.OpaqueToken(\"NgAsyncValidators\");var a=function(){function Validators(){}return Validators.required=function(e){return s.isBlank(e.value)||s.isString(e.value)&&\"\"==e.value?{required:!0}:null},Validators.minLength=function(e){return function(t){if(s.isPresent(Validators.required(t)))return null;var n=t.value;return n.lengthe?{maxlength:{requiredLength:e,actualLength:n.length}}:null}},Validators.pattern=function(e){return function(t){if(s.isPresent(Validators.required(t)))return null;var n=new RegExp(\"^\"+e+\"$\"),r=t.value;return n.test(r)?null:{pattern:{requiredPattern:\"^\"+e+\"$\",actualValue:r}}}},Validators.nullValidator=function(e){return null},Validators.compose=function(e){if(s.isBlank(e))return null;var t=e.filter(s.isPresent);return 0==t.length?null:function(e){return _mergeErrors(_executeValidators(e,t))}},Validators.composeAsync=function(e){if(s.isBlank(e))return null;var t=e.filter(s.isPresent);return 0==t.length?null:function(e){var n=_executeAsyncValidators(e,t).map(_convertToPromise);return Promise.all(n).then(_mergeErrors)}},Validators}();t.Validators=a},function(e,t,n){\"use strict\";var r=n(0),i=n(123),o=n(72),s=n(16),a=n(126),l=n(278);t.PRIMITIVE=String;var c=function(){function Serializer(e){this._renderStore=e}return Serializer.prototype.serialize=function(e,n){var i=this;if(!s.isPresent(e))return null;if(s.isArray(e))return e.map(function(e){return i.serialize(e,n)});if(n==t.PRIMITIVE)return e;if(n==u)return this._renderStore.serialize(e);if(n===r.RenderComponentType)return this._serializeRenderComponentType(e);if(n===r.ViewEncapsulation)return s.serializeEnum(e);if(n===l.LocationType)return this._serializeLocation(e);throw new o.BaseException(\"No serializer for \"+n.toString())},Serializer.prototype.deserialize=function(e,n,a){var c=this;if(!s.isPresent(e))return null;if(s.isArray(e)){var p=[];return e.forEach(function(e){return p.push(c.deserialize(e,n,a))}),p}if(n==t.PRIMITIVE)return e;if(n==u)return this._renderStore.deserialize(e);if(n===r.RenderComponentType)return this._deserializeRenderComponentType(e);if(n===r.ViewEncapsulation)return i.VIEW_ENCAPSULATION_VALUES[e];if(n===l.LocationType)return this._deserializeLocation(e);throw new o.BaseException(\"No deserializer for \"+n.toString())},Serializer.prototype._serializeLocation=function(e){return{href:e.href,protocol:e.protocol,host:e.host,hostname:e.hostname,port:e.port,pathname:e.pathname,search:e.search,hash:e.hash,origin:e.origin}},Serializer.prototype._deserializeLocation=function(e){return new l.LocationType(e.href,e.protocol,e.host,e.hostname,e.port,e.pathname,e.search,e.hash,e.origin)},Serializer.prototype._serializeRenderComponentType=function(e){return{id:e.id,templateUrl:e.templateUrl,slotCount:e.slotCount,encapsulation:this.serialize(e.encapsulation,r.ViewEncapsulation),styles:this.serialize(e.styles,t.PRIMITIVE)}},Serializer.prototype._deserializeRenderComponentType=function(e){return new r.RenderComponentType(e.id,e.templateUrl,e.slotCount,this.deserialize(e.encapsulation,r.ViewEncapsulation),this.deserialize(e.styles,t.PRIMITIVE),{})},Serializer.decorators=[{type:r.Injectable}],Serializer.ctorParameters=[{type:a.RenderStore}],Serializer}();t.Serializer=c;var u=function(){function RenderStoreObject(){}return RenderStoreObject}();t.RenderStoreObject=u},function(e,t,n){var r=n(2),i=n(24),o=n(13);e.exports=function(e,t){var n=(i.Object||{})[e]||Object[e],s={};s[e]=t(n),r(r.S+r.F*o(function(){n(1)}),\"Object\",s)}},function(e,t,n){var r=n(133),i=n(75);e.exports=function(e){return r(i(e))}},function(e,t,n){\"use strict\";function _convertToPromise(e){return s.isPromise(e)?e:i.toPromise.call(e)}function _executeValidators(e,t){return t.map(function(t){return t(e)})}function _executeAsyncValidators(e,t){return t.map(function(t){return t(e)})}function _mergeErrors(e){var t=e.reduce(function(e,t){return s.isPresent(t)?o.StringMapWrapper.merge(e,t):e},{});return o.StringMapWrapper.isEmpty(t)?null:t}var r=n(0),i=n(313),o=n(34),s=n(7);t.NG_VALIDATORS=new r.OpaqueToken(\"NgValidators\"),t.NG_ASYNC_VALIDATORS=new r.OpaqueToken(\"NgAsyncValidators\");var a=function(){function Validators(){}return Validators.required=function(e){return s.isBlank(e.value)||s.isString(e.value)&&\"\"==e.value?{required:!0}:null},Validators.minLength=function(e){return function(t){if(s.isPresent(Validators.required(t)))return null;var n=t.value;return n.lengthe?{maxlength:{requiredLength:e,actualLength:n.length}}:null}},Validators.pattern=function(e){return function(t){if(s.isPresent(Validators.required(t)))return null;var n=new RegExp(\"^\"+e+\"$\"),r=t.value;return n.test(r)?null:{pattern:{requiredPattern:\"^\"+e+\"$\",actualValue:r}}}},Validators.nullValidator=function(e){return null},Validators.compose=function(e){if(s.isBlank(e))return null;var t=e.filter(s.isPresent);return 0==t.length?null:function(e){return _mergeErrors(_executeValidators(e,t))}},Validators.composeAsync=function(e){if(s.isBlank(e))return null;var t=e.filter(s.isPresent);return 0==t.length?null:function(e){var n=_executeAsyncValidators(e,t).map(_convertToPromise);return Promise.all(n).then(_mergeErrors)}},Validators}();t.Validators=a},function(e,t,n){\"use strict\";var r=this&&this.__extends||function(e,t){function __(){this.constructor=e}for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);e.prototype=null===t?Object.create(t):(__.prototype=t.prototype,new __)},i=n(83),o=n(7),s=function(e){function InvalidPipeArgumentException(t,n){e.call(this,\"Invalid argument '\"+n+\"' for pipe '\"+o.stringify(t)+\"'\")}return r(InvalidPipeArgumentException,e),InvalidPipeArgumentException}(i.BaseException);t.InvalidPipeArgumentException=s},function(e,t,n){\"use strict\";/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nvar r=n(5),i=function(){function ParseLocation(e,t,n,r){this.file=e,this.offset=t,this.line=n,this.col=r}return ParseLocation.prototype.toString=function(){return r.isPresent(this.offset)?this.file.url+\"@\"+this.line+\":\"+this.col:this.file.url},ParseLocation}();t.ParseLocation=i;var o=function(){function ParseSourceFile(e,t){this.content=e,this.url=t}return ParseSourceFile}();t.ParseSourceFile=o;var s=function(){function ParseSourceSpan(e,t,n){void 0===n&&(n=null),this.start=e,this.end=t,this.details=n}return ParseSourceSpan.prototype.toString=function(){return this.start.file.content.substring(this.start.offset,this.end.offset)},ParseSourceSpan}();t.ParseSourceSpan=s,function(e){e[e.WARNING=0]=\"WARNING\",e[e.FATAL=1]=\"FATAL\"}(t.ParseErrorLevel||(t.ParseErrorLevel={}));var a=t.ParseErrorLevel,l=function(){function ParseError(e,t,n){void 0===n&&(n=a.FATAL),this.span=e,this.msg=t,this.level=n}return ParseError.prototype.toString=function(){var e=this.span.start.file.content,t=this.span.start.offset,n=\"\",i=\"\";if(r.isPresent(t)){t>e.length-1&&(t=e.length-1);for(var o=t,s=0,a=0;s<100&&t>0&&(t--,s++,\"\\n\"!=e[t]||3!=++a););for(s=0,a=0;s<100&&o]\"+e.substring(this.span.start.offset,o+1);n=' (\"'+l+'\")'}return this.span.details&&(i=\", \"+this.span.details),\"\"+this.msg+n+\": \"+this.span.start+i},ParseError}();t.ParseError=l},function(e,t,n){\"use strict\";function templateVisitAll(e,t,n){void 0===n&&(n=null);var i=[];return t.forEach(function(t){var o=t.visit(e,n);r.isPresent(o)&&i.push(o)}),i}var r=n(5),i=function(){function TextAst(e,t,n){this.value=e,this.ngContentIndex=t,this.sourceSpan=n}return TextAst.prototype.visit=function(e,t){return e.visitText(this,t)},TextAst}();t.TextAst=i;var o=function(){function BoundTextAst(e,t,n){this.value=e,this.ngContentIndex=t,this.sourceSpan=n}return BoundTextAst.prototype.visit=function(e,t){return e.visitBoundText(this,t)},BoundTextAst}();t.BoundTextAst=o;var s=function(){function AttrAst(e,t,n){this.name=e,this.value=t,this.sourceSpan=n}return AttrAst.prototype.visit=function(e,t){return e.visitAttr(this,t)},AttrAst}();t.AttrAst=s;var a=function(){function BoundElementPropertyAst(e,t,n,r,i,o){this.name=e,this.type=t,this.securityContext=n,this.value=r,this.unit=i,this.sourceSpan=o}return BoundElementPropertyAst.prototype.visit=function(e,t){return e.visitElementProperty(this,t)},BoundElementPropertyAst}();t.BoundElementPropertyAst=a;var l=function(){function BoundEventAst(e,t,n,r){this.name=e,this.target=t,this.handler=n,this.sourceSpan=r}return BoundEventAst.prototype.visit=function(e,t){return e.visitEvent(this,t)},Object.defineProperty(BoundEventAst.prototype,\"fullName\",{get:function(){return r.isPresent(this.target)?this.target+\":\"+this.name:this.name},enumerable:!0,configurable:!0}),BoundEventAst}();t.BoundEventAst=l;var c=function(){function ReferenceAst(e,t,n){this.name=e,this.value=t,this.sourceSpan=n}return ReferenceAst.prototype.visit=function(e,t){return e.visitReference(this,t)},ReferenceAst}();t.ReferenceAst=c;var u=function(){function VariableAst(e,t,n){this.name=e,this.value=t,this.sourceSpan=n}return VariableAst.prototype.visit=function(e,t){return e.visitVariable(this,t)},VariableAst}();t.VariableAst=u;var p=function(){function ElementAst(e,t,n,r,i,o,s,a,l,c,u){this.name=e,this.attrs=t,this.inputs=n,this.outputs=r,this.references=i,this.directives=o,this.providers=s,this.hasViewContainer=a,this.children=l,this.ngContentIndex=c,this.sourceSpan=u}return ElementAst.prototype.visit=function(e,t){return e.visitElement(this,t)},ElementAst}();t.ElementAst=p;var d=function(){function EmbeddedTemplateAst(e,t,n,r,i,o,s,a,l,c){this.attrs=e,this.outputs=t,this.references=n,this.variables=r,this.directives=i,this.providers=o,this.hasViewContainer=s,this.children=a,this.ngContentIndex=l,this.sourceSpan=c}return EmbeddedTemplateAst.prototype.visit=function(e,t){return e.visitEmbeddedTemplate(this,t)},EmbeddedTemplateAst}();t.EmbeddedTemplateAst=d;var h=function(){function BoundDirectivePropertyAst(e,t,n,r){this.directiveName=e,this.templateName=t,this.value=n,this.sourceSpan=r}return BoundDirectivePropertyAst.prototype.visit=function(e,t){return e.visitDirectiveProperty(this,t)},BoundDirectivePropertyAst}();t.BoundDirectivePropertyAst=h;var f=function(){function DirectiveAst(e,t,n,r,i){this.directive=e,this.inputs=t,this.hostProperties=n,this.hostEvents=r,this.sourceSpan=i}return DirectiveAst.prototype.visit=function(e,t){return e.visitDirective(this,t)},DirectiveAst}();t.DirectiveAst=f;var m=function(){function ProviderAst(e,t,n,r,i,o,s){this.token=e,this.multiProvider=t,this.eager=n,this.providers=r,this.providerType=i,this.lifecycleHooks=o,this.sourceSpan=s}return ProviderAst.prototype.visit=function(e,t){return null},ProviderAst}();t.ProviderAst=m,function(e){e[e.PublicService=0]=\"PublicService\",e[e.PrivateService=1]=\"PrivateService\",e[e.Component=2]=\"Component\",e[e.Directive=3]=\"Directive\",e[e.Builtin=4]=\"Builtin\"}(t.ProviderAstType||(t.ProviderAstType={}));var g=(t.ProviderAstType,function(){function NgContentAst(e,t,n){this.index=e,this.ngContentIndex=t,this.sourceSpan=n}return NgContentAst.prototype.visit=function(e,t){return e.visitNgContent(this,t)},NgContentAst}());t.NgContentAst=g,function(e){e[e.Property=0]=\"Property\",e[e.Attribute=1]=\"Attribute\",e[e.Class=2]=\"Class\",e[e.Style=3]=\"Style\",e[e.Animation=4]=\"Animation\"}(t.PropertyBindingType||(t.PropertyBindingType={}));t.PropertyBindingType;t.templateVisitAll=templateVisitAll},function(e,t){\"use strict\";var n=function(){function MessageBus(){}return MessageBus}();t.MessageBus=n},function(e,t){\"use strict\";t.PRIMARY_OUTLET=\"primary\"},function(e,t,n){var r=n(106),i=n(133),o=n(50),s=n(44),a=n(676);e.exports=function(e,t){var n=1==e,l=2==e,c=3==e,u=4==e,p=6==e,d=5==e||p,h=t||a;return function(t,a,f){for(var m,g,y=o(t),v=i(y),b=r(a,f,3),_=s(v.length),w=0,S=n?h(t,_):l?h(t,0):void 0;_>w;w++)if((d||w in v)&&(m=v[w],g=b(m,w,y),e))if(n)S[w]=g;else if(g)switch(e){case 3:return!0;case 5:return m;case 6:return w;case 2:S.push(m)}else if(u)return!1;return p?-1:c||u?u:S}}},function(e,t,n){var r=n(30),i=n(109);e.exports=n(35)?function(e,t,n){return r.f(e,t,i(1,n))}:function(e,t,n){return e[t]=n,e}},function(e,t,n){var r=n(472),i=n(2),o=n(199)(\"metadata\"),s=o.store||(o.store=new(n(798))),a=function(e,t,n){var i=s.get(e);if(!i){if(!n)return;s.set(e,i=new r)}var o=i.get(t);if(!o){if(!n)return;i.set(t,o=new r)}return o},l=function(e,t,n){var r=a(t,n,!1);return void 0!==r&&r.has(e)},c=function(e,t,n){var r=a(t,n,!1);return void 0===r?void 0:r.get(e)},u=function(e,t,n,r){a(n,r,!0).set(e,t)},p=function(e,t){var n=a(e,t,!1),r=[];return n&&n.forEach(function(e,t){r.push(t)}),r},d=function(e){return void 0===e||\"symbol\"==typeof e?e:String(e)},h=function(e){i(i.S,\"Reflect\",e)};e.exports={store:s,map:a,has:l,get:c,set:u,keys:p,key:d,exp:h}},function(e,t,n){var r=n(48),i=n(50),o=n(300)(\"IE_PROTO\"),s=Object.prototype;e.exports=Object.getPrototypeOf||function(e){return e=i(e),r(e,o)?e[o]:\"function\"==typeof e.constructor&&e instanceof e.constructor?e.constructor.prototype:e instanceof Object?s:null}},function(e,t,n){\"use strict\";var r=n(347),i=function(){function InterpolationConfig(e,t){this.start=e,this.end=t}return InterpolationConfig.fromArray=function(e){return e?(r.assertInterpolationSymbols(\"interpolation\",e),new InterpolationConfig(e[0],e[1])):t.DEFAULT_INTERPOLATION_CONFIG},InterpolationConfig}();t.InterpolationConfig=i,t.DEFAULT_INTERPOLATION_CONFIG=new i(\"{{\",\"}}\")},[1107,263],function(e,t,n){\"use strict\";function controlPath(e,t){var n=r.ListWrapper.clone(t.path);return n.push(e),n}function setUpControl(e,t){o.isBlank(e)&&_throwError(t,\"Cannot find control with\"),o.isBlank(t.valueAccessor)&&_throwError(t,\"No value accessor for form control with\"),e.validator=s.Validators.compose([e.validator,t.validator]),e.asyncValidator=s.Validators.composeAsync([e.asyncValidator,t.asyncValidator]),t.valueAccessor.writeValue(e.value),t.valueAccessor.registerOnChange(function(n){t.viewToModelUpdate(n),e.markAsDirty(),e.setValue(n,{emitModelToViewChange:!1})}),e.registerOnChange(function(e,n){t.valueAccessor.writeValue(e),n&&t.viewToModelUpdate(e)}),t.valueAccessor.registerOnTouched(function(){return e.markAsTouched()})}function setUpFormContainer(e,t){o.isBlank(e)&&_throwError(t,\"Cannot find control with\"),e.validator=s.Validators.compose([e.validator,t.validator]),e.asyncValidator=s.Validators.composeAsync([e.asyncValidator,t.asyncValidator])}function _throwError(e,t){var n;throw n=e.path.length>1?\"path: '\"+e.path.join(\" -> \")+\"'\":e.path[0]?\"name: '\"+e.path+\"'\":\"unspecified name attribute\",new i.BaseException(t+\" \"+n)}function composeValidators(e){return o.isPresent(e)?s.Validators.compose(e.map(c.normalizeValidator)):null}function composeAsyncValidators(e){return o.isPresent(e)?s.Validators.composeAsync(e.map(c.normalizeAsyncValidator)):null}function isPropertyUpdated(e,t){if(!r.StringMapWrapper.contains(e,\"model\"))return!1;var n=e.model;return!!n.isFirstChange()||!o.looseIdentical(t,n.currentValue)}function selectValueAccessor(e,t){if(o.isBlank(t))return null;var n,r,i;return t.forEach(function(t){o.hasConstructor(t,l.DefaultValueAccessor)?n=t:o.hasConstructor(t,a.CheckboxControlValueAccessor)||o.hasConstructor(t,u.NumberValueAccessor)||o.hasConstructor(t,d.SelectControlValueAccessor)||o.hasConstructor(t,h.SelectMultipleControlValueAccessor)||o.hasConstructor(t,p.RadioControlValueAccessor)?(o.isPresent(r)&&_throwError(e,\"More than one built-in value accessor matches form control with\"),r=t):(o.isPresent(i)&&_throwError(e,\"More than one custom value accessor matches form control with\"),i=t)}),o.isPresent(i)?i:o.isPresent(r)?r:o.isPresent(n)?n:(_throwError(e,\"No valid value accessor for form control with\"),null)}var r=n(47),i=n(88),o=n(32),s=n(54),a=n(169),l=n(170),c=n(587),u=n(266),p=n(172),d=n(173),h=n(174);t.controlPath=controlPath,t.setUpControl=setUpControl,t.setUpFormContainer=setUpFormContainer,t.composeValidators=composeValidators,t.composeAsyncValidators=composeAsyncValidators,t.isPropertyUpdated=isPropertyUpdated,t.selectValueAccessor=selectValueAccessor},function(e,t){\"use strict\";!function(e){e[e.Get=0]=\"Get\",e[e.Post=1]=\"Post\",e[e.Put=2]=\"Put\",e[e.Delete=3]=\"Delete\",e[e.Options=4]=\"Options\",e[e.Head=5]=\"Head\",e[e.Patch=6]=\"Patch\"}(t.RequestMethod||(t.RequestMethod={}));t.RequestMethod;!function(e){e[e.Unsent=0]=\"Unsent\",e[e.Open=1]=\"Open\",e[e.HeadersReceived=2]=\"HeadersReceived\",e[e.Loading=3]=\"Loading\",e[e.Done=4]=\"Done\",e[e.Cancelled=5]=\"Cancelled\"}(t.ReadyState||(t.ReadyState={}));t.ReadyState;!function(e){e[e.Basic=0]=\"Basic\",e[e.Cors=1]=\"Cors\",e[e.Default=2]=\"Default\",e[e.Error=3]=\"Error\",e[e.Opaque=4]=\"Opaque\"}(t.ResponseType||(t.ResponseType={}));t.ResponseType;!function(e){e[e.NONE=0]=\"NONE\",e[e.JSON=1]=\"JSON\",e[e.FORM=2]=\"FORM\",e[e.FORM_DATA=3]=\"FORM_DATA\",e[e.TEXT=4]=\"TEXT\",e[e.BLOB=5]=\"BLOB\",e[e.ARRAY_BUFFER=6]=\"ARRAY_BUFFER\"}(t.ContentType||(t.ContentType={}));t.ContentType;!function(e){e[e.Text=0]=\"Text\",e[e.Json=1]=\"Json\",e[e.ArrayBuffer=2]=\"ArrayBuffer\",e[e.Blob=3]=\"Blob\"}(t.ResponseContentType||(t.ResponseContentType={}));t.ResponseContentType},[1106,418,419,419],function(e,t,n){\"use strict\";function createEmptyUrlTree(){return new o(new s([],{}),{},null)}function containsTree(e,t,n){return n?equalSegmentGroups(e.root,t.root):containsSegmentGroup(e.root,t.root)}function equalSegmentGroups(e,t){if(!equalPath(e.segments,t.segments))return!1;if(e.numberOfChildren!==t.numberOfChildren)return!1;for(var n in t.children){if(!e.children[n])return!1;if(!equalSegmentGroups(e.children[n],t.children[n]))return!1}return!0}function containsSegmentGroup(e,t){return containsSegmentGroupHelper(e,t,t.segments)}function containsSegmentGroupHelper(e,t,n){if(e.segments.length>n.length){var i=e.segments.slice(0,n.length);return!!equalPath(i,n)&&!t.hasChildren()}if(e.segments.length===n.length){if(!equalPath(e.segments,n))return!1;for(var o in t.children){if(!e.children[o])return!1;if(!containsSegmentGroup(e.children[o],t.children[o]))return!1}return!0}var i=n.slice(0,e.segments.length),s=n.slice(e.segments.length);return!!equalPath(e.segments,i)&&(!!e.children[r.PRIMARY_OUTLET]&&containsSegmentGroupHelper(e.children[r.PRIMARY_OUTLET],t,s))}function equalSegments(e,t){if(e.length!==t.length)return!1;for(var n=0;n0?n+\"(\"+o.join(\"//\")+\")\":\"\"+n}if(e.hasChildren()&&!t){var s=mapChildrenIntoArray(e,function(t,n){return n===r.PRIMARY_OUTLET?[serializeSegment(e.children[r.PRIMARY_OUTLET],!1)]:[n+\":\"+serializeSegment(t,!1)]});return serializePaths(e)+\"/(\"+s.join(\"//\")+\")\"}return serializePaths(e)}function encode(e){return encodeURIComponent(e)}function decode(e){return decodeURIComponent(e)}function serializePath(e){return\"\"+encode(e.path)+serializeParams(e.parameters)}function serializeParams(e){return pairs(e).map(function(e){return\";\"+encode(e.first)+\"=\"+encode(e.second)}).join(\"\")}function serializeQueryParams(e){var t=pairs(e).map(function(e){return encode(e.first)+\"=\"+encode(e.second)});return t.length>0?\"?\"+t.join(\"&\"):\"\"}function pairs(e){var t=[];for(var n in e)e.hasOwnProperty(n)&&t.push(new u(n,e[n]));return t}function matchSegments(e){p.lastIndex=0;var t=e.match(p);return t?t[0]:\"\"}function matchQueryParams(e){d.lastIndex=0;var t=e.match(p);return t?t[0]:\"\"}function matchUrlQueryParamValue(e){h.lastIndex=0;var t=e.match(h);return t?t[0]:\"\"}var r=n(63),i=n(74);t.createEmptyUrlTree=createEmptyUrlTree,t.containsTree=containsTree;var o=function(){function UrlTree(e,t,n){this.root=e,this.queryParams=t,this.fragment=n}return UrlTree.prototype.toString=function(){return(new c).serialize(this)},UrlTree}();t.UrlTree=o;var s=function(){function UrlSegmentGroup(e,t){var n=this;this.segments=e,this.children=t,this.parent=null,i.forEach(t,function(e,t){return e.parent=n})}return UrlSegmentGroup.prototype.hasChildren=function(){return this.numberOfChildren>0},Object.defineProperty(UrlSegmentGroup.prototype,\"numberOfChildren\",{get:function(){return Object.keys(this.children).length},enumerable:!0,configurable:!0}),UrlSegmentGroup.prototype.toString=function(){return serializePaths(this)},UrlSegmentGroup}();t.UrlSegmentGroup=s;var a=function(){function UrlSegment(e,t){this.path=e,this.parameters=t}return UrlSegment.prototype.toString=function(){return serializePath(this)},UrlSegment}();t.UrlSegment=a,t.equalSegments=equalSegments,t.equalPath=equalPath,t.mapChildrenIntoArray=mapChildrenIntoArray;var l=function(){function UrlSerializer(){}return UrlSerializer}();t.UrlSerializer=l;var c=function(){function DefaultUrlSerializer(){}return DefaultUrlSerializer.prototype.parse=function(e){var t=new f(e);return new o(t.parseRootSegment(),t.parseQueryParams(),t.parseFragment())},DefaultUrlSerializer.prototype.serialize=function(e){var t=\"/\"+serializeSegment(e.root,!0),n=serializeQueryParams(e.queryParams),r=null!==e.fragment&&void 0!==e.fragment?\"#\"+encodeURIComponent(e.fragment):\"\";return\"\"+t+n+r},DefaultUrlSerializer}();t.DefaultUrlSerializer=c,t.serializePaths=serializePaths,t.encode=encode,t.decode=decode,t.serializePath=serializePath;var u=function(){function Pair(e,t){this.first=e,this.second=t}return Pair}(),p=/^[^\\/\\(\\)\\?;=&#]+/,d=/^[^=\\?&#]+/,h=/^[^\\?&#]+/,f=function(){function UrlParser(e){this.url=e,this.remaining=e}return UrlParser.prototype.peekStartsWith=function(e){return this.remaining.startsWith(e)},UrlParser.prototype.capture=function(e){if(!this.remaining.startsWith(e))throw new Error('Expected \"'+e+'\".');this.remaining=this.remaining.substring(e.length)},UrlParser.prototype.parseRootSegment=function(){return this.remaining.startsWith(\"/\")&&this.capture(\"/\"),\"\"===this.remaining||this.remaining.startsWith(\"?\")||this.remaining.startsWith(\"#\")?new s([],{}):new s([],this.parseChildren())},UrlParser.prototype.parseChildren=function(){if(0==this.remaining.length)return{};this.peekStartsWith(\"/\")&&this.capture(\"/\");var e=[];for(this.peekStartsWith(\"(\")||e.push(this.parseSegments());this.peekStartsWith(\"/\")&&!this.peekStartsWith(\"//\")&&!this.peekStartsWith(\"/(\");)this.capture(\"/\"),e.push(this.parseSegments());var t={};this.peekStartsWith(\"/(\")&&(this.capture(\"/\"),t=this.parseParens(!0));var n={};return this.peekStartsWith(\"(\")&&(n=this.parseParens(!1)),(e.length>0||Object.keys(t).length>0)&&(n[r.PRIMARY_OUTLET]=new s(e,t)),n},UrlParser.prototype.parseSegments=function(){var e=matchSegments(this.remaining);if(\"\"===e&&this.peekStartsWith(\";\"))throw new Error(\"Empty path url segment cannot have parameters: '\"+this.remaining+\"'.\");this.capture(e);var t={};return this.peekStartsWith(\";\")&&(t=this.parseMatrixParams()),new a(decode(e),t)},UrlParser.prototype.parseQueryParams=function(){var e={};if(this.peekStartsWith(\"?\"))for(this.capture(\"?\"),this.parseQueryParam(e);this.remaining.length>0&&this.peekStartsWith(\"&\");)this.capture(\"&\"),this.parseQueryParam(e);return e},UrlParser.prototype.parseFragment=function(){return this.peekStartsWith(\"#\")?decode(this.remaining.substring(1)):null},UrlParser.prototype.parseMatrixParams=function(){for(var e={};this.remaining.length>0&&this.peekStartsWith(\";\");)this.capture(\";\"),this.parseParam(e);return e},UrlParser.prototype.parseParam=function(e){var t=matchSegments(this.remaining);if(t){this.capture(t);var n=\"true\";if(this.peekStartsWith(\"=\")){this.capture(\"=\");var r=matchSegments(this.remaining);r&&(n=r,this.capture(n))}e[decode(t)]=decode(n)}},UrlParser.prototype.parseQueryParam=function(e){var t=matchQueryParams(this.remaining);if(t){this.capture(t);var n=\"\";if(this.peekStartsWith(\"=\")){this.capture(\"=\");var r=matchUrlQueryParamValue(this.remaining);r&&(n=r,this.capture(n))}e[decode(t)]=decode(n)}},UrlParser.prototype.parseParens=function(e){var t={};for(this.capture(\"(\");!this.peekStartsWith(\")\")&&this.remaining.length>0;){var n=matchSegments(this.remaining),i=this.remaining[n.length];if(\"/\"!==i&&\")\"!==i&&\";\"!==i)throw new Error(\"Cannot parse url '\"+this.url+\"'\");var o=void 0;n.indexOf(\":\")>-1?(o=n.substr(0,n.indexOf(\":\")),this.capture(o),this.capture(\":\")):e&&(o=r.PRIMARY_OUTLET);var a=this.parseChildren();t[o]=1===Object.keys(a).length?a[r.PRIMARY_OUTLET]:new s([],a),this.peekStartsWith(\"//\")&&this.capture(\"//\")}return this.capture(\")\"),t},UrlParser}()},function(e,t,n){\"use strict\";function shallowEqualArrays(e,t){if(e.length!==t.length)return!1;for(var n=0;n0?e[0]:null}function last(e){return e.length>0?e[e.length-1]:null}function and(e){return e.reduce(function(e,t){return e&&t},!0)}function merge(e,t){var n={};for(var r in e)e.hasOwnProperty(r)&&(n[r]=e[r]);for(var r in t)t.hasOwnProperty(r)&&(n[r]=t[r]);return n}function forEach(e,t){for(var n in e)e.hasOwnProperty(n)&&t(e[n],n)}function waitForMap(e,t){var n=[],r={};return forEach(e,function(e,i){i===s.PRIMARY_OUTLET&&n.push(t(i,e).map(function(e){return r[i]=e,e}))}),forEach(e,function(e,i){i!==s.PRIMARY_OUTLET&&n.push(t(i,e).map(function(e){return r[i]=e,e}))}),n.length>0?o.of.apply(void 0,n).concatAll().last().map(function(e){return r}):o.of(r)}function andObservables(e){return e.mergeAll().every(function(e){return e===!0})}function wrapIntoObservable(e){return e instanceof r.Observable?e:e instanceof Promise?i.fromPromise(e):o.of(e)}n(304),n(497);var r=n(1),i=n(211),o=n(141),s=n(63);t.shallowEqualArrays=shallowEqualArrays,t.shallowEqual=shallowEqual,t.flatten=flatten,t.first=first,t.last=last,t.and=and,t.merge=merge,t.forEach=forEach,t.waitForMap=waitForMap,t.andObservables=andObservables,t.wrapIntoObservable=wrapIntoObservable},function(e,t){e.exports=function(e){if(void 0==e)throw TypeError(\"Can't call method on \"+e);return e}},function(e,t,n){var r=n(137)(\"meta\"),i=n(15),o=n(48),s=n(30).f,a=0,l=Object.isExtensible||function(){return!0},c=!n(13)(function(){return l(Object.preventExtensions({}))}),u=function(e){s(e,r,{value:{i:\"O\"+ ++a,w:{}}})},p=function(e,t){if(!i(e))return\"symbol\"==typeof e?e:(\"string\"==typeof e?\"S\":\"P\")+e;if(!o(e,r)){if(!l(e))return\"F\";if(!t)return\"E\";u(e)}return e[r].i},d=function(e,t){if(!o(e,r)){if(!l(e))return!0;if(!t)return!1;u(e)}return e[r].w},h=function(e){return c&&f.NEED&&l(e)&&!o(e,r)&&u(e),e},f=e.exports={KEY:r,NEED:!1,fastKey:p,getWeak:d,onFreeze:h}},function(e,t,n){var r=n(197),i=n(109),o=n(57),s=n(97),a=n(48),l=n(453),c=Object.getOwnPropertyDescriptor;t.f=n(35)?c:function(e,t){if(e=o(e),t=s(t,!0),l)try{return c(e,t)}catch(n){}if(a(e,t))return i(!r.f.call(e,t),e[t])}},function(e,t){e.exports=\".vt-row {\\n display: flex;\\n flex-wrap: wrap;\\n height: 100%;\\n width: 100%;\\n}\\n\\n.vt-card {\\n display: inline-table;\\n margin-left: 25px;\\n margin-bottom: 10px;\\n margin-top: 10px;\\n}\\n\\n.stats-container {\\n width: 100%;\\n}\\n\\n.vt-padding{\\n padding-left: 25px;\\n padding-right: 25px;\\n}\\n\\n>>> p-dialog .ui-dialog{\\n position: fixed !important;\\n top: 50% !important;\\n left: 50% !important;\\n transform: translate(-50%, -50%);\\n margin: 0;\\n width: auto !important;\\n}\\n\\n.vt-popUpContainer{\\n position: fixed;\\n padding: 0;\\n margin: 0;\\n z-index: 0;\\n bottom: 0;\\n right: 0;\\n top: 0;\\n left: 0;\\n min-height: 1000vh;\\n min-width: 1000vw;\\n height: 100%;\\n width: 100%;\\n background: rgba(0,0,0,0.6);\\n}\\n\\n.vt-dark-link:link {\\n text-decoration: none;\\n color: black;\\n}\\n\\n.vt-dark-link:visited {\\n text-decoration: none;\\n color: black;\\n}\\n\\n.vt-dark-link:hover {\\n text-decoration: none;\\n color: black;\\n}\\n\\n.vt-dark-link:active {\\n text-decoration: none;\\n color: black;\\n}\\n\\n/* Toolbar */\\n.vt-toolbar {\\n width: 100%;\\n text-align: center;\\n}\\n\\n>>> p-accordiontab a {\\n padding-left: 25px! important;\\n}\\n\\n>>> .ui-accordion-content button {\\n margin-top: 2px;\\n}\\n\\n>>> p-menu .ui-menu {\\n margin-top: 19px;\\n display: inline-block;\\n top: auto !important;\\n left: auto !important;\\n float: right;\\n \\n}\\n\\np-menu {\\n display: inline-block;\\n float: left;\\n}\\n\\n.vt-toolbar .vt-menu {\\n padding-top: 19px;\\n float: left;\\n}\\n\\n.vt-toolbar .vt-right-menu {\\n padding-top: 19px;\\n position: fixed;\\n right: 25px;\\n top: 19px;\\n}\\n\\n.vt-card-toolbar {\\n display: inline-block;\\n width: 100%;\\n}\\n\\n.vt-card-toolbar .vt-menu {\\n float: left;\\n}\\n.vt-card-toolbar .vt-title {\\n float: right;\\n margin: 0;\\n padding-left: 25px;\\n}\\n\\nmd-list:hover {\\n background: #E8E8E8\\n}\\n\"},function(e,t,n){\"use strict\";var r=this&&this.__extends||function(e,t){function __(){this.constructor=e}for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);e.prototype=null===t?Object.create(t):(__.prototype=t.prototype,new __)},i=n(1),o=n(308),s=n(80),a=n(98),l=function(e){function ArrayObservable(t,n){e.call(this),this.array=t,this.scheduler=n,n||1!==t.length||(this._isScalar=!0,this.value=t[0])}return r(ArrayObservable,e),ArrayObservable.create=function(e,t){return new ArrayObservable(e,t)},ArrayObservable.of=function(){for(var e=[],t=0;t1?new ArrayObservable(e,n):1===r?new o.ScalarObservable(e[0],n):new s.EmptyObservable(n)},ArrayObservable.dispatch=function(e){var t=e.array,n=e.index,r=e.count,i=e.subscriber;return n>=r?void i.complete():(i.next(t[n]),void(i.isUnsubscribed||(e.index=n+1,this.schedule(e))))},ArrayObservable.prototype._subscribe=function(e){var t=0,n=this.array,r=n.length,i=this.scheduler;if(i)return i.schedule(ArrayObservable.dispatch,0,{array:n,index:t,count:r,subscriber:e});for(var o=0;o0?\" { \"+e.children.map(serializeNode).join(\", \")+\" } \":\"\";return\"\"+e.value+t}function advanceActivatedRoute(e){e.snapshot?(a.shallowEqual(e.snapshot.queryParams,e._futureSnapshot.queryParams)||e.queryParams.next(e._futureSnapshot.queryParams),e.snapshot.fragment!==e._futureSnapshot.fragment&&e.fragment.next(e._futureSnapshot.fragment),a.shallowEqual(e.snapshot.params,e._futureSnapshot.params)||(e.params.next(e._futureSnapshot.params),e.data.next(e._futureSnapshot.data)),a.shallowEqualArrays(e.snapshot.url,e._futureSnapshot.url)||e.url.next(e._futureSnapshot.url),e.snapshot=e._futureSnapshot):(e.snapshot=e._futureSnapshot,e.data.next(e._futureSnapshot.data))}var r=this&&this.__extends||function(e,t){function __(){this.constructor=e}for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);e.prototype=null===t?Object.create(t):(__.prototype=t.prototype,new __)},i=n(207),o=n(63),s=n(73),a=n(74),l=n(281),c=function(e){function RouterState(t,n){e.call(this,t),this.snapshot=n,setRouterStateSnapshot(this,t)}return r(RouterState,e),Object.defineProperty(RouterState.prototype,\"queryParams\",{get:function(){return this.root.queryParams},enumerable:!0,configurable:!0}),Object.defineProperty(RouterState.prototype,\"fragment\",{get:function(){return this.root.fragment},enumerable:!0,configurable:!0}),RouterState.prototype.toString=function(){return this.snapshot.toString()},RouterState}(l.Tree);t.RouterState=c,t.createEmptyState=createEmptyState;var u=function(){function ActivatedRoute(e,t,n,r,i,o,s,a){this.url=e,this.params=t,this.queryParams=n,this.fragment=r,this.data=i,this.outlet=o,this.component=s,this._futureSnapshot=a}return Object.defineProperty(ActivatedRoute.prototype,\"routeConfig\",{get:function(){return this._futureSnapshot.routeConfig},enumerable:!0,configurable:!0}),Object.defineProperty(ActivatedRoute.prototype,\"root\",{get:function(){return this._routerState.root},enumerable:!0,configurable:!0}),Object.defineProperty(ActivatedRoute.prototype,\"parent\",{get:function(){return this._routerState.parent(this)},enumerable:!0,configurable:!0}),Object.defineProperty(ActivatedRoute.prototype,\"firstChild\",{get:function(){return this._routerState.firstChild(this)},enumerable:!0,configurable:!0}),Object.defineProperty(ActivatedRoute.prototype,\"children\",{get:function(){return this._routerState.children(this)},enumerable:!0,configurable:!0}),Object.defineProperty(ActivatedRoute.prototype,\"pathFromRoot\",{get:function(){return this._routerState.pathFromRoot(this)},enumerable:!0,configurable:!0}),ActivatedRoute.prototype.toString=function(){return this.snapshot?this.snapshot.toString():\"Future(\"+this._futureSnapshot+\")\"},ActivatedRoute}();t.ActivatedRoute=u;var p=function(){function InheritedResolve(e,t){this.parent=e,this.current=t,this.resolvedData={}}return Object.defineProperty(InheritedResolve.prototype,\"flattenedResolvedData\",{get:function(){return this.parent?a.merge(this.parent.flattenedResolvedData,this.resolvedData):this.resolvedData},enumerable:!0,configurable:!0}),Object.defineProperty(InheritedResolve,\"empty\",{get:function(){return new InheritedResolve(null,{})},enumerable:!0,configurable:!0}),InheritedResolve}();t.InheritedResolve=p;var d=function(){function ActivatedRouteSnapshot(e,t,n,r,i,o,s,a,l,c,u){this.url=e,this.params=t,this.queryParams=n,this.fragment=r,this.data=i,this.outlet=o,this.component=s,this._routeConfig=a,this._urlSegment=l,this._lastPathIndex=c,this._resolve=u}return Object.defineProperty(ActivatedRouteSnapshot.prototype,\"routeConfig\",{get:function(){return this._routeConfig},enumerable:!0,configurable:!0}),Object.defineProperty(ActivatedRouteSnapshot.prototype,\"root\",{get:function(){return this._routerState.root},enumerable:!0,configurable:!0}),Object.defineProperty(ActivatedRouteSnapshot.prototype,\"parent\",{get:function(){return this._routerState.parent(this)},enumerable:!0,configurable:!0}),Object.defineProperty(ActivatedRouteSnapshot.prototype,\"firstChild\",{get:function(){return this._routerState.firstChild(this)},enumerable:!0,configurable:!0}),Object.defineProperty(ActivatedRouteSnapshot.prototype,\"children\",{get:function(){return this._routerState.children(this)},enumerable:!0,configurable:!0}),Object.defineProperty(ActivatedRouteSnapshot.prototype,\"pathFromRoot\",{get:function(){return this._routerState.pathFromRoot(this)},enumerable:!0,configurable:!0}),ActivatedRouteSnapshot.prototype.toString=function(){var e=this.url.map(function(e){return e.toString()}).join(\"/\"),t=this._routeConfig?this._routeConfig.path:\"\";return\"Route(url:'\"+e+\"', path:'\"+t+\"')\"},ActivatedRouteSnapshot}();t.ActivatedRouteSnapshot=d;var h=function(e){function RouterStateSnapshot(t,n){e.call(this,n),this.url=t,setRouterStateSnapshot(this,n)}return r(RouterStateSnapshot,e),Object.defineProperty(RouterStateSnapshot.prototype,\"queryParams\",{get:function(){return this.root.queryParams},enumerable:!0,configurable:!0}),Object.defineProperty(RouterStateSnapshot.prototype,\"fragment\",{get:function(){return this.root.fragment},enumerable:!0,configurable:!0}),RouterStateSnapshot.prototype.toString=function(){return serializeNode(this._root)},RouterStateSnapshot}(l.Tree);t.RouterStateSnapshot=h,t.advanceActivatedRoute=advanceActivatedRoute},function(e,t,n){\"use strict\";var r=n(43),i=(n.n(r),n(0));n.n(i);n.d(t,\"a\",function(){return a});var o=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=o<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if(\"object\"==typeof Reflect&&\"function\"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(o<3?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},s=this&&this.__metadata||function(e,t){if(\"object\"==typeof Reflect&&\"function\"==typeof Reflect.metadata)return Reflect.metadata(e,t)},a=function(){function VtctlService(e){this.http=e,this.vtctlUrl=\"../api/vtctl/\"}return VtctlService.prototype.sendPostRequest=function(e,t){var n=new r.Headers({\"Content-Type\":\"application/json\"}),i=new r.RequestOptions({headers:n});return this.http.post(e,JSON.stringify(t),i).map(function(e){return e.json()})},VtctlService.prototype.runCommand=function(e){return this.sendPostRequest(this.vtctlUrl,e)},VtctlService=o([n.i(i.Injectable)(),s(\"design:paramtypes\",[\"function\"==typeof(e=\"undefined\"!=typeof r.Http&&r.Http)&&e||Object])],VtctlService);var e}()},function(e,t,n){\"use strict\";var r=n(192);n.d(t,\"a\",function(){return i});var i=function(){function DialogContent(e,t,n,r,i){void 0===e&&(e=\"\"),void 0===t&&(t={}),void 0===n&&(n={}),void 0===r&&(r=void 0),void 0===i&&(i=\"\"),this.nameId=e,this.flags=t,this.requiredFlags=n,this.prepareFunction=r,this.action=i}return DialogContent.prototype.getName=function(){return this.flags[this.nameId]?this.flags[this.nameId].getStrValue():\"\"},DialogContent.prototype.setName=function(e){this.flags[this.nameId]&&this.flags[this.nameId].setValue(e)},DialogContent.prototype.getPostBody=function(e){void 0===e&&(e=void 0),e||(e=this.getFlags());var t=[],n=[];t.push(this.action);for(var r=0,i=e;r1?\"path: '\"+e.path.join(\" -> \")+\"'\":e.path[0]?\"name: '\"+e.path+\"'\":\"unspecified name\",new i.BaseException(t+\" \"+n)}function composeValidators(e){return o.isPresent(e)?s.Validators.compose(e.map(c.normalizeValidator)):null}function composeAsyncValidators(e){return o.isPresent(e)?s.Validators.composeAsync(e.map(c.normalizeAsyncValidator)):null}function isPropertyUpdated(e,t){if(!r.StringMapWrapper.contains(e,\"model\"))return!1;var n=e.model;return!!n.isFirstChange()||!o.looseIdentical(t,n.currentValue)}function selectValueAccessor(e,t){if(o.isBlank(t))return null;var n,r,i;return t.forEach(function(t){o.hasConstructor(t,l.DefaultValueAccessor)?n=t:o.hasConstructor(t,a.CheckboxControlValueAccessor)||o.hasConstructor(t,u.NumberValueAccessor)||o.hasConstructor(t,d.SelectControlValueAccessor)||o.hasConstructor(t,h.SelectMultipleControlValueAccessor)||o.hasConstructor(t,p.RadioControlValueAccessor)?(o.isPresent(r)&&_throwError(e,\"More than one built-in value accessor matches form control with\"),r=t):(o.isPresent(i)&&_throwError(e,\"More than one custom value accessor matches form control with\"),i=t)}),o.isPresent(i)?i:o.isPresent(r)?r:o.isPresent(n)?n:(_throwError(e,\"No valid value accessor for form control with\"),null)}var r=n(34),i=n(83),o=n(7),s=n(58),a=n(144),l=n(145),c=n(526),u=n(227),p=n(146),d=n(147),h=n(228);t.controlPath=controlPath,t.setUpControl=setUpControl,t.setUpControlGroup=setUpControlGroup,t.composeValidators=composeValidators,t.composeAsyncValidators=composeAsyncValidators,t.isPropertyUpdated=isPropertyUpdated,t.selectValueAccessor=selectValueAccessor},function(e,t,n){\"use strict\";var r=n(0),i=n(18),o=n(28),s=function(){function CompilerConfig(e){var t=void 0===e?{}:e,n=t.renderTypes,i=void 0===n?new l:n,o=t.defaultEncapsulation,s=void 0===o?r.ViewEncapsulation.Emulated:o,a=t.genDebugInfo,c=t.logBindingUpdate,u=t.useJit,p=void 0===u||u,d=t.deprecatedPlatformDirectives,h=void 0===d?[]:d,f=t.deprecatedPlatformPipes,m=void 0===f?[]:f;this.renderTypes=i,this.defaultEncapsulation=s,this._genDebugInfo=a,this._logBindingUpdate=c,this.useJit=p,this.platformDirectives=h,this.platformPipes=m}return Object.defineProperty(CompilerConfig.prototype,\"genDebugInfo\",{get:function(){return void 0===this._genDebugInfo?r.isDevMode():this._genDebugInfo},enumerable:!0,configurable:!0}),Object.defineProperty(CompilerConfig.prototype,\"logBindingUpdate\",{get:function(){return void 0===this._logBindingUpdate?r.isDevMode():this._logBindingUpdate},enumerable:!0,configurable:!0}),CompilerConfig}();t.CompilerConfig=s;var a=function(){function RenderTypes(){}return Object.defineProperty(RenderTypes.prototype,\"renderer\",{get:function(){return i.unimplemented()},enumerable:!0,configurable:!0}),Object.defineProperty(RenderTypes.prototype,\"renderText\",{get:function(){return i.unimplemented()},enumerable:!0,configurable:!0}),Object.defineProperty(RenderTypes.prototype,\"renderElement\",{get:function(){return i.unimplemented()},enumerable:!0,configurable:!0}),Object.defineProperty(RenderTypes.prototype,\"renderComment\",{get:function(){return i.unimplemented()},enumerable:!0,configurable:!0}),Object.defineProperty(RenderTypes.prototype,\"renderNode\",{get:function(){return i.unimplemented()},enumerable:!0,configurable:!0}),Object.defineProperty(RenderTypes.prototype,\"renderEvent\",{get:function(){return i.unimplemented()},enumerable:!0,configurable:!0}),RenderTypes}();t.RenderTypes=a;var l=function(){function DefaultRenderTypes(){this.renderer=o.Identifiers.Renderer,this.renderText=null,this.renderElement=null,this.renderComment=null,this.renderNode=null,this.renderEvent=null}return DefaultRenderTypes}();t.DefaultRenderTypes=l},function(e,t){\"use strict\";function splitNsName(e){if(\":\"!=e[0])return[null,e];var t=e.indexOf(\":\",1);if(t==-1)throw new Error('Unsupported format \"'+e+'\" expecting \":namespace:name\"');return[e.slice(1,t),e.slice(t+1)]}function getNsPrefix(e){return null===e?null:splitNsName(e)[0]}function mergeNsAndName(e,t){return e?\":\"+e+\":\"+t:t}!function(e){e[e.RAW_TEXT=0]=\"RAW_TEXT\",e[e.ESCAPABLE_RAW_TEXT=1]=\"ESCAPABLE_RAW_TEXT\",e[e.PARSABLE_DATA=2]=\"PARSABLE_DATA\"}(t.TagContentType||(t.TagContentType={}));t.TagContentType;t.splitNsName=splitNsName,t.getNsPrefix=getNsPrefix,t.mergeNsAndName=mergeNsAndName,t.NAMED_ENTITIES={Aacute:\"Á\",aacute:\"á\",Acirc:\"Â\",acirc:\"â\",acute:\"´\",AElig:\"Æ\",aelig:\"æ\",Agrave:\"À\",agrave:\"à\",alefsym:\"ℵ\",Alpha:\"Α\",alpha:\"α\",amp:\"&\",and:\"∧\",ang:\"∠\",apos:\"'\",Aring:\"Å\",aring:\"å\",asymp:\"≈\",Atilde:\"Ã\",atilde:\"ã\",Auml:\"Ä\",auml:\"ä\",bdquo:\"„\",Beta:\"Β\",beta:\"β\",brvbar:\"¦\",bull:\"•\",cap:\"∩\",Ccedil:\"Ç\",ccedil:\"ç\",cedil:\"¸\",cent:\"¢\",Chi:\"Χ\",chi:\"χ\",circ:\"ˆ\",clubs:\"♣\",cong:\"≅\",copy:\"©\",crarr:\"↵\",cup:\"∪\",curren:\"¤\",dagger:\"†\",Dagger:\"‡\",darr:\"↓\",dArr:\"⇓\",deg:\"°\",Delta:\"Δ\",delta:\"δ\",diams:\"♦\",divide:\"÷\",Eacute:\"É\",eacute:\"é\",Ecirc:\"Ê\",ecirc:\"ê\",Egrave:\"È\",egrave:\"è\",empty:\"∅\",emsp:\"\u2003\",ensp:\"\u2002\",Epsilon:\"Ε\",epsilon:\"ε\",equiv:\"≡\",Eta:\"Η\",eta:\"η\",ETH:\"Ð\",eth:\"ð\",Euml:\"Ë\",euml:\"ë\",euro:\"€\",exist:\"∃\",fnof:\"ƒ\",forall:\"∀\",frac12:\"½\",frac14:\"¼\",frac34:\"¾\",frasl:\"⁄\",Gamma:\"Γ\",gamma:\"γ\",ge:\"≥\",gt:\">\",harr:\"↔\",hArr:\"⇔\",hearts:\"♥\",hellip:\"…\",Iacute:\"Í\",iacute:\"í\",Icirc:\"Î\",icirc:\"î\",iexcl:\"¡\",Igrave:\"Ì\",igrave:\"ì\",image:\"ℑ\",infin:\"∞\",\"int\":\"∫\",Iota:\"Ι\",iota:\"ι\",iquest:\"¿\",isin:\"∈\",Iuml:\"Ï\",iuml:\"ï\",Kappa:\"Κ\",kappa:\"κ\",Lambda:\"Λ\",lambda:\"λ\",lang:\"⟨\",laquo:\"«\",larr:\"←\",lArr:\"⇐\",lceil:\"⌈\",ldquo:\"“\",le:\"≤\",lfloor:\"⌊\",lowast:\"∗\",loz:\"◊\",lrm:\"\u200e\",lsaquo:\"‹\",lsquo:\"‘\",lt:\"<\",macr:\"¯\",mdash:\"—\",micro:\"µ\",middot:\"·\",minus:\"−\",Mu:\"Μ\",mu:\"μ\",nabla:\"∇\",nbsp:\"\u00a0\",ndash:\"–\",ne:\"≠\",ni:\"∋\",not:\"¬\",notin:\"∉\",nsub:\"⊄\",Ntilde:\"Ñ\",ntilde:\"ñ\",Nu:\"Ν\",nu:\"ν\",Oacute:\"Ó\",oacute:\"ó\",Ocirc:\"Ô\",ocirc:\"ô\",OElig:\"Œ\",oelig:\"œ\",Ograve:\"Ò\",ograve:\"ò\",oline:\"‾\",Omega:\"Ω\",omega:\"ω\",Omicron:\"Ο\",omicron:\"ο\",oplus:\"⊕\",or:\"∨\",ordf:\"ª\",ordm:\"º\",Oslash:\"Ø\",oslash:\"ø\",Otilde:\"Õ\",otilde:\"õ\",otimes:\"⊗\",Ouml:\"Ö\",ouml:\"ö\",para:\"¶\",permil:\"‰\",perp:\"⊥\",Phi:\"Φ\",phi:\"φ\",Pi:\"Π\",pi:\"π\",piv:\"ϖ\",plusmn:\"±\",pound:\"£\",prime:\"′\",Prime:\"″\",prod:\"∏\",prop:\"∝\",Psi:\"Ψ\",psi:\"ψ\",quot:'\"',radic:\"√\",rang:\"⟩\",raquo:\"»\",rarr:\"→\",rArr:\"⇒\",rceil:\"⌉\",rdquo:\"”\",real:\"ℜ\",reg:\"®\",rfloor:\"⌋\",Rho:\"Ρ\",rho:\"ρ\",rlm:\"\u200f\",rsaquo:\"›\",rsquo:\"’\",sbquo:\"‚\",Scaron:\"Š\",scaron:\"š\",sdot:\"⋅\",sect:\"§\",shy:\"\u00ad\",Sigma:\"Σ\",sigma:\"σ\",sigmaf:\"ς\",sim:\"∼\",spades:\"♠\",sub:\"⊂\",sube:\"⊆\",sum:\"∑\",sup:\"⊃\",sup1:\"¹\",sup2:\"²\",sup3:\"³\",supe:\"⊇\",szlig:\"ß\",Tau:\"Τ\",tau:\"τ\",there4:\"∴\",Theta:\"Θ\",theta:\"θ\",thetasym:\"ϑ\",thinsp:\"\u2009\",THORN:\"Þ\",thorn:\"þ\",tilde:\"˜\",times:\"×\",trade:\"™\",Uacute:\"Ú\",uacute:\"ú\",uarr:\"↑\",uArr:\"⇑\",Ucirc:\"Û\",ucirc:\"û\",Ugrave:\"Ù\",ugrave:\"ù\",uml:\"¨\",upsih:\"ϒ\",Upsilon:\"Υ\",upsilon:\"υ\",Uuml:\"Ü\",uuml:\"ü\",weierp:\"℘\",Xi:\"Ξ\",xi:\"ξ\",Yacute:\"Ý\",yacute:\"ý\",yen:\"¥\",yuml:\"ÿ\",Yuml:\"Ÿ\",Zeta:\"Ζ\",zeta:\"ζ\",zwj:\"\u200d\",zwnj:\"\u200c\"}},function(e,t,n){\"use strict\";function createUrlResolverWithoutPackagePrefix(){return new s}function createOfflineCompileUrlResolver(){return new s(o)}function getUrlScheme(e){var t=_split(e);return t&&t[a.Scheme]||\"\"}function _buildFromEncodedParts(e,t,n,r,o,s,a){var l=[];return i.isPresent(e)&&l.push(e+\":\"),i.isPresent(n)&&(l.push(\"//\"),i.isPresent(t)&&l.push(t+\"@\"),l.push(n),i.isPresent(r)&&l.push(\":\"+r)),i.isPresent(o)&&l.push(o),i.isPresent(s)&&l.push(\"?\"+s),i.isPresent(a)&&l.push(\"#\"+a),l.join(\"\")}function _split(e){return e.match(l)}function _removeDotSegments(e){if(\"/\"==e)return\"/\";for(var t=\"/\"==e[0]?\"/\":\"\",n=\"/\"===e[e.length-1]?\"/\":\"\",r=e.split(\"/\"),i=[],o=0,s=0;s0?i.pop():o++;break;default:i.push(a)}}if(\"\"==t){for(;o-- >0;)i.unshift(\"..\");0===i.length&&i.push(\".\")}return t+i.join(\"/\")+n}function _joinAndCanonicalizePath(e){var t=e[a.Path];return t=i.isBlank(t)?\"\":_removeDotSegments(t),e[a.Path]=t,_buildFromEncodedParts(e[a.Scheme],e[a.UserInfo],e[a.Domain],e[a.Port],t,e[a.QueryData],e[a.Fragment])}function _resolveUrl(e,t){var n=_split(encodeURI(t)),r=_split(e);if(i.isPresent(n[a.Scheme]))return _joinAndCanonicalizePath(n);n[a.Scheme]=r[a.Scheme];for(var o=a.Scheme;o<=a.Port;o++)i.isBlank(n[o])&&(n[o]=r[o]);if(\"/\"==n[a.Path][0])return _joinAndCanonicalizePath(n);var s=r[a.Path];i.isBlank(s)&&(s=\"/\");var l=s.lastIndexOf(\"/\");return s=s.substring(0,l+1)+n[a.Path],n[a.Path]=s,_joinAndCanonicalizePath(n)}var r=n(0),i=n(5),o=\"asset:\";t.createUrlResolverWithoutPackagePrefix=createUrlResolverWithoutPackagePrefix,t.createOfflineCompileUrlResolver=createOfflineCompileUrlResolver,t.DEFAULT_PACKAGE_URL_PROVIDER={provide:r.PACKAGE_ROOT_URL,useValue:\"/\"};var s=function(){function UrlResolver(e){void 0===e&&(e=null),this._packagePrefix=e}return UrlResolver.prototype.resolve=function(e,t){var n=t;i.isPresent(e)&&e.length>0&&(n=_resolveUrl(e,n));var r=_split(n),s=this._packagePrefix;if(i.isPresent(s)&&i.isPresent(r)&&\"package\"==r[a.Scheme]){var l=r[a.Path];if(this._packagePrefix!==o)return s=i.StringWrapper.stripRight(s,\"/\"),l=i.StringWrapper.stripLeft(l,\"/\"),s+\"/\"+l;var c=l.split(/\\//);n=\"asset:\"+c[0]+\"/lib/\"+c.slice(1).join(\"/\")}return n},UrlResolver.decorators=[{type:r.Injectable}],UrlResolver.ctorParameters=[{type:void 0,decorators:[{type:r.Inject,args:[r.PACKAGE_ROOT_URL]}]}],UrlResolver}();t.UrlResolver=s,t.getUrlScheme=getUrlScheme;var a,l=new RegExp(\"^(?:([^:/?#.]+):)?(?://(?:([^/?#]*)@)?([\\\\w\\\\d\\\\-\\\\u0100-\\\\uffff.%]*)(?::([0-9]+))?)?([^?#]+)?(?:\\\\?([^#]*))?(?:#(.*))?$\");!function(e){e[e.Scheme=1]=\"Scheme\",e[e.UserInfo=2]=\"UserInfo\",e[e.Domain=3]=\"Domain\",e[e.Port=4]=\"Port\",e[e.Path=5]=\"Path\",e[e.QueryData=6]=\"QueryData\",e[e.Fragment=7]=\"Fragment\"}(a||(a={}))},function(e,t,n){\"use strict\";function _enumExpression(e,t){if(s.isBlank(t))return l.NULL_EXPR;var n=s.resolveEnumToken(e.runtime,t);return l.importExpr(new o.CompileIdentifierMetadata({name:e.name+\".\"+n,moduleUrl:e.moduleUrl,runtime:t}))}var r=n(0),i=n(27),o=n(31),s=n(5),a=n(28),l=n(17),c=function(){function ViewTypeEnum(){}return ViewTypeEnum.fromValue=function(e){return _enumExpression(a.Identifiers.ViewType,e)},ViewTypeEnum.HOST=ViewTypeEnum.fromValue(i.ViewType.HOST),ViewTypeEnum.COMPONENT=ViewTypeEnum.fromValue(i.ViewType.COMPONENT),ViewTypeEnum.EMBEDDED=ViewTypeEnum.fromValue(i.ViewType.EMBEDDED),ViewTypeEnum}();t.ViewTypeEnum=c;var u=function(){function ViewEncapsulationEnum(){}return ViewEncapsulationEnum.fromValue=function(e){return _enumExpression(a.Identifiers.ViewEncapsulation,e)},ViewEncapsulationEnum.Emulated=ViewEncapsulationEnum.fromValue(r.ViewEncapsulation.Emulated),ViewEncapsulationEnum.Native=ViewEncapsulationEnum.fromValue(r.ViewEncapsulation.Native),ViewEncapsulationEnum.None=ViewEncapsulationEnum.fromValue(r.ViewEncapsulation.None),ViewEncapsulationEnum}();t.ViewEncapsulationEnum=u;var p=function(){function ChangeDetectionStrategyEnum(){}return ChangeDetectionStrategyEnum.fromValue=function(e){return _enumExpression(a.Identifiers.ChangeDetectionStrategy,e)},ChangeDetectionStrategyEnum.OnPush=ChangeDetectionStrategyEnum.fromValue(r.ChangeDetectionStrategy.OnPush),ChangeDetectionStrategyEnum.Default=ChangeDetectionStrategyEnum.fromValue(r.ChangeDetectionStrategy.Default),ChangeDetectionStrategyEnum}();t.ChangeDetectionStrategyEnum=p;var d=function(){function ChangeDetectorStatusEnum(){}return ChangeDetectorStatusEnum.fromValue=function(e){return _enumExpression(a.Identifiers.ChangeDetectorStatus,e)},ChangeDetectorStatusEnum.CheckOnce=ChangeDetectorStatusEnum.fromValue(i.ChangeDetectorStatus.CheckOnce),ChangeDetectorStatusEnum.Checked=ChangeDetectorStatusEnum.fromValue(i.ChangeDetectorStatus.Checked),ChangeDetectorStatusEnum.CheckAlways=ChangeDetectorStatusEnum.fromValue(i.ChangeDetectorStatus.CheckAlways),ChangeDetectorStatusEnum.Detached=ChangeDetectorStatusEnum.fromValue(i.ChangeDetectorStatus.Detached),ChangeDetectorStatusEnum.Errored=ChangeDetectorStatusEnum.fromValue(i.ChangeDetectorStatus.Errored),ChangeDetectorStatusEnum.Destroyed=ChangeDetectorStatusEnum.fromValue(i.ChangeDetectorStatus.Destroyed),ChangeDetectorStatusEnum}();t.ChangeDetectorStatusEnum=d;var h=function(){function ViewConstructorVars(){}return ViewConstructorVars.viewUtils=l.variable(\"viewUtils\"),ViewConstructorVars.parentInjector=l.variable(\"parentInjector\"),ViewConstructorVars.declarationEl=l.variable(\"declarationEl\"),ViewConstructorVars}();t.ViewConstructorVars=h;var f=function(){function ViewProperties(){}return ViewProperties.renderer=l.THIS_EXPR.prop(\"renderer\"),ViewProperties.projectableNodes=l.THIS_EXPR.prop(\"projectableNodes\"),ViewProperties.viewUtils=l.THIS_EXPR.prop(\"viewUtils\"),ViewProperties}();t.ViewProperties=f;var m=function(){function EventHandlerVars(){}return EventHandlerVars.event=l.variable(\"$event\"),EventHandlerVars}();t.EventHandlerVars=m;var g=function(){function InjectMethodVars(){}return InjectMethodVars.token=l.variable(\"token\"),InjectMethodVars.requestNodeIndex=l.variable(\"requestNodeIndex\"),InjectMethodVars.notFoundResult=l.variable(\"notFoundResult\"),InjectMethodVars}();t.InjectMethodVars=g;var y=function(){function DetectChangesVars(){}return DetectChangesVars.throwOnChange=l.variable(\"throwOnChange\"),DetectChangesVars.changes=l.variable(\"changes\"),DetectChangesVars.changed=l.variable(\"changed\"),DetectChangesVars.valUnwrapper=l.variable(\"valUnwrapper\"),DetectChangesVars}();t.DetectChangesVars=y},99,function(e,t,n){var r=n(95);e.exports=function(e,t,n){if(r(e),void 0===t)return e;switch(n){case 1:return function(n){return e.call(t,n)};case 2:return function(n,r){return e.call(t,n,r)};case 3:return function(n,r,i){return e.call(t,n,r,i)}}return function(){return e.apply(t,arguments)}}},function(e,t,n){var r=n(8),i=n(462),o=n(288),s=n(300)(\"IE_PROTO\"),a=function(){},l=\"prototype\",c=function(){var e,t=n(451)(\"iframe\"),r=o.length,i=\"<\",s=\">\";for(t.style.display=\"none\",n(452).appendChild(t),t.src=\"javascript:\",e=t.contentWindow.document,e.open(),e.write(i+\"script\"+s+\"document.F=Object\"+i+\"/script\"+s),e.close(),c=e.F;r--;)delete c[l][o[r]];return c()};e.exports=Object.create||function(e,t){var n;return null!==e?(a[l]=r(e),n=new a,a[l]=null,n[s]=e):n=c(),void 0===t?n:i(n,t)}},function(e,t,n){var r=n(464),i=n(288);e.exports=Object.keys||function(e){return r(e,i)}},function(e,t){e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},function(e,t){var n=Math.ceil,r=Math.floor;e.exports=function(e){return isNaN(e=+e)?0:(e>0?r:n)(e)}},function(e,t,n){\"use strict\";function multicast(e){var t;return t=\"function\"==typeof e?e:function(){return e},new r.ConnectableObservable(this,t)}var r=n(502);t.multicast=multicast},[1107,219],function(e,t){\"use strict\";var n=function(){function ElementSchemaRegistry(){}return ElementSchemaRegistry}();t.ElementSchemaRegistry=n},function(e,t,n){\"use strict\";function getPropertyInView(e,t,n){if(t===n)return e;for(var o=s.THIS_EXPR,a=t;a!==n&&i.isPresent(a.declarationElement.view);)a=a.declarationElement.view,o=o.prop(\"parent\");if(a!==n)throw new r.BaseException(\"Internal error: Could not calculate a property in a parent view: \"+e);if(e instanceof s.ReadPropExpr){var l=e;(n.fields.some(function(e){return e.name==l.name})||n.getters.some(function(e){return e.name==l.name}))&&(o=o.cast(n.classType))}return s.replaceVarInExpression(s.THIS_EXPR.name,o,e)}function injectFromViewParentInjector(e,t){var n=[a.createDiTokenExpression(e)];return t&&n.push(s.NULL_EXPR),s.THIS_EXPR.prop(\"parentInjector\").callMethod(\"get\",n)}function getViewFactoryName(e,t){return\"viewFactory_\"+e.type.name+t}function createFlatArray(e){for(var t=[],n=s.literalArr([]),r=0;r0&&(n=n.callMethod(s.BuiltinMethod.ConcatArray,[s.literalArr(t)]),t=[]),n=n.callMethod(s.BuiltinMethod.ConcatArray,[i])):t.push(i)}return t.length>0&&(n=n.callMethod(s.BuiltinMethod.ConcatArray,[s.literalArr(t)])),n}function createPureProxy(e,t,n,a){a.fields.push(new s.ClassField(n.name,null));var l=t0){var r=e.substring(0,n),i=e.substring(n+1).trim();t.set(r,i)}}),t},Headers.prototype.append=function(e,t){e=normalize(e);var n=this._headersMap.get(e),i=r.isListLikeIterable(n)?n:[];i.push(t),this._headersMap.set(e,i)},Headers.prototype.delete=function(e){this._headersMap.delete(normalize(e))},Headers.prototype.forEach=function(e){this._headersMap.forEach(e)},Headers.prototype.get=function(e){return r.ListWrapper.first(this._headersMap.get(normalize(e)))},Headers.prototype.has=function(e){return this._headersMap.has(normalize(e))},Headers.prototype.keys=function(){return r.MapWrapper.keys(this._headersMap)},Headers.prototype.set=function(e,t){var n=[];if(r.isListLikeIterable(t)){var i=t.join(\",\");n.push(i)}else n.push(t);this._headersMap.set(normalize(e),n)},Headers.prototype.values=function(){return r.MapWrapper.values(this._headersMap)},Headers.prototype.toJSON=function(){var e={};return this._headersMap.forEach(function(t,n){var i=[];r.iterateListLike(t,function(e){return i=r.ListWrapper.concat(i,e.split(\",\"))}),e[normalize(n)]=i}),e},Headers.prototype.getAll=function(e){var t=this._headersMap.get(normalize(e));return r.isListLikeIterable(t)?t:[]},Headers.prototype.entries=function(){throw new i.BaseException('\"entries\" method is not implemented on Headers class')},Headers}();t.Headers=s},function(e,t){\"use strict\";var n=function(){function ConnectionBackend(){}return ConnectionBackend}();t.ConnectionBackend=n;var r=function(){function Connection(){}return Connection}();t.Connection=r;var i=function(){function XSRFStrategy(){}return XSRFStrategy}();t.XSRFStrategy=i},function(e,t,n){\"use strict\";var r=n(0);t.RenderDebugInfo=r.__core_private__.RenderDebugInfo,t.wtfInit=r.__core_private__.wtfInit,t.ReflectionCapabilities=r.__core_private__.ReflectionCapabilities,t.VIEW_ENCAPSULATION_VALUES=r.__core_private__.VIEW_ENCAPSULATION_VALUES,t.DebugDomRootRenderer=r.__core_private__.DebugDomRootRenderer,t.reflector=r.__core_private__.reflector,t.NoOpAnimationPlayer=r.__core_private__.NoOpAnimationPlayer,t.AnimationPlayer=r.__core_private__.AnimationPlayer,t.AnimationSequencePlayer=r.__core_private__.AnimationSequencePlayer,t.AnimationGroupPlayer=r.__core_private__.AnimationGroupPlayer,t.AnimationKeyframe=r.__core_private__.AnimationKeyframe,t.AnimationStyles=r.__core_private__.AnimationStyles,t.prepareFinalAnimationStyles=r.__core_private__.prepareFinalAnimationStyles,t.balanceAnimationKeyframes=r.__core_private__.balanceAnimationKeyframes,t.flattenStyles=r.__core_private__.flattenStyles,t.clearStyles=r.__core_private__.clearStyles,t.collectAndResolveStyles=r.__core_private__.collectAndResolveStyles},function(e,t,n){\"use strict\";var r=n(0);t.DOCUMENT=new r.OpaqueToken(\"DocumentToken\")},function(e,t,n){\"use strict\";var r=this&&this.__extends||function(e,t){function __(){this.constructor=e}for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);e.prototype=null===t?Object.create(t):(__.prototype=t.prototype,new __)},i=n(0),o=n(33),s=n(16),a=n(62),l=n(55),c=function(){function ClientMessageBrokerFactory(){}return ClientMessageBrokerFactory}();t.ClientMessageBrokerFactory=c;var u=function(e){function ClientMessageBrokerFactory_(t,n){e.call(this),this._messageBus=t,this._serializer=n}return r(ClientMessageBrokerFactory_,e),ClientMessageBrokerFactory_.prototype.createMessageBroker=function(e,t){return void 0===t&&(t=!0),this._messageBus.initChannel(e,t),new d(this._messageBus,this._serializer,e)},ClientMessageBrokerFactory_.decorators=[{type:i.Injectable}],ClientMessageBrokerFactory_.ctorParameters=[{type:a.MessageBus},{type:l.Serializer}],ClientMessageBrokerFactory_}(c);t.ClientMessageBrokerFactory_=u;var p=function(){function ClientMessageBroker(){}return ClientMessageBroker}();t.ClientMessageBroker=p;var d=function(e){function ClientMessageBroker_(t,n,r){var i=this;e.call(this),this.channel=r,this._pending=new Map,this._sink=t.to(r),this._serializer=n;var o=t.from(r);o.subscribe({next:function(e){return i._handleMessage(e)}})}return r(ClientMessageBroker_,e),ClientMessageBroker_.prototype._generateMessageId=function(e){for(var t=s.stringify(s.DateWrapper.toMillis(s.DateWrapper.now())),n=0,r=e+t+s.stringify(n);s.isPresent(this._pending[r]);)r=\"\"+e+t+n,n++;return r},ClientMessageBroker_.prototype.runOnService=function(e,t){var n=this,r=[];s.isPresent(e.args)&&e.args.forEach(function(e){null!=e.type?r.push(n._serializer.serialize(e.value,e.type)):r.push(e.value)});var i,o=null;if(null!=t){var a;i=new Promise(function(e,t){a={resolve:e,reject:t}}),o=this._generateMessageId(e.method),this._pending.set(o,a),i.catch(function(e){s.print(e),a.reject(e)}),i=i.then(function(e){return null==n._serializer?e:n._serializer.deserialize(e,t)})}else i=null;var l={method:e.method,args:r};return null!=o&&(l.id=o),this._sink.emit(l),i},ClientMessageBroker_.prototype._handleMessage=function(e){var t=new h(e);if(s.StringWrapper.equals(t.type,\"result\")||s.StringWrapper.equals(t.type,\"error\")){var n=t.id;this._pending.has(n)&&(s.StringWrapper.equals(t.type,\"result\")?this._pending.get(n).resolve(t.value):this._pending.get(n).reject(t.value),this._pending.delete(n))}},ClientMessageBroker_}(p);t.ClientMessageBroker_=d;var h=function(){function MessageData(e){this.type=o.StringMapWrapper.get(e,\"type\"),this.id=this._getValueIfPresent(e,\"id\"),this.value=this._getValueIfPresent(e,\"value\")}return MessageData.prototype._getValueIfPresent=function(e,t){return o.StringMapWrapper.contains(e,t)?o.StringMapWrapper.get(e,t):null},MessageData}(),f=function(){function FnArg(e,t){this.value=e,this.type=t}return FnArg}();t.FnArg=f;var m=function(){function UiArguments(e,t){this.method=e,this.args=t}return UiArguments}();t.UiArguments=m},function(e,t,n){\"use strict\";var r=n(0),i=function(){function RenderStore(){this._nextIndex=0,this._lookupById=new Map,this._lookupByObject=new Map}return RenderStore.prototype.allocateId=function(){return this._nextIndex++},RenderStore.prototype.store=function(e,t){this._lookupById.set(t,e),this._lookupByObject.set(e,t)},RenderStore.prototype.remove=function(e){var t=this._lookupByObject.get(e);this._lookupByObject.delete(e),this._lookupById.delete(t)},RenderStore.prototype.deserialize=function(e){return null==e?null:this._lookupById.has(e)?this._lookupById.get(e):null},RenderStore.prototype.serialize=function(e){return null==e?null:this._lookupByObject.get(e)},RenderStore.decorators=[{type:r.Injectable}],RenderStore.ctorParameters=[],RenderStore}();t.RenderStore=i},function(e,t,n){\"use strict\";var r=this&&this.__extends||function(e,t){function __(){this.constructor=e}for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);e.prototype=null===t?Object.create(t):(__.prototype=t.prototype,new __)},i=n(0),o=n(33),s=n(16),a=n(62),l=n(55),c=function(){function ServiceMessageBrokerFactory(){}return ServiceMessageBrokerFactory}();t.ServiceMessageBrokerFactory=c;var u=function(e){function ServiceMessageBrokerFactory_(t,n){e.call(this),this._messageBus=t,this._serializer=n}return r(ServiceMessageBrokerFactory_,e),ServiceMessageBrokerFactory_.prototype.createMessageBroker=function(e,t){return void 0===t&&(t=!0),this._messageBus.initChannel(e,t),new d(this._messageBus,this._serializer,e)},ServiceMessageBrokerFactory_.decorators=[{type:i.Injectable}],ServiceMessageBrokerFactory_.ctorParameters=[{type:a.MessageBus},{type:l.Serializer}],ServiceMessageBrokerFactory_}(c);t.ServiceMessageBrokerFactory_=u;var p=function(){function ServiceMessageBroker(){}return ServiceMessageBroker}();t.ServiceMessageBroker=p;var d=function(e){function ServiceMessageBroker_(t,n,r){var i=this;e.call(this),this._serializer=n,this.channel=r,this._methods=new o.Map,this._sink=t.to(r);var s=t.from(r);s.subscribe({next:function(e){return i._handleMessage(e)}})}return r(ServiceMessageBroker_,e),ServiceMessageBroker_.prototype.registerMethod=function(e,t,n,r){var i=this;this._methods.set(e,function(e){for(var a=e.args,l=null===t?0:t.length,c=o.ListWrapper.createFixedSize(l),u=0;u0?n[n.length-1]._routeConfig._loadedConfig:null}function nodeChildrenAsMap(e){return e?e.children.reduce(function(e,t){return e[t.value.outlet]=t,e},{}):{}}function getOutlet(e,t){var n=e._outlets[t.outlet];if(!n){var r=t.component.name;throw t.outlet===g.PRIMARY_OUTLET?new Error(\"Cannot find primary outlet to load '\"+r+\"'\"):new Error(\"Cannot find the outlet \"+t.outlet+\" to load '\"+r+\"'\")}return n}n(140),n(499),n(305),n(500),n(493);var r=n(0),i=n(20),o=n(309),s=n(141),a=n(623),l=n(624),c=n(625),u=n(626),p=n(627),d=n(628),h=n(187),f=n(129),m=n(91),g=n(63),y=n(73),v=n(74),b=function(){function NavigationStart(e,t){this.id=e,this.url=t}return NavigationStart.prototype.toString=function(){return\"NavigationStart(id: \"+this.id+\", url: '\"+this.url+\"')\"},NavigationStart}();t.NavigationStart=b;var _=function(){function NavigationEnd(e,t,n){this.id=e,this.url=t,this.urlAfterRedirects=n}return NavigationEnd.prototype.toString=function(){return\"NavigationEnd(id: \"+this.id+\", url: '\"+this.url+\"', urlAfterRedirects: '\"+this.urlAfterRedirects+\"')\"},NavigationEnd}();t.NavigationEnd=_;var w=function(){function NavigationCancel(e,t){this.id=e,this.url=t}return NavigationCancel.prototype.toString=function(){return\"NavigationCancel(id: \"+this.id+\", url: '\"+this.url+\"')\"},NavigationCancel}();t.NavigationCancel=w;var S=function(){function NavigationError(e,t,n){this.id=e,this.url=t,this.error=n}return NavigationError.prototype.toString=function(){return\"NavigationError(id: \"+this.id+\", url: '\"+this.url+\"', error: \"+this.error+\")\"},NavigationError}();t.NavigationError=S;var C=function(){function RoutesRecognized(e,t,n,r){this.id=e,this.url=t,this.urlAfterRedirects=n,this.state=r}return RoutesRecognized.prototype.toString=function(){return\"RoutesRecognized(id: \"+this.id+\", url: '\"+this.url+\"', urlAfterRedirects: '\"+this.urlAfterRedirects+\"', state: \"+this.state+\")\"},RoutesRecognized}();t.RoutesRecognized=C;var E=function(){function Router(e,t,n,r,o,s,a,l){this.rootComponentType=e,this.resolver=t,this.urlSerializer=n,this.outletMap=r,this.location=o,this.injector=s,this.navigationId=0,this.navigated=!1,this.resetConfig(l),this.routerEvents=new i.Subject,this.currentUrlTree=y.createEmptyUrlTree(),this.configLoader=new h.RouterConfigLoader(a),this.currentRouterState=m.createEmptyState(this.currentUrlTree,this.rootComponentType)}return Router.prototype.initialNavigation=function(){this.setUpLocationChangeListener(),this.navigateByUrl(this.location.path(!0))},Object.defineProperty(Router.prototype,\"routerState\",{get:function(){return this.currentRouterState},enumerable:!0,configurable:!0}),Object.defineProperty(Router.prototype,\"url\",{get:function(){return this.serializeUrl(this.currentUrlTree)},enumerable:!0,configurable:!0}),Object.defineProperty(Router.prototype,\"events\",{get:function(){return this.routerEvents},enumerable:!0,configurable:!0}),Router.prototype.resetConfig=function(e){l.validateConfig(e),this.config=e},Router.prototype.ngOnDestroy=function(){this.dispose()},Router.prototype.dispose=function(){this.locationSubscription.unsubscribe()},Router.prototype.createUrlTree=function(e,t){var n=void 0===t?{}:t,r=n.relativeTo,i=n.queryParams,o=n.fragment,s=n.preserveQueryParams,a=n.preserveFragment,l=r?r:this.routerState.root,c=s?this.currentUrlTree.queryParams:i,p=a?this.currentUrlTree.fragment:o;return u.createUrlTree(l,this.currentUrlTree,e,c,p)},Router.prototype.navigateByUrl=function(e,t){if(void 0===t&&(t={skipLocationChange:!1}),e instanceof y.UrlTree)return this.scheduleNavigation(e,t);var n=this.urlSerializer.parse(e);return this.scheduleNavigation(n,t)},Router.prototype.navigate=function(e,t){return void 0===t&&(t={skipLocationChange:!1}),this.scheduleNavigation(this.createUrlTree(e,t),t)},Router.prototype.serializeUrl=function(e){return this.urlSerializer.serialize(e)},Router.prototype.parseUrl=function(e){return this.urlSerializer.parse(e)},Router.prototype.isActive=function(e,t){if(e instanceof y.UrlTree)return y.containsTree(this.currentUrlTree,e,t);var n=this.urlSerializer.parse(e);return y.containsTree(this.currentUrlTree,n,t)},Router.prototype.scheduleNavigation=function(e,t){var n=this,r=++this.navigationId;return this.routerEvents.next(new b(r,this.serializeUrl(e))),Promise.resolve().then(function(i){return n.runNavigate(e,t.skipLocationChange,r)})},Router.prototype.setUpLocationChangeListener=function(){var e=this;this.locationSubscription=this.location.subscribe(Zone.current.wrap(function(t){var n=e.urlSerializer.parse(t.url);return e.currentUrlTree.toString()!==n.toString()?e.scheduleNavigation(n,t.pop):null}))},Router.prototype.runNavigate=function(e,t,n){var r=this;return n!==this.navigationId?(this.location.go(this.urlSerializer.serialize(this.currentUrlTree)),this.routerEvents.next(new w(n,this.serializeUrl(e))),Promise.resolve(!1)):new Promise(function(i,o){var l,u,h,f,m=r.currentRouterState,g=r.currentUrlTree;a.applyRedirects(r.injector,r.configLoader,e,r.config).mergeMap(function(e){return f=e,p.recognize(r.rootComponentType,r.config,f,r.serializeUrl(f))}).mergeMap(function(t){return r.routerEvents.next(new C(n,r.serializeUrl(e),r.serializeUrl(f),t)),d.resolve(r.resolver,t)}).map(function(e){return c.createRouterState(e,r.currentRouterState)}).map(function(e){l=e,h=new P(l.snapshot,r.currentRouterState.snapshot,r.injector),h.traverse(r.outletMap)}).mergeMap(function(e){return h.checkGuards()}).mergeMap(function(e){return e?h.resolveData().map(function(){return e}):s.of(e)}).forEach(function(i){if(!i||n!==r.navigationId)return r.routerEvents.next(new w(n,r.serializeUrl(e))),void(u=!1);if(r.currentUrlTree=f,r.currentRouterState=l,new x(l,m).activate(r.outletMap),!t){var o=r.urlSerializer.serialize(f);r.location.isCurrentPathEqualTo(o)?r.location.replaceState(o):r.location.go(o)}u=!0}).then(function(){r.navigated=!0,r.routerEvents.next(new _(n,r.serializeUrl(e),r.serializeUrl(f))),i(u)},function(t){r.currentRouterState=m,r.currentUrlTree=g,r.routerEvents.next(new S(n,r.serializeUrl(e),t)),o(t)})})},Router}();t.Router=E;var R=function(){function CanActivate(e){this.path=e}return Object.defineProperty(CanActivate.prototype,\"route\",{get:function(){return this.path[this.path.length-1]},enumerable:!0,configurable:!0}),CanActivate}(),T=function(){function CanDeactivate(e,t){this.component=e,this.route=t}return CanDeactivate}(),P=function(){function PreActivation(e,t,n){this.future=e,this.curr=t,this.injector=n,this.checks=[]}return PreActivation.prototype.traverse=function(e){var t=this.future._root,n=this.curr?this.curr._root:null;this.traverseChildRoutes(t,n,e,[t.value])},PreActivation.prototype.checkGuards=function(){var e=this;return 0===this.checks.length?s.of(!0):o.from(this.checks).map(function(t){if(t instanceof R)return v.andObservables(o.from([e.runCanActivate(t.route),e.runCanActivateChild(t.path)]));if(t instanceof T){var n=t;return e.runCanDeactivate(n.component,n.route)}throw new Error(\"Cannot be reached\")}).mergeAll().every(function(e){return e===!0})},PreActivation.prototype.resolveData=function(){var e=this;return 0===this.checks.length?s.of(null):o.from(this.checks).mergeMap(function(t){return t instanceof R?e.runResolve(t.route):s.of(null)}).reduce(function(e,t){return e})},PreActivation.prototype.traverseChildRoutes=function(e,t,n,r){var i=this,o=nodeChildrenAsMap(t);e.children.forEach(function(e){i.traverseRoutes(e,o[e.value.outlet],n,r.concat([e.value])),delete o[e.value.outlet]}),v.forEach(o,function(e,t){return i.deactivateOutletAndItChildren(e,n._outlets[t])})},PreActivation.prototype.traverseRoutes=function(e,t,n,r){var i=e.value,o=t?t.value:null,s=n?n._outlets[e.value.outlet]:null;o&&i._routeConfig===o._routeConfig?(v.shallowEqual(i.params,o.params)||this.checks.push(new T(s.component,o),new R(r)),i.component?this.traverseChildRoutes(e,t,s?s.outletMap:null,r):this.traverseChildRoutes(e,t,n,r)):(o&&(o.component?this.deactivateOutletAndItChildren(o,s):this.deactivateOutletMap(n)),this.checks.push(new R(r)),i.component?this.traverseChildRoutes(e,null,s?s.outletMap:null,r):this.traverseChildRoutes(e,null,n,r))},PreActivation.prototype.deactivateOutletAndItChildren=function(e,t){t&&t.isActivated&&(this.deactivateOutletMap(t.outletMap),this.checks.push(new T(t.component,e)))},PreActivation.prototype.deactivateOutletMap=function(e){var t=this;v.forEach(e._outlets,function(e){e.isActivated&&t.deactivateOutletAndItChildren(e.activatedRoute.snapshot,e)})},PreActivation.prototype.runCanActivate=function(e){var t=this,n=e._routeConfig?e._routeConfig.canActivate:null;if(!n||0===n.length)return s.of(!0);var r=o.from(n).map(function(n){var r=t.getToken(n,e,t.future);return r.canActivate?v.wrapIntoObservable(r.canActivate(e,t.future)):v.wrapIntoObservable(r(e,t.future))});return v.andObservables(r)},PreActivation.prototype.runCanActivateChild=function(e){var t=this,n=e[e.length-1],r=e.slice(0,e.length-1).reverse().map(function(e){return t.extractCanActivateChild(e)}).filter(function(e){return null!==e});return v.andObservables(o.from(r).map(function(e){var r=o.from(e.guards).map(function(e){var r=t.getToken(e,e.node,t.future);return r.canActivateChild?v.wrapIntoObservable(r.canActivateChild(n,t.future)):v.wrapIntoObservable(r(n,t.future))});return v.andObservables(r)}))},PreActivation.prototype.extractCanActivateChild=function(e){var t=e._routeConfig?e._routeConfig.canActivateChild:null;return t&&0!==t.length?{node:e,guards:t}:null},PreActivation.prototype.runCanDeactivate=function(e,t){var n=this,r=t&&t._routeConfig?t._routeConfig.canDeactivate:null;return r&&0!==r.length?o.from(r).map(function(r){var i=n.getToken(r,t,n.curr);return i.canDeactivate?v.wrapIntoObservable(i.canDeactivate(e,t,n.curr)):v.wrapIntoObservable(i(e,t,n.curr))}).mergeAll().every(function(e){return e===!0}):s.of(!0)},PreActivation.prototype.runResolve=function(e){var t=e._resolve;return this.resolveNode(t.current,e).map(function(n){return t.resolvedData=n,e.data=v.merge(e.data,t.flattenedResolvedData),null})},PreActivation.prototype.resolveNode=function(e,t){var n=this;return v.waitForMap(e,function(e,r){var i=n.getToken(r,t,n.future);return i.resolve?v.wrapIntoObservable(i.resolve(t,n.future)):v.wrapIntoObservable(i(t,n.future))})},PreActivation.prototype.getToken=function(e,t,n){var r=closestLoadedConfig(n,t),i=r?r.injector:this.injector;return i.get(e)},PreActivation}(),x=function(){function ActivateRoutes(e,t){this.futureState=e,this.currState=t}return ActivateRoutes.prototype.activate=function(e){var t=this.futureState._root,n=this.currState?this.currState._root:null;m.advanceActivatedRoute(this.futureState.root),this.activateChildRoutes(t,n,e)},ActivateRoutes.prototype.activateChildRoutes=function(e,t,n){var r=this,i=nodeChildrenAsMap(t);e.children.forEach(function(e){r.activateRoutes(e,i[e.value.outlet],n),delete i[e.value.outlet]}),v.forEach(i,function(e,t){return r.deactivateOutletAndItChildren(n._outlets[t])})},ActivateRoutes.prototype.activateRoutes=function(e,t,n){\nvar r=e.value,i=t?t.value:null;if(r===i)if(m.advanceActivatedRoute(r),r.component){var o=getOutlet(n,e.value);this.activateChildRoutes(e,t,o.outletMap)}else this.activateChildRoutes(e,t,n);else{if(i)if(i.component){var o=getOutlet(n,e.value);this.deactivateOutletAndItChildren(o)}else this.deactivateOutletMap(n);if(r.component){m.advanceActivatedRoute(r);var o=getOutlet(n,e.value),s=new f.RouterOutletMap;this.placeComponentIntoOutlet(s,r,o),this.activateChildRoutes(e,null,s)}else m.advanceActivatedRoute(r),this.activateChildRoutes(e,null,n)}},ActivateRoutes.prototype.placeComponentIntoOutlet=function(e,t,n){var i=[{provide:m.ActivatedRoute,useValue:t},{provide:f.RouterOutletMap,useValue:e}],o=closestLoadedConfig(this.futureState.snapshot,t.snapshot),s=null,a=null;o&&(s=o.factoryResolver,a=o.injector,i.push({provide:r.ComponentFactoryResolver,useValue:s})),n.activate(t,s,a,r.ReflectiveInjector.resolve(i),e)},ActivateRoutes.prototype.deactivateOutletAndItChildren=function(e){e&&e.isActivated&&(this.deactivateOutletMap(e.outletMap),e.deactivate())},ActivateRoutes.prototype.deactivateOutletMap=function(e){var t=this;v.forEach(e._outlets,function(e){return t.deactivateOutletAndItChildren(e)})},ActivateRoutes}()},function(e,t){\"use strict\";var n=function(){function RouterOutletMap(){this._outlets={}}return RouterOutletMap.prototype.registerOutlet=function(e,t){this._outlets[e]=t},RouterOutletMap.prototype.removeOutlet=function(e){this._outlets[e]=void 0},RouterOutletMap}();t.RouterOutletMap=n},function(e,t,n){\"use strict\";var r=n(43),i=(n.n(r),n(0));n.n(i);n.d(t,\"a\",function(){return a});var o=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=o<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if(\"object\"==typeof Reflect&&\"function\"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(o<3?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},s=this&&this.__metadata||function(e,t){if(\"object\"==typeof Reflect&&\"function\"==typeof Reflect.metadata)return Reflect.metadata(e,t)},a=function(){function FeaturesService(e){var t=this;this.http=e,this.activeReparents=!1,this.showStatus=!1,this.showTopologyCRUD=!1,this.showWorkflows=!1,this.workflows=[],this.featuresUrl=\"../api/features\",this.getFeatures().subscribe(function(e){t.activeReparents=e.activeReparents,t.showStatus=e.showStatus,t.showTopologyCRUD=e.showTopologyCRUD,t.showWorkflows=e.showWorkflows,t.workflows=e.workflows})}return FeaturesService.prototype.getFeatures=function(){return this.http.get(this.featuresUrl).map(function(e){return e.json()})},FeaturesService=o([n.i(i.Injectable)(),s(\"design:paramtypes\",[\"function\"==typeof(e=\"undefined\"!=typeof r.Http&&r.Http)&&e||Object])],FeaturesService);var e}()},function(e,t,n){\"use strict\";var r=n(43),i=(n.n(r),n(0)),o=(n.n(i),n(484)),s=(n.n(o),n(283)),a=n(644),l=n(284);n.d(t,\"a\",function(){return p});var c=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=o<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if(\"object\"==typeof Reflect&&\"function\"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(o<3?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},u=this&&this.__metadata||function(e,t){if(\"object\"==typeof Reflect&&\"function\"==typeof Reflect.metadata)return Reflect.metadata(e,t)},p=function(){function KeyspaceService(e,t){this.http=e,this.shardService=t,this.keyspacesUrl=\"../api/keyspaces/\",this.srvKeyspaceUrl=\"../api/srv_keyspace/local/\"}return KeyspaceService.prototype.getShards=function(e){return this.shardService.getShards(e)},KeyspaceService.prototype.getKeyspaceNames=function(){return this.http.get(this.keyspacesUrl).map(function(e){return e.json()})},KeyspaceService.prototype.getSrvKeyspaces=function(){return this.http.get(this.srvKeyspaceUrl).map(function(e){return e.json()})},KeyspaceService.prototype.SrvKeyspaceAndNamesObservable=function(){var e=this.getKeyspaceNames(),t=this.getSrvKeyspaces();return e.combineLatest(t)},KeyspaceService.prototype.getKeyspaceShardingData=function(e){return this.http.get(this.keyspacesUrl+e).map(function(e){return e.json()})},KeyspaceService.prototype.getShardsAndShardingData=function(e){var t=this.getShards(e),n=this.getKeyspaceShardingData(e);return t.combineLatest(n)},KeyspaceService.prototype.buildKeyspace=function(e,t){return this.getShardsAndShardingData(e).map(function(n){var r=n[0],i=n[1],o=new a.a(e);return t.forEach(function(e){return o.addServingShard(e)}),r.forEach(function(e){o.contains(e)||o.addNonservingShard(e)}),o.shardingColumnName=i.sharding_column_name||\"\",o.shardingColumnType=i.sharding_column_type||\"\",o})},KeyspaceService.prototype.getServingShards=function(e,t){if(t&&t[e]){var n=t[e].partitions;if(void 0===n)return[];for(var r=0;r=0;a--)(i=e[a])&&(s=(o<3?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){if(\"object\"==typeof Reflect&&\"function\"==typeof Reflect.metadata)return Reflect.metadata(e,t)},o=n(0),s=n(9),a=n(3),l=function(){function Button(e,t){this.el=e,this.domHandler=t,this.iconPos=\"left\"}return Button.prototype.ngAfterViewInit=function(){if(this.domHandler.addMultipleClasses(this.el.nativeElement,this.getStyleClass()),this.icon){var e=document.createElement(\"span\"),t=\"right\"==this.iconPos?\"ui-button-icon-right\":\"ui-button-icon-left\";e.className=t+\" ui-c fa fa-fw \"+this.icon,this.el.nativeElement.appendChild(e)}var n=document.createElement(\"span\");n.className=\"ui-button-text ui-c\",n.appendChild(document.createTextNode(this.label||\"ui-button\")),this.el.nativeElement.appendChild(n),this.initialized=!0},Button.prototype.onMouseenter=function(e){this.hover=!0},Button.prototype.onMouseleave=function(e){this.hover=!1,this.active=!1},Button.prototype.onMouseDown=function(e){this.active=!0},Button.prototype.onMouseUp=function(e){this.active=!1},Button.prototype.onFocus=function(e){this.focus=!0},Button.prototype.onBlur=function(e){this.focus=!1},Button.prototype.isDisabled=function(){return this.el.nativeElement.disabled},Button.prototype.getStyleClass=function(){var e=\"ui-button ui-widget ui-state-default ui-corner-all\";return e+=this.icon?null!=this.label&&void 0!=this.label?\"left\"==this.iconPos?\" ui-button-text-icon-left\":\" ui-button-text-icon-right\":\" ui-button-icon-only\":\" ui-button-text-only\"},Object.defineProperty(Button.prototype,\"label\",{get:function(){return this._label},set:function(e){this._label=e,this.initialized&&(this.domHandler.findSingle(this.el.nativeElement,\".ui-button-text\").textContent=this._label)},enumerable:!0,configurable:!0}),Button.prototype.ngOnDestroy=function(){for(;this.el.nativeElement.hasChildNodes();)this.el.nativeElement.removeChild(this.el.nativeElement.lastChild);this.initialized=!1},r([o.Input(),i(\"design:type\",String)],Button.prototype,\"icon\",void 0),r([o.Input(),i(\"design:type\",String)],Button.prototype,\"iconPos\",void 0),r([o.HostListener(\"mouseenter\",[\"$event\"]),i(\"design:type\",Function),i(\"design:paramtypes\",[Object]),i(\"design:returntype\",void 0)],Button.prototype,\"onMouseenter\",null),r([o.HostListener(\"mouseleave\",[\"$event\"]),i(\"design:type\",Function),i(\"design:paramtypes\",[Object]),i(\"design:returntype\",void 0)],Button.prototype,\"onMouseleave\",null),r([o.HostListener(\"mousedown\",[\"$event\"]),i(\"design:type\",Function),i(\"design:paramtypes\",[Object]),i(\"design:returntype\",void 0)],Button.prototype,\"onMouseDown\",null),r([o.HostListener(\"mouseup\",[\"$event\"]),i(\"design:type\",Function),i(\"design:paramtypes\",[Object]),i(\"design:returntype\",void 0)],Button.prototype,\"onMouseUp\",null),r([o.HostListener(\"focus\",[\"$event\"]),i(\"design:type\",Function),i(\"design:paramtypes\",[Object]),i(\"design:returntype\",void 0)],Button.prototype,\"onFocus\",null),r([o.HostListener(\"blur\",[\"$event\"]),i(\"design:type\",Function),i(\"design:paramtypes\",[Object]),i(\"design:returntype\",void 0)],Button.prototype,\"onBlur\",null),r([o.Input(),i(\"design:type\",String)],Button.prototype,\"label\",null),Button=r([o.Directive({selector:\"[pButton]\",host:{\"[class.ui-state-hover]\":\"hover&&!isDisabled()\",\"[class.ui-state-focus]\":\"focus\",\"[class.ui-state-active]\":\"active\",\"[class.ui-state-disabled]\":\"isDisabled()\"},providers:[s.DomHandler]}),i(\"design:paramtypes\",[o.ElementRef,s.DomHandler])],Button)}();t.Button=l;var c=function(){function ButtonModule(){}return ButtonModule=r([o.NgModule({imports:[a.CommonModule],exports:[l],declarations:[l]}),i(\"design:paramtypes\",[])],ButtonModule)}();t.ButtonModule=c},function(e,t,n){\"use strict\";var r=n(1),i=n(505);r.Observable.prototype.map=i.map},function(e,t,n){\"use strict\";var r=n(79);t.of=r.ArrayObservable.of},function(e,t,n){\"use strict\";var r=n(51),i=r.root.Symbol;if(\"function\"==typeof i)i.iterator?t.$$iterator=i.iterator:\"function\"==typeof i.for&&(t.$$iterator=i.for(\"iterator\"));else if(r.root.Set&&\"function\"==typeof(new r.root.Set)[\"@@iterator\"])t.$$iterator=\"@@iterator\";else if(r.root.Map)for(var o=Object.getOwnPropertyNames(r.root.Map.prototype),s=0;s=this.length?i.$EOF:o.StringWrapper.charCodeAt(this.input,this.index)},_Scanner.prototype.scanToken=function(){for(var e=this.input,t=this.length,n=this.peek,r=this.index;n<=i.$SPACE;){if(++r>=t){n=i.$EOF;break}n=o.StringWrapper.charCodeAt(e,r)}if(this.peek=n,this.index=r,r>=t)return null;if(isIdentifierStart(n))return this.scanIdentifier();if(i.isDigit(n))return this.scanNumber(r);var s=r;switch(n){case i.$PERIOD:return this.advance(),i.isDigit(this.peek)?this.scanNumber(s):newCharacterToken(s,i.$PERIOD);case i.$LPAREN:case i.$RPAREN:case i.$LBRACE:case i.$RBRACE:case i.$LBRACKET:case i.$RBRACKET:case i.$COMMA:case i.$COLON:case i.$SEMICOLON:return this.scanCharacter(s,n);case i.$SQ:case i.$DQ:return this.scanString();case i.$HASH:case i.$PLUS:case i.$MINUS:case i.$STAR:case i.$SLASH:case i.$PERCENT:case i.$CARET:return this.scanOperator(s,o.StringWrapper.fromCharCode(n));case i.$QUESTION:return this.scanComplexOperator(s,\"?\",i.$PERIOD,\".\");case i.$LT:case i.$GT:return this.scanComplexOperator(s,o.StringWrapper.fromCharCode(n),i.$EQ,\"=\");case i.$BANG:case i.$EQ:return this.scanComplexOperator(s,o.StringWrapper.fromCharCode(n),i.$EQ,\"=\",i.$EQ,\"=\");case i.$AMPERSAND:return this.scanComplexOperator(s,\"&\",i.$AMPERSAND,\"&\");case i.$BAR:return this.scanComplexOperator(s,\"|\",i.$BAR,\"|\");case i.$NBSP:for(;i.isWhitespace(this.peek);)this.advance();return this.scanToken()}return this.advance(),this.error(\"Unexpected character [\"+o.StringWrapper.fromCharCode(n)+\"]\",0)},_Scanner.prototype.scanCharacter=function(e,t){return this.advance(),newCharacterToken(e,t)},_Scanner.prototype.scanOperator=function(e,t){return this.advance(),newOperatorToken(e,t)},_Scanner.prototype.scanComplexOperator=function(e,t,n,r,i,s){this.advance();var a=t;return this.peek==n&&(this.advance(),a+=r),o.isPresent(i)&&this.peek==i&&(this.advance(),a+=s),newOperatorToken(e,a)},_Scanner.prototype.scanIdentifier=function(){var e=this.index;for(this.advance();isIdentifierPart(this.peek);)this.advance();var t=this.input.substring(e,this.index);return a.indexOf(t)>-1?newKeywordToken(e,t):newIdentifierToken(e,t)},_Scanner.prototype.scanNumber=function(e){var t=this.index===e;for(this.advance();;){if(i.isDigit(this.peek));else if(this.peek==i.$PERIOD)t=!1;else{if(!isExponentStart(this.peek))break;if(this.advance(),isExponentSign(this.peek)&&this.advance(),!i.isDigit(this.peek))return this.error(\"Invalid exponent\",-1);t=!1}this.advance()}var n=this.input.substring(e,this.index),r=t?o.NumberWrapper.parseIntAutoRadix(n):o.NumberWrapper.parseFloat(n);return newNumberToken(e,r)},_Scanner.prototype.scanString=function(){var e=this.index,t=this.peek;this.advance();for(var n,r=this.index,s=this.input;this.peek!=t;)if(this.peek==i.$BACKSLASH){null==n&&(n=new o.StringJoiner),n.add(s.substring(r,this.index)),this.advance();var a;if(this.peek==i.$u){var l=s.substring(this.index+1,this.index+5);try{a=o.NumberWrapper.parseInt(l,16)}catch(c){return this.error(\"Invalid unicode escape [\\\\u\"+l+\"]\",0)}for(var u=0;u<5;u++)this.advance()}else a=unescape(this.peek),this.advance();n.add(o.StringWrapper.fromCharCode(a)),r=this.index}else{if(this.peek==i.$EOF)return this.error(\"Unterminated quote\",0);this.advance()}var p=s.substring(r,this.index);this.advance();var d=p;return null!=n&&(n.add(p),d=n.toString()),newStringToken(e,d)},_Scanner.prototype.error=function(e,t){var n=this.index+t;return newErrorToken(n,\"Lexer Error: \"+e+\" at column \"+n+\" in expression [\"+this.input+\"]\")},_Scanner}();t.isIdentifier=isIdentifier,t.isQuote=isQuote},function(e,t,n){\"use strict\";function _createInterpolateRegExp(e){var t=o.escapeRegExp(e.start)+\"([\\\\s\\\\S]*?)\"+o.escapeRegExp(e.end);return new RegExp(t,\"g\")}var r=n(0),i=n(233),o=n(5),s=n(68),a=n(236),l=n(151),c=function(){function SplitInterpolation(e,t){this.strings=e,this.expressions=t}return SplitInterpolation}();t.SplitInterpolation=c;var u=function(){function TemplateBindingParseResult(e,t,n){this.templateBindings=e,this.warnings=t,this.errors=n}return TemplateBindingParseResult}();t.TemplateBindingParseResult=u;var p=function(){function Parser(e){this._lexer=e,this.errors=[]}return Parser.prototype.parseAction=function(e,t,n){void 0===n&&(n=s.DEFAULT_INTERPOLATION_CONFIG),this._checkNoInterpolation(e,t,n);var r=this._lexer.tokenize(this._stripComments(e)),i=new d(e,t,r,(!0),this.errors).parseChain();return new a.ASTWithSource(i,e,t,this.errors)},Parser.prototype.parseBinding=function(e,t,n){void 0===n&&(n=s.DEFAULT_INTERPOLATION_CONFIG);var r=this._parseBindingAst(e,t,n);return new a.ASTWithSource(r,e,t,this.errors)},Parser.prototype.parseSimpleBinding=function(e,t,n){void 0===n&&(n=s.DEFAULT_INTERPOLATION_CONFIG);var r=this._parseBindingAst(e,t,n);return h.check(r)||this._reportError(\"Host binding expression can only contain field access and constants\",e,t),new a.ASTWithSource(r,e,t,this.errors)},Parser.prototype._reportError=function(e,t,n,r){this.errors.push(new a.ParserError(e,t,n,r))},Parser.prototype._parseBindingAst=function(e,t,n){var r=this._parseQuote(e,t);if(o.isPresent(r))return r;this._checkNoInterpolation(e,t,n);var i=this._lexer.tokenize(this._stripComments(e));return new d(e,t,i,(!1),this.errors).parseChain()},Parser.prototype._parseQuote=function(e,t){if(o.isBlank(e))return null;var n=e.indexOf(\":\");if(n==-1)return null;var r=e.substring(0,n).trim();if(!l.isIdentifier(r))return null;var i=e.substring(n+1);return new a.Quote(new a.ParseSpan(0,e.length),r,i,t)},Parser.prototype.parseTemplateBindings=function(e,t){var n=this._lexer.tokenize(e);return new d(e,t,n,(!1),this.errors).parseTemplateBindings()},Parser.prototype.parseInterpolation=function(e,t,n){void 0===n&&(n=s.DEFAULT_INTERPOLATION_CONFIG);var r=this.splitInterpolation(e,t,n);if(null==r)return null;for(var i=[],l=0;l0?l.push(p):this._reportError(\"Blank expressions are not allowed in interpolated strings\",e,\"at column \"+this._findInterpolationErrorColumn(i,u,n)+\" in\",t)}return new c(a,l)},Parser.prototype.wrapLiteralPrimitive=function(e,t){return new a.ASTWithSource(new a.LiteralPrimitive(new a.ParseSpan(0,o.isBlank(e)?0:e.length),e),e,t,this.errors)},Parser.prototype._stripComments=function(e){var t=this._commentStart(e);return o.isPresent(t)?e.substring(0,t).trim():e},Parser.prototype._commentStart=function(e){for(var t=null,n=0;n1&&this._reportError(\"Got interpolation (\"+n.start+n.end+\") where expression was expected\",e,\"at column \"+this._findInterpolationErrorColumn(i,1,n)+\" in\",t)},Parser.prototype._findInterpolationErrorColumn=function(e,t,n){for(var r=\"\",i=0;i\":case\"<=\":case\">=\":this.advance();var n=this.parseAdditive();e=new a.Binary(this.span(e.span.start),t,e,n);continue}break}return e},_ParseAST.prototype.parseAdditive=function(){for(var e=this.parseMultiplicative();this.next.type==l.TokenType.Operator;){var t=this.next.strValue;switch(t){case\"+\":case\"-\":this.advance();var n=this.parseMultiplicative();e=new a.Binary(this.span(e.span.start),t,e,n);continue}break}return e},_ParseAST.prototype.parseMultiplicative=function(){for(var e=this.parsePrefix();this.next.type==l.TokenType.Operator;){var t=this.next.strValue;switch(t){case\"*\":case\"%\":case\"/\":this.advance();var n=this.parsePrefix();e=new a.Binary(this.span(e.span.start),t,e,n);continue}break}return e},_ParseAST.prototype.parsePrefix=function(){if(this.next.type==l.TokenType.Operator){var e=this.inputIndex,t=this.next.strValue,n=void 0;switch(t){case\"+\":return this.advance(),this.parsePrefix();case\"-\":return this.advance(),n=this.parsePrefix(),new a.Binary(this.span(e),t,new a.LiteralPrimitive(new a.ParseSpan(e,e),0),n);case\"!\":return this.advance(),n=this.parsePrefix(),new a.PrefixNot(this.span(e),n)}}return this.parseCallChain()},_ParseAST.prototype.parseCallChain=function(){for(var e=this.parsePrimary();;)if(this.optionalCharacter(i.$PERIOD))e=this.parseAccessMemberOrMethodCall(e,!1);else if(this.optionalOperator(\"?.\"))e=this.parseAccessMemberOrMethodCall(e,!0);else if(this.optionalCharacter(i.$LBRACKET)){this.rbracketsExpected++;var t=this.parsePipe();if(this.rbracketsExpected--,this.expectCharacter(i.$RBRACKET),this.optionalOperator(\"=\")){var n=this.parseConditional();e=new a.KeyedWrite(this.span(e.span.start),e,t,n)}else e=new a.KeyedRead(this.span(e.span.start),e,t)}else{if(!this.optionalCharacter(i.$LPAREN))return e;this.rparensExpected++;var r=this.parseCallArguments();this.rparensExpected--,this.expectCharacter(i.$RPAREN),e=new a.FunctionCall(this.span(e.span.start),e,r)}},_ParseAST.prototype.parsePrimary=function(){var e=this.inputIndex;if(this.optionalCharacter(i.$LPAREN)){this.rparensExpected++;var t=this.parsePipe();return this.rparensExpected--,this.expectCharacter(i.$RPAREN),t}if(this.next.isKeywordNull())return this.advance(),new a.LiteralPrimitive(this.span(e),null);if(this.next.isKeywordUndefined())return this.advance(),new a.LiteralPrimitive(this.span(e),(void 0));if(this.next.isKeywordTrue())return this.advance(),new a.LiteralPrimitive(this.span(e),(!0));if(this.next.isKeywordFalse())return this.advance(),new a.LiteralPrimitive(this.span(e),(!1));if(this.next.isKeywordThis())return this.advance(),new a.ImplicitReceiver(this.span(e));if(this.optionalCharacter(i.$LBRACKET)){this.rbracketsExpected++;var n=this.parseExpressionList(i.$RBRACKET);return this.rbracketsExpected--,this.expectCharacter(i.$RBRACKET),new a.LiteralArray(this.span(e),n)}if(this.next.isCharacter(i.$LBRACE))return this.parseLiteralMap();if(this.next.isIdentifier())return this.parseAccessMemberOrMethodCall(new a.ImplicitReceiver(this.span(e)),!1);if(this.next.isNumber()){var r=this.next.toNumber();return this.advance(),new a.LiteralPrimitive(this.span(e),r)}if(this.next.isString()){var o=this.next.toString();return this.advance(),new a.LiteralPrimitive(this.span(e),o)}return this.index>=this.tokens.length?(this.error(\"Unexpected end of expression: \"+this.input),new a.EmptyExpr(this.span(e))):(this.error(\"Unexpected token \"+this.next),new a.EmptyExpr(this.span(e)))},_ParseAST.prototype.parseExpressionList=function(e){var t=[];if(!this.next.isCharacter(e))do t.push(this.parsePipe());while(this.optionalCharacter(i.$COMMA));return t},_ParseAST.prototype.parseLiteralMap=function(){var e=[],t=[],n=this.inputIndex;if(this.expectCharacter(i.$LBRACE),!this.optionalCharacter(i.$RBRACE)){this.rbracesExpected++;do{var r=this.expectIdentifierOrKeywordOrString();e.push(r),this.expectCharacter(i.$COLON),t.push(this.parsePipe())}while(this.optionalCharacter(i.$COMMA));this.rbracesExpected--,this.expectCharacter(i.$RBRACE)}return new a.LiteralMap(this.span(n),e,t)},_ParseAST.prototype.parseAccessMemberOrMethodCall=function(e,t){void 0===t&&(t=!1);var n=e.span.start,r=this.expectIdentifierOrKeyword();if(this.optionalCharacter(i.$LPAREN)){this.rparensExpected++;var o=this.parseCallArguments();this.expectCharacter(i.$RPAREN),this.rparensExpected--;var s=this.span(n);return t?new a.SafeMethodCall(s,e,r,o):new a.MethodCall(s,e,r,o)}if(t)return this.optionalOperator(\"=\")?(this.error(\"The '?.' operator cannot be used in the assignment\"),new a.EmptyExpr(this.span(n))):new a.SafePropertyRead(this.span(n),e,r);if(this.optionalOperator(\"=\")){if(!this.parseAction)return this.error(\"Bindings cannot contain assignments\"),new a.EmptyExpr(this.span(n));var l=this.parseConditional();return new a.PropertyWrite(this.span(n),e,r,l)}return new a.PropertyRead(this.span(n),e,r)},_ParseAST.prototype.parseCallArguments=function(){if(this.next.isCharacter(i.$RPAREN))return[];var e=[];do e.push(this.parsePipe());while(this.optionalCharacter(i.$COMMA));return e},_ParseAST.prototype.expectTemplateBindingKey=function(){var e=\"\",t=!1;do e+=this.expectIdentifierOrKeywordOrString(),t=this.optionalOperator(\"-\"),t&&(e+=\"-\");while(t);return e.toString()},_ParseAST.prototype.parseTemplateBindings=function(){for(var e=[],t=null,n=[];this.index0&&e[e.length-1]===t}var r=this&&this.__extends||function(e,t){function __(){this.constructor=e}for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);e.prototype=null===t?Object.create(t):(__.prototype=t.prototype,new __)},i=n(10),o=n(5),s=n(60),a=n(85),l=n(68),c=n(546),u=n(102),p=function(e){function TreeError(t,n,r){e.call(this,n,r),this.elementName=t}return r(TreeError,e),TreeError.create=function(e,t,n){return new TreeError(e,t,n)},TreeError}(s.ParseError);t.TreeError=p;var d=function(){function ParseTreeResult(e,t){this.rootNodes=e,this.errors=t}return ParseTreeResult}();t.ParseTreeResult=d;var h=function(){function Parser(e){this._getTagDefinition=e}return Parser.prototype.parse=function(e,t,n,r){void 0===n&&(n=!1),void 0===r&&(r=l.DEFAULT_INTERPOLATION_CONFIG);var i=c.tokenize(e,t,this._getTagDefinition,n,r),o=new f(i.tokens,this._getTagDefinition).build();return new d(o.rootNodes,i.errors.concat(o.errors))},Parser}();t.Parser=h;var f=function(){function _TreeBuilder(e,t){this.tokens=e,this.getTagDefinition=t,this._index=-1,this._rootNodes=[],this._errors=[],this._elementStack=[],this._advance()}return _TreeBuilder.prototype.build=function(){for(;this._peek.type!==c.TokenType.EOF;)this._peek.type===c.TokenType.TAG_OPEN_START?this._consumeStartTag(this._advance()):this._peek.type===c.TokenType.TAG_CLOSE?this._consumeEndTag(this._advance()):this._peek.type===c.TokenType.CDATA_START?(this._closeVoidElement(),this._consumeCdata(this._advance())):this._peek.type===c.TokenType.COMMENT_START?(this._closeVoidElement(),this._consumeComment(this._advance())):this._peek.type===c.TokenType.TEXT||this._peek.type===c.TokenType.RAW_TEXT||this._peek.type===c.TokenType.ESCAPABLE_RAW_TEXT?(this._closeVoidElement(),this._consumeText(this._advance())):this._peek.type===c.TokenType.EXPANSION_FORM_START?this._consumeExpansion(this._advance()):this._advance();return new d(this._rootNodes,this._errors)},_TreeBuilder.prototype._advance=function(){var e=this._peek;return this._index0)return this._errors=this._errors.concat(i.errors),null;var l=new s.ParseSourceSpan(e.sourceSpan.start,r.sourceSpan.end),u=new s.ParseSourceSpan(t.sourceSpan.start,r.sourceSpan.end);return new a.ExpansionCase(e.parts[0],i.rootNodes,l,e.sourceSpan,u)},_TreeBuilder.prototype._collectExpansionExpTokens=function(e){for(var t=[],n=[c.TokenType.EXPANSION_CASE_EXP_START];;){if(this._peek.type!==c.TokenType.EXPANSION_FORM_START&&this._peek.type!==c.TokenType.EXPANSION_CASE_EXP_START||n.push(this._peek.type),this._peek.type===c.TokenType.EXPANSION_CASE_EXP_END){if(!lastOnStack(n,c.TokenType.EXPANSION_CASE_EXP_START))return this._errors.push(p.create(null,e.sourceSpan,\"Invalid ICU message. Missing '}'.\")),null;if(n.pop(),0==n.length)return t}if(this._peek.type===c.TokenType.EXPANSION_FORM_END){if(!lastOnStack(n,c.TokenType.EXPANSION_FORM_START))return this._errors.push(p.create(null,e.sourceSpan,\"Invalid ICU message. Missing '}'.\")),null;n.pop()}if(this._peek.type===c.TokenType.EOF)return this._errors.push(p.create(null,e.sourceSpan,\"Invalid ICU message. Missing '}'.\")),null;t.push(this._advance())}},_TreeBuilder.prototype._consumeText=function(e){var t=e.parts[0];if(t.length>0&&\"\\n\"==t[0]){var n=this._getParentElement();o.isPresent(n)&&0==n.children.length&&this.getTagDefinition(n.name).ignoreFirstLf&&(t=t.substring(1))}t.length>0&&this._addToParent(new a.Text(t,e.sourceSpan))},_TreeBuilder.prototype._closeVoidElement=function(){if(this._elementStack.length>0){var e=i.ListWrapper.last(this._elementStack);this.getTagDefinition(e.name).isVoid&&this._elementStack.pop()}},_TreeBuilder.prototype._consumeStartTag=function(e){for(var t=e.parts[0],n=e.parts[1],r=[];this._peek.type===c.TokenType.ATTR_NAME;)r.push(this._consumeAttr(this._advance()));var i=this._getElementFullName(t,n,this._getParentElement()),o=!1;if(this._peek.type===c.TokenType.TAG_OPEN_END_VOID){this._advance(),o=!0;var l=this.getTagDefinition(i);l.canSelfClose||null!==u.getNsPrefix(i)||l.isVoid||this._errors.push(p.create(i,e.sourceSpan,'Only void and foreign elements can be self closed \"'+e.parts[1]+'\"'))}else this._peek.type===c.TokenType.TAG_OPEN_END&&(this._advance(),o=!1);var d=this._peek.sourceSpan.start,h=new s.ParseSourceSpan(e.sourceSpan.start,d),f=new a.Element(i,r,[],h,h,null);this._pushElement(f),o&&(this._popElement(i),f.endSourceSpan=h)},_TreeBuilder.prototype._pushElement=function(e){if(this._elementStack.length>0){var t=i.ListWrapper.last(this._elementStack);this.getTagDefinition(t.name).isClosedByChild(e.name)&&this._elementStack.pop()}var n=this.getTagDefinition(e.name),r=this._getParentElementSkippingContainers(),s=r.parent,l=r.container;if(o.isPresent(s)&&n.requireExtraParent(s.name)){var c=new a.Element(n.parentToAdd,[],[],e.sourceSpan,e.startSourceSpan,e.endSourceSpan);this._insertBeforeContainer(s,l,c)}this._addToParent(e),this._elementStack.push(e)},_TreeBuilder.prototype._consumeEndTag=function(e){var t=this._getElementFullName(e.parts[0],e.parts[1],this._getParentElement());this._getParentElement()&&(this._getParentElement().endSourceSpan=e.sourceSpan),this.getTagDefinition(t).isVoid?this._errors.push(p.create(t,e.sourceSpan,'Void elements do not have end tags \"'+e.parts[1]+'\"')):this._popElement(t)||this._errors.push(p.create(t,e.sourceSpan,'Unexpected closing tag \"'+e.parts[1]+'\"'))},_TreeBuilder.prototype._popElement=function(e){for(var t=this._elementStack.length-1;t>=0;t--){var n=this._elementStack[t];if(n.name==e)return i.ListWrapper.splice(this._elementStack,t,this._elementStack.length-t),!0;if(!this.getTagDefinition(n.name).closedByParent)return!1}return!1},_TreeBuilder.prototype._consumeAttr=function(e){var t=u.mergeNsAndName(e.parts[0],e.parts[1]),n=e.sourceSpan.end,r=\"\";if(this._peek.type===c.TokenType.ATTR_VALUE){var i=this._advance();r=i.parts[0],n=i.sourceSpan.end}return new a.Attribute(t,r,new s.ParseSourceSpan(e.sourceSpan.start,n))},_TreeBuilder.prototype._getParentElement=function(){return this._elementStack.length>0?i.ListWrapper.last(this._elementStack):null},_TreeBuilder.prototype._getParentElementSkippingContainers=function(){for(var e=null,t=this._elementStack.length-1;t>=0;t--){if(\"ng-container\"!==this._elementStack[t].name)return{parent:this._elementStack[t],container:e};e=this._elementStack[t]}return{parent:i.ListWrapper.last(this._elementStack),container:e}},_TreeBuilder.prototype._addToParent=function(e){var t=this._getParentElement();o.isPresent(t)?t.children.push(e):this._rootNodes.push(e)},_TreeBuilder.prototype._insertBeforeContainer=function(e,t,n){if(t){if(e){var r=e.children.indexOf(t);e.children[r]=n}else this._rootNodes.push(n);n.children.push(t),this._elementStack.splice(this._elementStack.indexOf(t),0,n)}else this._addToParent(n),this._elementStack.push(n)},_TreeBuilder.prototype._getElementFullName=function(e,t,n){return o.isBlank(e)&&(e=this.getTagDefinition(t).implicitNamespacePrefix,o.isBlank(e)&&o.isPresent(n)&&(e=u.getNsPrefix(n.name))),u.mergeNsAndName(e,t)},_TreeBuilder}()},function(e,t,n){\"use strict\";function splitClasses(e){return e.trim().split(/\\s+/g)}function createElementCssSelector(e,t){var n=new w.CssSelector,r=y.splitNsName(e)[1];n.setElement(r);for(var i=0;i0&&this._console.warn(\"Template parse warnings:\\n\"+a.join(\"\\n\")),l.length>0){var c=l.join(\"\\n\");throw new u.BaseException(\"Template parse errors:\\n\"+c)}return s.templateAst},TemplateParser.prototype.tryParse=function(e,t,n,r,i,o){var a;e.template&&(a=g.InterpolationConfig.fromArray(e.template.interpolation));var l,c=this._htmlParser.parse(t,o,!0,a),u=c.errors;if(0==u.length){var d=m.expandNodes(c.rootNodes);u.push.apply(u,d.errors),c=new f.ParseTreeResult(d.nodes,u)}if(c.rootNodes.length>0){var y=s.removeIdentifierDuplicates(n),v=s.removeIdentifierDuplicates(r),_=new b.ProviderViewContext(e,c.rootNodes[0].sourceSpan),w=new j(_,y,v,i,this._exprParser,this._schemaRegistry);l=h.visitAll(w,c.rootNodes,z),u.push.apply(u,w.errors.concat(_.errors))}else l=[];return this._assertNoReferenceDuplicationOnTemplate(l,u),u.length>0?new L(l,u):(p.isPresent(this.transforms)&&this.transforms.forEach(function(e){l=E.templateVisitAll(e,l)}),new L(l,u))},TemplateParser.prototype._assertNoReferenceDuplicationOnTemplate=function(e,t){var n=[];e.filter(function(e){return!!e.references}).forEach(function(e){return e.references.forEach(function(e){var r=e.name;if(n.indexOf(r)<0)n.push(r);else{var i=new V('Reference \"#'+r+'\" is defined several times',e.sourceSpan,v.ParseErrorLevel.FATAL);t.push(i)}})})},TemplateParser.decorators=[{type:i.Injectable}],TemplateParser.ctorParameters=[{type:l.Parser},{type:_.ElementSchemaRegistry},{type:f.HtmlParser},{type:o.Console},{type:Array,decorators:[{type:i.Optional},{type:i.Inject,args:[t.TEMPLATE_TRANSFORMS]}]}],TemplateParser}();t.TemplateParser=F;var j=function(){function TemplateParseVisitor(e,t,n,r,i,o){var s=this;this.providerViewContext=e,this._schemas=r,this._exprParser=i,this._schemaRegistry=o,this.errors=[],this.directivesIndex=new Map,this.ngContentCount=0,this.selectorMatcher=new w.SelectorMatcher;var a=e.component.template;p.isPresent(a)&&p.isPresent(a.interpolation)&&(this._interpolationConfig={start:a.interpolation[0],end:a.interpolation[1]}),c.ListWrapper.forEachWithIndex(t,function(e,t){var n=w.CssSelector.parse(e.selector);s.selectorMatcher.addSelectables(n,e),s.directivesIndex.set(e,t)}),this.pipesByName=new Map,n.forEach(function(e){return s.pipesByName.set(e.name,e)})}return TemplateParseVisitor.prototype._reportError=function(e,t,n){void 0===n&&(n=v.ParseErrorLevel.FATAL),this.errors.push(new V(e,t,n))},TemplateParseVisitor.prototype._reportParserErors=function(e,t){for(var n=0,r=e;no.MAX_INTERPOLATION_VALUES)throw new u.BaseException(\"Only support at most \"+o.MAX_INTERPOLATION_VALUES+\" interpolation values!\");return r}catch(i){return this._reportError(\"\"+i,t),this._exprParser.wrapLiteralPrimitive(\"ERROR\",n)}},TemplateParseVisitor.prototype._parseAction=function(e,t){var n=t.start.toString();try{var r=this._exprParser.parseAction(e,n,this._interpolationConfig);return r&&this._reportParserErors(r.errors,t),!r||r.ast instanceof a.EmptyExpr?(this._reportError(\"Empty expressions are not allowed\",t),this._exprParser.wrapLiteralPrimitive(\"ERROR\",n)):(this._checkPipes(r,t),r)}catch(i){return this._reportError(\"\"+i,t),this._exprParser.wrapLiteralPrimitive(\"ERROR\",n)}},TemplateParseVisitor.prototype._parseBinding=function(e,t){var n=t.start.toString();try{var r=this._exprParser.parseBinding(e,n,this._interpolationConfig);return r&&this._reportParserErors(r.errors,t),this._checkPipes(r,t),r}catch(i){return this._reportError(\"\"+i,t),this._exprParser.wrapLiteralPrimitive(\"ERROR\",n)}},TemplateParseVisitor.prototype._parseTemplateBindings=function(e,t){var n=this,r=t.start.toString();try{var i=this._exprParser.parseTemplateBindings(e,r);return this._reportParserErors(i.errors,t),i.templateBindings.forEach(function(e){p.isPresent(e.expression)&&n._checkPipes(e.expression,t)}),i.warnings.forEach(function(e){n._reportError(e,t,v.ParseErrorLevel.WARNING)}),i.templateBindings}catch(o){return this._reportError(\"\"+o,t),[]}},TemplateParseVisitor.prototype._checkPipes=function(e,t){var n=this;if(p.isPresent(e)){var r=new q;e.visit(r),r.pipes.forEach(function(e){n.pipesByName.has(e)||n._reportError(\"The pipe '\"+e+\"' could not be found\",t)})}},TemplateParseVisitor.prototype.visitExpansion=function(e,t){return null},TemplateParseVisitor.prototype.visitExpansionCase=function(e,t){return null},TemplateParseVisitor.prototype.visitText=function(e,t){var n=t.findNgContentIndex(N),r=this._parseInterpolation(e.value,e.sourceSpan);return p.isPresent(r)?new E.BoundTextAst(r,n,e.sourceSpan):new E.TextAst(e.value,n,e.sourceSpan)},TemplateParseVisitor.prototype.visitAttribute=function(e,t){return new E.AttrAst(e.name,e.value,e.sourceSpan)},TemplateParseVisitor.prototype.visitComment=function(e,t){return null},TemplateParseVisitor.prototype.visitElement=function(e,t){var n=this,r=e.name,i=R.preparseElement(e);if(i.type===R.PreparsedElementType.SCRIPT||i.type===R.PreparsedElementType.STYLE)return null;if(i.type===R.PreparsedElementType.STYLESHEET&&S.isStyleUrlResolvable(i.hrefAttr))return null;var o=[],s=[],a=[],l=[],c=[],u=[],d=[],f=[],m=[],g=!1,v=[],_=y.splitNsName(r.toLowerCase())[1],C=_==P;e.attrs.forEach(function(e){var t=n._parseAttr(C,e,o,s,c,u,a,l),r=n._parseInlineTemplateBinding(e,f,d,m);r&&g&&n._reportError(\"Can't have multiple template bindings on one element. Use only one attribute named 'template' or prefixed with *\",e.sourceSpan),t||r||(v.push(n.visitAttribute(e,null)),o.push([e.name,e.value])),r&&(g=!0)});var T=createElementCssSelector(r,o),x=this._parseDirectives(this.selectorMatcher,T),M=[],k=this._createDirectiveAsts(C,e.name,x,s,a,e.sourceSpan,M),I=this._createElementPropertyAsts(e.name,s,k).concat(c),A=t.isTemplateElement||g,O=new b.ProviderElementContext(this.providerViewContext,t.providerContext,A,k,v,M,e.sourceSpan),D=h.visitAll(i.nonBindable?G:this,e.children,U.create(C,k,C?t.providerContext:O));O.afterElement();var N,V=p.isPresent(i.projectAs)?w.CssSelector.parse(i.projectAs)[0]:T,L=t.findNgContentIndex(V);if(i.type===R.PreparsedElementType.NG_CONTENT)p.isPresent(e.children)&&e.children.length>0&&this._reportError(\" element cannot have content. must be immediately followed by \",e.sourceSpan),N=new E.NgContentAst((this.ngContentCount++),g?null:L,e.sourceSpan);else if(C)this._assertAllEventsPublishedByDirectives(k,u),this._assertNoComponentsNorElementBindingsOnTemplate(k,I,e.sourceSpan),N=new E.EmbeddedTemplateAst(v,u,M,l,O.transformedDirectiveAsts,O.transformProviders,O.transformedHasViewContainer,D,g?null:L,e.sourceSpan);else{this._assertOnlyOneComponent(k,e.sourceSpan);var F=g?null:t.findNgContentIndex(V);N=new E.ElementAst(r,v,I,u,M,O.transformedDirectiveAsts,O.transformProviders,O.transformedHasViewContainer,D,g?null:F,e.sourceSpan)}if(g){var j=createElementCssSelector(P,f),B=this._parseDirectives(this.selectorMatcher,j),W=this._createDirectiveAsts(!0,e.name,B,d,[],e.sourceSpan,[]),H=this._createElementPropertyAsts(e.name,d,W);this._assertNoComponentsNorElementBindingsOnTemplate(W,H,e.sourceSpan);var z=new b.ProviderElementContext(this.providerViewContext,t.providerContext,t.isTemplateElement,W,[],[],e.sourceSpan);z.afterElement(),N=new E.EmbeddedTemplateAst([],[],[],m,z.transformedDirectiveAsts,z.transformProviders,z.transformedHasViewContainer,[N],L,e.sourceSpan)}return N},TemplateParseVisitor.prototype._parseInlineTemplateBinding=function(e,t,n,r){var i=null;if(this._normalizeAttributeName(e.name)==x)i=e.value;else if(e.name.startsWith(M)){var o=e.name.substring(M.length);i=0==e.value.length?o:o+\" \"+e.value}if(p.isPresent(i)){for(var s=this._parseTemplateBindings(i,e.sourceSpan),a=0;a elements is deprecated. Use \"let-\" instead!',t.sourceSpan,v.ParseErrorLevel.WARNING),this._parseVariable(h,c,t.sourceSpan,a)):(this._reportError('\"var-\" on non